diff --git a/_unit_tests_2compat_8hpp_source.html b/_unit_tests_2compat_8hpp_source.html index 745537584..66b4b0bb1 100644 --- a/_unit_tests_2compat_8hpp_source.html +++ b/_unit_tests_2compat_8hpp_source.html @@ -170,7 +170,7 @@ $(document).ready(function() { init_codefold(0); }); diff --git a/annotated.html b/annotated.html index 83ac4d0ea..2eaa02667 100644 --- a/annotated.html +++ b/annotated.html @@ -236,7 +236,7 @@ $(function() { diff --git a/base64_8hpp_source.html b/base64_8hpp_source.html index 6d2e28483..7ea5602d7 100644 --- a/base64_8hpp_source.html +++ b/base64_8hpp_source.html @@ -534,15 +534,15 @@ $(document).ready(function() { init_codefold(0); });
stdex::base64_writer::encode
void encode()
Encodes one complete internal buffer of data.
Definition base64.hpp:219
stdex::base64_writer::encode
void encode(size_t size)
Encodes partial internal buffer of data.
Definition base64.hpp:232
stdex::base64_writer::write
virtual size_t write(_In_reads_bytes_opt_(length) const void *data, size_t length)
Writes block of data to the stream.
Definition base64.hpp:190
-
stdex::stream::basic
‍UTF-8 byte-order-mark
Definition stream.hpp:78
-
stdex::stream::basic::ok
bool ok() const
Returns true if the stream state is clean i.e. previous operation was succesful.
Definition stream.hpp:174
-
stdex::stream::basic::state
state_t state() const
Returns stream state after last operation.
Definition stream.hpp:169
-
stdex::stream::basic::write_array
size_t write_array(_In_reads_bytes_opt_(size *count) const void *array, size_t size, size_t count)
Writes an array of data to the stream.
Definition stream.hpp:399
-
stdex::stream::converter
Modifies data on the fly when reading from/writing to a source stream. Could also be used to modify r...
Definition stream.hpp:1021
+
stdex::stream::basic
‍UTF-8 byte-order-mark
Definition stream.hpp:79
+
stdex::stream::basic::ok
bool ok() const
Returns true if the stream state is clean i.e. previous operation was succesful.
Definition stream.hpp:175
+
stdex::stream::basic::state
state_t state() const
Returns stream state after last operation.
Definition stream.hpp:170
+
stdex::stream::basic::write_array
size_t write_array(_In_reads_bytes_opt_(size *count) const void *array, size_t size, size_t count)
Writes an array of data to the stream.
Definition stream.hpp:400
+
stdex::stream::converter
Modifies data on the fly when reading from/writing to a source stream. Could also be used to modify r...
Definition stream.hpp:1022
diff --git a/chrono_8hpp_source.html b/chrono_8hpp_source.html index a4011ab2a..d01392237 100644 --- a/chrono_8hpp_source.html +++ b/chrono_8hpp_source.html @@ -466,7 +466,7 @@ $(document).ready(function() { init_codefold(0); }); diff --git a/classes.html b/classes.html index ff6615356..c26d27161 100644 --- a/classes.html +++ b/classes.html @@ -130,7 +130,7 @@ $(function() { diff --git a/classstdex_1_1base64__dec-members.html b/classstdex_1_1base64__dec-members.html index f1cdc3b84..0468ac7cf 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 f55d324cc..1a7407a35 100644 --- a/classstdex_1_1base64__dec.html +++ b/classstdex_1_1base64__dec.html @@ -239,7 +239,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 acff28915..fda23de97 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 e391983cb..5f0cae5a3 100644 --- a/classstdex_1_1base64__enc.html +++ b/classstdex_1_1base64__enc.html @@ -244,7 +244,7 @@ template<class _Elem , class _Traits , class _Ax > diff --git a/classstdex_1_1base64__reader-members.html b/classstdex_1_1base64__reader-members.html index 5628723d7..ef10c1b7c 100644 --- a/classstdex_1_1base64__reader-members.html +++ b/classstdex_1_1base64__reader-members.html @@ -162,7 +162,7 @@ $(function() { diff --git a/classstdex_1_1base64__reader.html b/classstdex_1_1base64__reader.html index 713ee1fd9..add2ef773 100644 --- a/classstdex_1_1base64__reader.html +++ b/classstdex_1_1base64__reader.html @@ -443,7 +443,7 @@ size_t m_num diff --git a/classstdex_1_1base64__writer-members.html b/classstdex_1_1base64__writer-members.html index 1920856d5..a4d8a8774 100644 --- a/classstdex_1_1base64__writer-members.html +++ b/classstdex_1_1base64__writer-members.html @@ -164,7 +164,7 @@ $(function() { diff --git a/classstdex_1_1base64__writer.html b/classstdex_1_1base64__writer.html index eafea4f81..f0582268d 100644 --- a/classstdex_1_1base64__writer.html +++ b/classstdex_1_1base64__writer.html @@ -450,7 +450,7 @@ size_t m_num diff --git a/classstdex_1_1basic__hash-members.html b/classstdex_1_1basic__hash-members.html index 20519a831..95c1a6889 100644 --- a/classstdex_1_1basic__hash-members.html +++ b/classstdex_1_1basic__hash-members.html @@ -90,7 +90,7 @@ $(function() { diff --git a/classstdex_1_1basic__hash.html b/classstdex_1_1basic__hash.html index e58f4dd98..8a4a16d68 100644 --- a/classstdex_1_1basic__hash.html +++ b/classstdex_1_1basic__hash.html @@ -255,7 +255,7 @@ template<class T > diff --git a/classstdex_1_1block__hash-members.html b/classstdex_1_1block__hash-members.html index da421ba0f..207a5a986 100644 --- a/classstdex_1_1block__hash-members.html +++ b/classstdex_1_1block__hash-members.html @@ -94,7 +94,7 @@ $(function() { diff --git a/classstdex_1_1block__hash.html b/classstdex_1_1block__hash.html index 82d034238..1cc8a6b9d 100644 --- a/classstdex_1_1block__hash.html +++ b/classstdex_1_1block__hash.html @@ -245,7 +245,7 @@ template<class T > diff --git a/classstdex_1_1charset__encoder-members.html b/classstdex_1_1charset__encoder-members.html index 91731849a..e7de8950a 100644 --- a/classstdex_1_1charset__encoder-members.html +++ b/classstdex_1_1charset__encoder-members.html @@ -102,7 +102,7 @@ $(function() { diff --git a/classstdex_1_1charset__encoder.html b/classstdex_1_1charset__encoder.html index a1e7a4fdf..c77f0bfd4 100644 --- a/classstdex_1_1charset__encoder.html +++ b/classstdex_1_1charset__encoder.html @@ -607,7 +607,7 @@ template<class _Traits_to = std::char_traits<T_to>, class _Alloc_to = diff --git a/classstdex_1_1crc32__hash-members.html b/classstdex_1_1crc32__hash-members.html index b60c92051..0e7512e7d 100644 --- a/classstdex_1_1crc32__hash-members.html +++ b/classstdex_1_1crc32__hash-members.html @@ -90,7 +90,7 @@ $(function() { diff --git a/classstdex_1_1crc32__hash.html b/classstdex_1_1crc32__hash.html index 5aaf6d241..b797ed7b3 100644 --- a/classstdex_1_1crc32__hash.html +++ b/classstdex_1_1crc32__hash.html @@ -245,7 +245,7 @@ crc32_t m_value diff --git a/classstdex_1_1global__progress-members.html b/classstdex_1_1global__progress-members.html index e3319d922..e6f3042ba 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 48722484c..2cb090ee7 100644 --- a/classstdex_1_1global__progress.html +++ b/classstdex_1_1global__progress.html @@ -547,7 +547,7 @@ template<class T > diff --git a/classstdex_1_1hex__dec-members.html b/classstdex_1_1hex__dec-members.html index 070432e10..ce29138dd 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 9c84d53e8..849377102 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 ce876f593..de6ca6490 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 af4ae3d0e..20ab35a0a 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 14254f71e..2f0715da3 100644 --- a/classstdex_1_1idrec_1_1record-members.html +++ b/classstdex_1_1idrec_1_1record-members.html @@ -100,7 +100,7 @@ $(function() { diff --git a/classstdex_1_1idrec_1_1record.html b/classstdex_1_1idrec_1_1record.html index db3235759..4434c6e8a 100644 --- a/classstdex_1_1idrec_1_1record.html +++ b/classstdex_1_1idrec_1_1record.html @@ -837,7 +837,7 @@ template<class T , class T_ID , const T_ID ID, class T_SIZE , T_SIZE ALIGN> diff --git a/classstdex_1_1lazy__progress-members.html b/classstdex_1_1lazy__progress-members.html index e2063ed31..1a55efb5e 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 ba472a5b7..d0a4f2cad 100644 --- a/classstdex_1_1lazy__progress.html +++ b/classstdex_1_1lazy__progress.html @@ -131,9 +131,9 @@ Protected Attributes std::chrono::nanoseconds m_timeout   - -std::chrono::steady_clock::time_point m_last -  + +std::chrono::system_clock::time_point m_lastm_start   @@ -279,7 +279,7 @@ template<class T > diff --git a/classstdex_1_1md5__hash-members.html b/classstdex_1_1md5__hash-members.html index c269910ce..e4eb3f316 100644 --- a/classstdex_1_1md5__hash-members.html +++ b/classstdex_1_1md5__hash-members.html @@ -93,7 +93,7 @@ $(function() { diff --git a/classstdex_1_1md5__hash.html b/classstdex_1_1md5__hash.html index 1d6ad455d..148a04d34 100644 --- a/classstdex_1_1md5__hash.html +++ b/classstdex_1_1md5__hash.html @@ -259,7 +259,7 @@ uint32_t m_temp [16] diff --git a/classstdex_1_1parser_1_1basic__angle-members.html b/classstdex_1_1parser_1_1basic__angle-members.html index 20119411e..7d35a54c5 100644 --- a/classstdex_1_1parser_1_1basic__angle-members.html +++ b/classstdex_1_1parser_1_1basic__angle-members.html @@ -85,7 +85,7 @@ $(function() { decimal (defined in stdex::parser::basic_angle< T >)stdex::parser::basic_angle< T > degree (defined in stdex::parser::basic_angle< T >)stdex::parser::basic_angle< T > degree_separator (defined in stdex::parser::basic_angle< T >)stdex::parser::basic_angle< T > - intervalstdex::parser::basic_parser< T > + intervalstdex::parser::basic_parser< T > invalidate() (defined in stdex::parser::basic_angle< T >)stdex::parser::basic_angle< T >inlinevirtual m_locale (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >protected match(_In_reads_or_z_(end) const T *text, size_t start=0, size_t end=(size_t) -1, int flags=match_default) (defined in stdex::parser::basic_angle< T >)stdex::parser::basic_angle< T >inlinevirtual @@ -99,7 +99,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__angle.html b/classstdex_1_1parser_1_1basic__angle.html index 86b69e833..e48fe4170 100644 --- a/classstdex_1_1parser_1_1basic__angle.html +++ b/classstdex_1_1parser_1_1basic__angle.html @@ -141,10 +141,10 @@ std::shared_ptr< basic_parser< T > > decimal   - Public Attributes inherited from stdex::parser::basic_parser< T > - -interval< size_tinterval - Region of the last match.
-  + +stdex::interval< size_tinterval + Region of the last match.
+  @@ -244,7 +244,7 @@ template<clas diff --git a/classstdex_1_1parser_1_1basic__any__cu-members.html b/classstdex_1_1parser_1_1basic__any__cu-members.html index 936ad28e1..fc4a66eb8 100644 --- a/classstdex_1_1parser_1_1basic__any__cu-members.html +++ b/classstdex_1_1parser_1_1basic__any__cu-members.html @@ -82,7 +82,7 @@ $(function() {

Additional Inherited Members

- + @@ -92,7 +92,7 @@ $(function() {
basic_any_cu(const std::locale &locale=std::locale()) (defined in stdex::parser::basic_any_cu< T >)stdex::parser::basic_any_cu< T >inline
basic_parser(const std::locale &locale=std::locale()) (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inline
intervalstdex::parser::basic_parser< T >
intervalstdex::parser::basic_parser< T >
invalidate() (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inlinevirtual
m_locale (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >protected
match(_In_reads_or_z_(end) const T *text, size_t start=0, size_t end=(size_t) -1, int flags=match_default) (defined in stdex::parser::basic_any_cu< T >)stdex::parser::basic_any_cu< T >inlinevirtual
diff --git a/classstdex_1_1parser_1_1basic__any__cu.html b/classstdex_1_1parser_1_1basic__any__cu.html index db970b0be..05224f1ff 100644 --- a/classstdex_1_1parser_1_1basic__any__cu.html +++ b/classstdex_1_1parser_1_1basic__any__cu.html @@ -120,10 +120,10 @@ template<clas

Additional Inherited Members

- Public Attributes inherited from stdex::parser::basic_parser< T > - -interval< size_tinterval - Region of the last match.
-  + +stdex::interval< size_tinterval + Region of the last match.
- Protected Attributes inherited from stdex::parser::basic_parser< T > std::locale m_locale @@ -191,7 +191,7 @@ template<clas diff --git a/classstdex_1_1parser_1_1basic__bol-members.html b/classstdex_1_1parser_1_1basic__bol-members.html index f33c7e320..9b17f985e 100644 --- a/classstdex_1_1parser_1_1basic__bol-members.html +++ b/classstdex_1_1parser_1_1basic__bol-members.html @@ -82,7 +82,7 @@ $(function() { - + @@ -93,7 +93,7 @@ $(function() {
basic_bol(bool invert=false) (defined in stdex::parser::basic_bol< T >)stdex::parser::basic_bol< T >inline
basic_parser(const std::locale &locale=std::locale()) (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inline
intervalstdex::parser::basic_parser< T >
intervalstdex::parser::basic_parser< T >
invalidate() (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inlinevirtual
m_invert (defined in stdex::parser::basic_bol< T >)stdex::parser::basic_bol< T >protected
m_locale (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >protected
diff --git a/classstdex_1_1parser_1_1basic__bol.html b/classstdex_1_1parser_1_1basic__bol.html index fb35b20a4..e0269f0e8 100644 --- a/classstdex_1_1parser_1_1basic__bol.html +++ b/classstdex_1_1parser_1_1basic__bol.html @@ -131,10 +131,10 @@ std::locale m_locale

Additional Inherited Members

- Public Attributes inherited from stdex::parser::basic_parser< T > - -interval< size_tinterval - Region of the last match.
-  + +stdex::interval< size_tinterval + Region of the last match.

Detailed Description

template<class T>
@@ -198,7 +198,7 @@ template<clas
diff --git a/classstdex_1_1parser_1_1basic__branch-members.html b/classstdex_1_1parser_1_1basic__branch-members.html index c34439f24..22bf3e634 100644 --- a/classstdex_1_1parser_1_1basic__branch-members.html +++ b/classstdex_1_1parser_1_1basic__branch-members.html @@ -85,7 +85,7 @@ $(function() { basic_branch(std::vector< std::shared_ptr< basic_parser< T > > > &&collection, const std::locale &locale=std::locale()) (defined in stdex::parser::basic_branch< T >)stdex::parser::basic_branch< T >inline basic_parser(const std::locale &locale=std::locale()) (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inline hit_offset (defined in stdex::parser::basic_branch< T >)stdex::parser::basic_branch< T > - intervalstdex::parser::basic_parser< T > + intervalstdex::parser::basic_parser< T > invalidate() (defined in stdex::parser::basic_branch< T >)stdex::parser::basic_branch< T >inlinevirtual m_collection (defined in stdex::parser::parser_collection< T >)stdex::parser::parser_collection< T >protected m_locale (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >protected @@ -99,7 +99,7 @@ $(function() {
diff --git a/classstdex_1_1parser_1_1basic__branch.html b/classstdex_1_1parser_1_1basic__branch.html index 01559fe6c..16de398c6 100644 --- a/classstdex_1_1parser_1_1basic__branch.html +++ b/classstdex_1_1parser_1_1basic__branch.html @@ -136,10 +136,10 @@ Public Attributes size_t hit_offset   - Public Attributes inherited from stdex::parser::basic_parser< T > - -interval< size_tinterval - Region of the last match.
-  + +stdex::interval< size_tinterval + Region of the last match.
+  @@ -253,7 +253,7 @@ template<clas diff --git a/classstdex_1_1parser_1_1basic__chemical__formula-members.html b/classstdex_1_1parser_1_1basic__chemical__formula-members.html index 56c342454..20f46e2f5 100644 --- a/classstdex_1_1parser_1_1basic__chemical__formula-members.html +++ b/classstdex_1_1parser_1_1basic__chemical__formula-members.html @@ -84,7 +84,7 @@ $(function() { - + @@ -97,7 +97,7 @@ $(function() {

Protected Member Functions

basic_parser(const std::locale &locale=std::locale()) (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inline
has_charge (defined in stdex::parser::basic_chemical_formula< T >)stdex::parser::basic_chemical_formula< T >
has_digits (defined in stdex::parser::basic_chemical_formula< T >)stdex::parser::basic_chemical_formula< T >
intervalstdex::parser::basic_parser< T >
intervalstdex::parser::basic_parser< T >
invalidate() (defined in stdex::parser::basic_chemical_formula< T >)stdex::parser::basic_chemical_formula< T >inlinevirtual
m_digit (defined in stdex::parser::basic_chemical_formula< T >)stdex::parser::basic_chemical_formula< T >protected
m_element (defined in stdex::parser::basic_chemical_formula< T >)stdex::parser::basic_chemical_formula< T >protected
diff --git a/classstdex_1_1parser_1_1basic__chemical__formula.html b/classstdex_1_1parser_1_1basic__chemical__formula.html index cc7ebe777..895eeac6a 100644 --- a/classstdex_1_1parser_1_1basic__chemical__formula.html +++ b/classstdex_1_1parser_1_1basic__chemical__formula.html @@ -127,10 +127,10 @@ Public Attributes bool has_charge   - Public Attributes inherited from stdex::parser::basic_parser< T > - -interval< size_tinterval - Region of the last match.
-  + +stdex::interval< size_tinterval + Region of the last match.
+  @@ -239,7 +239,7 @@ template<clas diff --git a/classstdex_1_1parser_1_1basic__creditor__reference-members.html b/classstdex_1_1parser_1_1basic__creditor__reference-members.html index b080d10a4..5786a81aa 100644 --- a/classstdex_1_1parser_1_1basic__creditor__reference-members.html +++ b/classstdex_1_1parser_1_1basic__creditor__reference-members.html @@ -83,7 +83,7 @@ $(function() { - + @@ -96,7 +96,7 @@ $(function() {

Protected Attributes

basic_creditor_reference(const std::shared_ptr< basic_parser< T > > &space, const std::locale &locale=std::locale()) (defined in stdex::parser::basic_creditor_reference< T >)stdex::parser::basic_creditor_reference< T >inline
basic_parser(const std::locale &locale=std::locale()) (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inline
check_digitsstdex::parser::basic_creditor_reference< T >
intervalstdex::parser::basic_parser< T >
intervalstdex::parser::basic_parser< T >
invalidate() (defined in stdex::parser::basic_creditor_reference< T >)stdex::parser::basic_creditor_reference< T >inlinevirtual
is_validstdex::parser::basic_creditor_reference< T >
m_locale (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >protected
diff --git a/classstdex_1_1parser_1_1basic__creditor__reference.html b/classstdex_1_1parser_1_1basic__creditor__reference.html index d6d3916bb..a57bb706a 100644 --- a/classstdex_1_1parser_1_1basic__creditor__reference.html +++ b/classstdex_1_1parser_1_1basic__creditor__reference.html @@ -133,10 +133,10 @@ T reference [22]<  Is reference valid per ISO 7064.
  - Public Attributes inherited from stdex::parser::basic_parser< T > - -interval< size_tinterval - Region of the last match.
-  + +stdex::interval< size_tinterval + Region of the last match.
+  @@ -240,7 +240,7 @@ template<clas diff --git a/classstdex_1_1parser_1_1basic__cu-members.html b/classstdex_1_1parser_1_1basic__cu-members.html index 807f93a2d..78bba52f6 100644 --- a/classstdex_1_1parser_1_1basic__cu-members.html +++ b/classstdex_1_1parser_1_1basic__cu-members.html @@ -82,7 +82,7 @@ $(function() {

Protected Attributes

- + @@ -94,7 +94,7 @@ $(function() {
basic_cu(T chr, bool invert=false, const std::locale &locale=std::locale()) (defined in stdex::parser::basic_cu< T >)stdex::parser::basic_cu< T >inline
basic_parser(const std::locale &locale=std::locale()) (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inline
intervalstdex::parser::basic_parser< T >
intervalstdex::parser::basic_parser< T >
invalidate() (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inlinevirtual
m_chr (defined in stdex::parser::basic_cu< T >)stdex::parser::basic_cu< T >protected
m_invert (defined in stdex::parser::basic_cu< T >)stdex::parser::basic_cu< T >protected
diff --git a/classstdex_1_1parser_1_1basic__cu.html b/classstdex_1_1parser_1_1basic__cu.html index 6935dfe4b..a02a9565a 100644 --- a/classstdex_1_1parser_1_1basic__cu.html +++ b/classstdex_1_1parser_1_1basic__cu.html @@ -134,10 +134,10 @@ std::locale m_locale

Additional Inherited Members

- Public Attributes inherited from stdex::parser::basic_parser< T > - -interval< size_tinterval - Region of the last match.
-  + +stdex::interval< size_tinterval + Region of the last match.

Detailed Description

template<class T>
@@ -201,7 +201,7 @@ template<clas
diff --git a/classstdex_1_1parser_1_1basic__cu__set-members.html b/classstdex_1_1parser_1_1basic__cu__set-members.html index c58a89f04..9973d221b 100644 --- a/classstdex_1_1parser_1_1basic__cu__set-members.html +++ b/classstdex_1_1parser_1_1basic__cu__set-members.html @@ -84,7 +84,7 @@ $(function() { basic_parser(const std::locale &locale=std::locale()) (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inline basic_set(bool invert=false, const std::locale &locale=std::locale()) (defined in stdex::parser::basic_set< T >)stdex::parser::basic_set< T >inline hit_offset (defined in stdex::parser::basic_set< T >)stdex::parser::basic_set< T > - intervalstdex::parser::basic_parser< T > + intervalstdex::parser::basic_parser< T > invalidate() (defined in stdex::parser::basic_set< T >)stdex::parser::basic_set< T >inlinevirtual m_invert (defined in stdex::parser::basic_set< T >)stdex::parser::basic_set< T >protected m_locale (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >protected @@ -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 6625f0c57..2e115adbf 100644 --- a/classstdex_1_1parser_1_1basic__cu__set.html +++ b/classstdex_1_1parser_1_1basic__cu__set.html @@ -143,10 +143,10 @@ Additional Inherited Members size_t hit_offset   - Public Attributes inherited from stdex::parser::basic_parser< T > - -interval< size_tinterval - Region of the last match.
-  + +stdex::interval< size_tinterval + Region of the last match.

Detailed Description

template<class T>
@@ -210,7 +210,7 @@ template<clas
diff --git a/classstdex_1_1parser_1_1basic__date-members.html b/classstdex_1_1parser_1_1basic__date-members.html index e072d598e..2d2e32131 100644 --- a/classstdex_1_1parser_1_1basic__date-members.html +++ b/classstdex_1_1parser_1_1basic__date-members.html @@ -84,7 +84,7 @@ $(function() { basic_parser(const std::locale &locale=std::locale()) (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inline day (defined in stdex::parser::basic_date< T >)stdex::parser::basic_date< T > format (defined in stdex::parser::basic_date< T >)stdex::parser::basic_date< T > - intervalstdex::parser::basic_parser< T > + intervalstdex::parser::basic_parser< T > invalidate() (defined in stdex::parser::basic_date< T >)stdex::parser::basic_date< T >inlinevirtual is_valid(size_t day, size_t month) (defined in stdex::parser::basic_date< T >)stdex::parser::basic_date< T >inlineprotectedstatic m_format_mask (defined in stdex::parser::basic_date< T >)stdex::parser::basic_date< T >protected @@ -100,7 +100,7 @@ $(function() {
diff --git a/classstdex_1_1parser_1_1basic__date.html b/classstdex_1_1parser_1_1basic__date.html index 3cf195aa8..f5e87f15c 100644 --- a/classstdex_1_1parser_1_1basic__date.html +++ b/classstdex_1_1parser_1_1basic__date.html @@ -134,10 +134,10 @@ std::shared_ptr< basic_integer< T > > year   - Public Attributes inherited from stdex::parser::basic_parser< T > - -interval< size_tinterval - Region of the last match.
-  + +stdex::interval< size_tinterval + Region of the last match.
+  @@ -252,7 +252,7 @@ template<clas 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 bef0e9d62..02daa1838 100644 --- a/classstdex_1_1parser_1_1basic__dns__domain__char-members.html +++ b/classstdex_1_1parser_1_1basic__dns__domain__char-members.html @@ -83,7 +83,7 @@ $(function() { - + @@ -94,7 +94,7 @@ $(function() {

Static Protected Member Functions

allow_on_edgestdex::parser::basic_dns_domain_char< T >
basic_dns_domain_char(bool allow_idn, const std::locale &locale=std::locale()) (defined in stdex::parser::basic_dns_domain_char< T >)stdex::parser::basic_dns_domain_char< T >inline
basic_parser(const std::locale &locale=std::locale()) (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inline
intervalstdex::parser::basic_parser< T >
intervalstdex::parser::basic_parser< T >
invalidate() (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inlinevirtual
m_allow_idn (defined in stdex::parser::basic_dns_domain_char< T >)stdex::parser::basic_dns_domain_char< T >protected
m_locale (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >protected
diff --git a/classstdex_1_1parser_1_1basic__dns__domain__char.html b/classstdex_1_1parser_1_1basic__dns__domain__char.html index 9a30ec136..770b5d962 100644 --- a/classstdex_1_1parser_1_1basic__dns__domain__char.html +++ b/classstdex_1_1parser_1_1basic__dns__domain__char.html @@ -126,10 +126,10 @@ Public Attributes  Is character allowed at the beginning or an end of a DNS domain?
  - Public Attributes inherited from stdex::parser::basic_parser< T > - -interval< size_tinterval - Region of the last match.
-  + +stdex::interval< size_tinterval + Region of the last match.
+  @@ -203,7 +203,7 @@ template<clas diff --git a/classstdex_1_1parser_1_1basic__dns__name-members.html b/classstdex_1_1parser_1_1basic__dns__name-members.html index 6e50e217b..6792f98bb 100644 --- a/classstdex_1_1parser_1_1basic__dns__name-members.html +++ b/classstdex_1_1parser_1_1basic__dns__name-members.html @@ -82,7 +82,7 @@ $(function() {

Protected Attributes

- + @@ -95,7 +95,7 @@ $(function() {
basic_dns_name(bool allow_absolute, const std::shared_ptr< basic_dns_domain_char< T > > &domain_char, const std::shared_ptr< basic_parser< T > > &separator, const std::locale &locale=std::locale()) (defined in stdex::parser::basic_dns_name< T >)stdex::parser::basic_dns_name< T >inline
basic_parser(const std::locale &locale=std::locale()) (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inline
intervalstdex::parser::basic_parser< T >
intervalstdex::parser::basic_parser< T >
invalidate() (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inlinevirtual
m_allow_absolutestdex::parser::basic_dns_name< T >protected
m_domain_char (defined in stdex::parser::basic_dns_name< T >)stdex::parser::basic_dns_name< T >protected
diff --git a/classstdex_1_1parser_1_1basic__dns__name.html b/classstdex_1_1parser_1_1basic__dns__name.html index 003cd59d3..8f74e57e8 100644 --- a/classstdex_1_1parser_1_1basic__dns__name.html +++ b/classstdex_1_1parser_1_1basic__dns__name.html @@ -138,10 +138,10 @@ std::locale m_locale

Additional Inherited Members

- Public Attributes inherited from stdex::parser::basic_parser< T > - -interval< size_tinterval - Region of the last match.
-  + +stdex::interval< size_tinterval + Region of the last match.

Detailed Description

template<class T>
@@ -205,7 +205,7 @@ template<clas
diff --git a/classstdex_1_1parser_1_1basic__email__address-members.html b/classstdex_1_1parser_1_1basic__email__address-members.html index 21251fc78..a6548777f 100644 --- a/classstdex_1_1parser_1_1basic__email__address-members.html +++ b/classstdex_1_1parser_1_1basic__email__address-members.html @@ -83,7 +83,7 @@ $(function() { basic_email_address(const std::shared_ptr< basic_parser< T > > &_username, const std::shared_ptr< basic_parser< T > > &at, const std::shared_ptr< basic_parser< T > > &ip_lbracket, const std::shared_ptr< basic_parser< T > > &ip_rbracket, const std::shared_ptr< basic_parser< T > > &_ipv4_host, const std::shared_ptr< basic_parser< T > > &_ipv6_host, const std::shared_ptr< basic_parser< T > > &_dns_host, const std::locale &locale=std::locale()) (defined in stdex::parser::basic_email_address< T >)stdex::parser::basic_email_address< T >inline basic_parser(const std::locale &locale=std::locale()) (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inline dns_host (defined in stdex::parser::basic_email_address< T >)stdex::parser::basic_email_address< T > - intervalstdex::parser::basic_parser< T > + intervalstdex::parser::basic_parser< T > invalidate() (defined in stdex::parser::basic_email_address< T >)stdex::parser::basic_email_address< T >inlinevirtual ipv4_host (defined in stdex::parser::basic_email_address< T >)stdex::parser::basic_email_address< T > ipv6_host (defined in stdex::parser::basic_email_address< T >)stdex::parser::basic_email_address< T > @@ -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 840c6b817..628be5452 100644 --- a/classstdex_1_1parser_1_1basic__email__address.html +++ b/classstdex_1_1parser_1_1basic__email__address.html @@ -133,10 +133,10 @@ std::shared_ptr< basic_parser< T > > dns_host   - Public Attributes inherited from stdex::parser::basic_parser< T > - -interval< size_tinterval - Region of the last match.
-  + +stdex::interval< size_tinterval + Region of the last match.
+  @@ -245,7 +245,7 @@ template<clas diff --git a/classstdex_1_1parser_1_1basic__emoticon-members.html b/classstdex_1_1parser_1_1basic__emoticon-members.html index ae3af1886..b8ad9e91c 100644 --- a/classstdex_1_1parser_1_1basic__emoticon-members.html +++ b/classstdex_1_1parser_1_1basic__emoticon-members.html @@ -85,7 +85,7 @@ $(function() { - + @@ -97,7 +97,7 @@ $(function() {

Protected Attributes

basic_parser(const std::locale &locale=std::locale()) (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inline
emoticonstdex::parser::basic_emoticon< T >
eyesstdex::parser::basic_emoticon< T >
intervalstdex::parser::basic_parser< T >
intervalstdex::parser::basic_parser< T >
invalidate() (defined in stdex::parser::basic_emoticon< T >)stdex::parser::basic_emoticon< T >inlinevirtual
m_locale (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >protected
match(_In_reads_or_z_(end) const T *text, size_t start=0, size_t end=(size_t) -1, int flags=match_default) (defined in stdex::parser::basic_emoticon< T >)stdex::parser::basic_emoticon< T >inlinevirtual
diff --git a/classstdex_1_1parser_1_1basic__emoticon.html b/classstdex_1_1parser_1_1basic__emoticon.html index 5417dac27..c33785015 100644 --- a/classstdex_1_1parser_1_1basic__emoticon.html +++ b/classstdex_1_1parser_1_1basic__emoticon.html @@ -140,10 +140,10 @@ std::shared_ptr<  mouth (e.g. ), ), (, (, |, P, D, p, d)
  - Public Attributes inherited from
stdex::parser::basic_parser< T > - -interval< size_tinterval - Region of the last match.
-  + +stdex::interval< size_tinterval + Region of the last match.
+  @@ -243,7 +243,7 @@ template<clas diff --git a/classstdex_1_1parser_1_1basic__eol-members.html b/classstdex_1_1parser_1_1basic__eol-members.html index 6b31e11e8..34dc9803c 100644 --- a/classstdex_1_1parser_1_1basic__eol-members.html +++ b/classstdex_1_1parser_1_1basic__eol-members.html @@ -82,7 +82,7 @@ $(function() {

Additional Inherited Members

- + @@ -93,7 +93,7 @@ $(function() {
basic_eol(bool invert=false) (defined in stdex::parser::basic_eol< T >)stdex::parser::basic_eol< T >inline
basic_parser(const std::locale &locale=std::locale()) (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inline
intervalstdex::parser::basic_parser< T >
intervalstdex::parser::basic_parser< T >
invalidate() (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inlinevirtual
m_invert (defined in stdex::parser::basic_eol< T >)stdex::parser::basic_eol< T >protected
m_locale (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >protected
diff --git a/classstdex_1_1parser_1_1basic__eol.html b/classstdex_1_1parser_1_1basic__eol.html index f10816f5c..3bf6014fd 100644 --- a/classstdex_1_1parser_1_1basic__eol.html +++ b/classstdex_1_1parser_1_1basic__eol.html @@ -131,10 +131,10 @@ std::locale m_locale

Additional Inherited Members

- Public Attributes inherited from stdex::parser::basic_parser< T > - -interval< size_tinterval - Region of the last match.
-  + +stdex::interval< size_tinterval + Region of the last match.

Detailed Description

template<class T>
@@ -198,7 +198,7 @@ template<clas
diff --git a/classstdex_1_1parser_1_1basic__fraction-members.html b/classstdex_1_1parser_1_1basic__fraction-members.html index 9a8dea0e9..da4c7b1dd 100644 --- a/classstdex_1_1parser_1_1basic__fraction-members.html +++ b/classstdex_1_1parser_1_1basic__fraction-members.html @@ -84,7 +84,7 @@ $(function() { basic_parser(const std::locale &locale=std::locale()) (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inline denominator (defined in stdex::parser::basic_fraction< T >)stdex::parser::basic_fraction< T > fraction_line (defined in stdex::parser::basic_fraction< T >)stdex::parser::basic_fraction< T > - intervalstdex::parser::basic_parser< T > + intervalstdex::parser::basic_parser< T > invalidate() (defined in stdex::parser::basic_fraction< T >)stdex::parser::basic_fraction< T >inlinevirtual m_locale (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >protected match(_In_reads_or_z_(end) const T *text, size_t start=0, size_t end=(size_t) -1, int flags=match_default) (defined in stdex::parser::basic_fraction< T >)stdex::parser::basic_fraction< T >inlinevirtual @@ -95,7 +95,7 @@ $(function() {
diff --git a/classstdex_1_1parser_1_1basic__fraction.html b/classstdex_1_1parser_1_1basic__fraction.html index 9e95c1fbc..54590e2d4 100644 --- a/classstdex_1_1parser_1_1basic__fraction.html +++ b/classstdex_1_1parser_1_1basic__fraction.html @@ -129,10 +129,10 @@ std::shared_ptr< basic_parser< T > > denominator   - Public Attributes inherited from stdex::parser::basic_parser< T > - -interval< size_tinterval - Region of the last match.
-  + +stdex::interval< size_tinterval + Region of the last match.
+  @@ -232,7 +232,7 @@ template<clas diff --git a/classstdex_1_1parser_1_1basic__iban-members.html b/classstdex_1_1parser_1_1basic__iban-members.html index 32ed5570e..2f6abbcc6 100644 --- a/classstdex_1_1parser_1_1basic__iban-members.html +++ b/classstdex_1_1parser_1_1basic__iban-members.html @@ -85,7 +85,7 @@ $(function() { - + @@ -97,7 +97,7 @@ $(function() {

Additional Inherited Members

bbanstdex::parser::basic_iban< T >
check_digitsstdex::parser::basic_iban< T >
countrystdex::parser::basic_iban< T >
intervalstdex::parser::basic_parser< T >
intervalstdex::parser::basic_parser< T >
invalidate() (defined in stdex::parser::basic_iban< T >)stdex::parser::basic_iban< T >inlinevirtual
is_validstdex::parser::basic_iban< T >
m_locale (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >protected
diff --git a/classstdex_1_1parser_1_1basic__iban.html b/classstdex_1_1parser_1_1basic__iban.html index fa9c44e32..9aa64d0aa 100644 --- a/classstdex_1_1parser_1_1basic__iban.html +++ b/classstdex_1_1parser_1_1basic__iban.html @@ -137,10 +137,10 @@ T bban [31]  Is IBAN valid per ISO 7064.
  - Public Attributes inherited from stdex::parser::basic_parser< T > - -interval< size_tinterval - Region of the last match.
-  + +stdex::interval< size_tinterval + Region of the last match.
+  @@ -244,7 +244,7 @@ template<clas diff --git a/classstdex_1_1parser_1_1basic__integer-members.html b/classstdex_1_1parser_1_1basic__integer-members.html index 52349b1e1..3f7450fbb 100644 --- a/classstdex_1_1parser_1_1basic__integer-members.html +++ b/classstdex_1_1parser_1_1basic__integer-members.html @@ -82,7 +82,7 @@ $(function() {

Protected Attributes

- + @@ -93,7 +93,7 @@ $(function() {
basic_integer(const std::locale &locale=std::locale()) (defined in stdex::parser::basic_integer< T >)stdex::parser::basic_integer< T >inline
basic_parser(const std::locale &locale=std::locale()) (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inline
intervalstdex::parser::basic_parser< T >
intervalstdex::parser::basic_parser< T >
invalidate() (defined in stdex::parser::basic_integer< T >)stdex::parser::basic_integer< T >inlinevirtual
m_locale (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >protected
match(_In_reads_or_z_(end) const T *text, size_t start=0, size_t end=(size_t) -1, int flags=match_default)=0 (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >pure virtual
diff --git a/classstdex_1_1parser_1_1basic__integer.html b/classstdex_1_1parser_1_1basic__integer.html index ff71343ca..cb31c4c24 100644 --- a/classstdex_1_1parser_1_1basic__integer.html +++ b/classstdex_1_1parser_1_1basic__integer.html @@ -129,10 +129,10 @@ Public Attributes  Calculated value of the numeral.
  - Public Attributes inherited from stdex::parser::basic_parser< T > - -interval< size_tinterval - Region of the last match.
-  + +stdex::interval< size_tinterval + Region of the last match.
+  @@ -180,7 +180,7 @@ template<clas diff --git a/classstdex_1_1parser_1_1basic__integer10-members.html b/classstdex_1_1parser_1_1basic__integer10-members.html index e0cdbca31..5c6a9ed37 100644 --- a/classstdex_1_1parser_1_1basic__integer10-members.html +++ b/classstdex_1_1parser_1_1basic__integer10-members.html @@ -83,7 +83,7 @@ $(function() { - + @@ -104,7 +104,7 @@ $(function() {

Additional Inherited Members

basic_integer(const std::locale &locale=std::locale()) (defined in stdex::parser::basic_integer< T >)stdex::parser::basic_integer< T >inline
basic_integer10(const std::shared_ptr< basic_parser< T > > &digit_0, const std::shared_ptr< basic_parser< T > > &digit_1, const std::shared_ptr< basic_parser< T > > &digit_2, const std::shared_ptr< basic_parser< T > > &digit_3, const std::shared_ptr< basic_parser< T > > &digit_4, const std::shared_ptr< basic_parser< T > > &digit_5, const std::shared_ptr< basic_parser< T > > &digit_6, const std::shared_ptr< basic_parser< T > > &digit_7, const std::shared_ptr< basic_parser< T > > &digit_8, const std::shared_ptr< basic_parser< T > > &digit_9, const std::locale &locale=std::locale()) (defined in stdex::parser::basic_integer10< T >)stdex::parser::basic_integer10< T >inline
basic_parser(const std::locale &locale=std::locale()) (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inline
intervalstdex::parser::basic_parser< T >
intervalstdex::parser::basic_parser< T >
invalidate() (defined in stdex::parser::basic_integer< T >)stdex::parser::basic_integer< T >inlinevirtual
m_digit_0 (defined in stdex::parser::basic_integer10< T >)stdex::parser::basic_integer10< T >protected
m_digit_1 (defined in stdex::parser::basic_integer10< T >)stdex::parser::basic_integer10< T >protected
diff --git a/classstdex_1_1parser_1_1basic__integer10.html b/classstdex_1_1parser_1_1basic__integer10.html index b4aa25733..a566ec237 100644 --- a/classstdex_1_1parser_1_1basic__integer10.html +++ b/classstdex_1_1parser_1_1basic__integer10.html @@ -167,10 +167,10 @@ Additional Inherited Members  Calculated value of the numeral.
  - Public Attributes inherited from stdex::parser::basic_parser< T > - -interval< size_tinterval - Region of the last match.
-  + +stdex::interval< size_tinterval + Region of the last match.

Detailed Description

template<class T>
@@ -234,7 +234,7 @@ template<clas
diff --git a/classstdex_1_1parser_1_1basic__integer10ts-members.html b/classstdex_1_1parser_1_1basic__integer10ts-members.html index 0d70c9f74..807460898 100644 --- a/classstdex_1_1parser_1_1basic__integer10ts-members.html +++ b/classstdex_1_1parser_1_1basic__integer10ts-members.html @@ -85,7 +85,7 @@ $(function() { basic_parser(const std::locale &locale=std::locale()) (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inline digit_countstdex::parser::basic_integer10ts< T > has_separatorsstdex::parser::basic_integer10ts< T > - intervalstdex::parser::basic_parser< T > + intervalstdex::parser::basic_parser< T > invalidate() (defined in stdex::parser::basic_integer10ts< T >)stdex::parser::basic_integer10ts< T >inlinevirtual m_digits (defined in stdex::parser::basic_integer10ts< T >)stdex::parser::basic_integer10ts< T >protected m_locale (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >protected @@ -98,7 +98,7 @@ $(function() {
diff --git a/classstdex_1_1parser_1_1basic__integer10ts.html b/classstdex_1_1parser_1_1basic__integer10ts.html index f9a0c6bb7..faa3f60db 100644 --- a/classstdex_1_1parser_1_1basic__integer10ts.html +++ b/classstdex_1_1parser_1_1basic__integer10ts.html @@ -139,10 +139,10 @@ Public Attributes  Calculated value of the numeral.
  - Public Attributes inherited from stdex::parser::basic_parser< T > - -interval< size_tinterval - Region of the last match.
-  + +stdex::interval< size_tinterval + Region of the last match.
+  @@ -248,7 +248,7 @@ template<clas diff --git a/classstdex_1_1parser_1_1basic__integer16-members.html b/classstdex_1_1parser_1_1basic__integer16-members.html index e67975a99..610ffc187 100644 --- a/classstdex_1_1parser_1_1basic__integer16-members.html +++ b/classstdex_1_1parser_1_1basic__integer16-members.html @@ -83,7 +83,7 @@ $(function() { - + @@ -110,7 +110,7 @@ $(function() {

Protected Attributes

basic_integer(const std::locale &locale=std::locale()) (defined in stdex::parser::basic_integer< T >)stdex::parser::basic_integer< T >inline
basic_integer16(const std::shared_ptr< basic_parser< T > > &digit_0, const std::shared_ptr< basic_parser< T > > &digit_1, const std::shared_ptr< basic_parser< T > > &digit_2, const std::shared_ptr< basic_parser< T > > &digit_3, const std::shared_ptr< basic_parser< T > > &digit_4, const std::shared_ptr< basic_parser< T > > &digit_5, const std::shared_ptr< basic_parser< T > > &digit_6, const std::shared_ptr< basic_parser< T > > &digit_7, const std::shared_ptr< basic_parser< T > > &digit_8, const std::shared_ptr< basic_parser< T > > &digit_9, const std::shared_ptr< basic_parser< T > > &digit_10, const std::shared_ptr< basic_parser< T > > &digit_11, const std::shared_ptr< basic_parser< T > > &digit_12, const std::shared_ptr< basic_parser< T > > &digit_13, const std::shared_ptr< basic_parser< T > > &digit_14, const std::shared_ptr< basic_parser< T > > &digit_15, const std::locale &locale=std::locale()) (defined in stdex::parser::basic_integer16< T >)stdex::parser::basic_integer16< T >inline
basic_parser(const std::locale &locale=std::locale()) (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inline
intervalstdex::parser::basic_parser< T >
intervalstdex::parser::basic_parser< T >
invalidate() (defined in stdex::parser::basic_integer< T >)stdex::parser::basic_integer< T >inlinevirtual
m_digit_0 (defined in stdex::parser::basic_integer16< T >)stdex::parser::basic_integer16< T >protected
m_digit_1 (defined in stdex::parser::basic_integer16< T >)stdex::parser::basic_integer16< T >protected
diff --git a/classstdex_1_1parser_1_1basic__integer16.html b/classstdex_1_1parser_1_1basic__integer16.html index c61f13af5..7bbf7b233 100644 --- a/classstdex_1_1parser_1_1basic__integer16.html +++ b/classstdex_1_1parser_1_1basic__integer16.html @@ -185,10 +185,10 @@ Additional Inherited Members  Calculated value of the numeral.
  - Public Attributes inherited from stdex::parser::basic_parser< T > - -interval< size_tinterval - Region of the last match.
-  + +stdex::interval< size_tinterval + Region of the last match.

Detailed Description

template<class T>
@@ -252,7 +252,7 @@ template<clas
diff --git a/classstdex_1_1parser_1_1basic__ipv4__address-members.html b/classstdex_1_1parser_1_1basic__ipv4__address-members.html index aeb8844ad..95e6e68ae 100644 --- a/classstdex_1_1parser_1_1basic__ipv4__address-members.html +++ b/classstdex_1_1parser_1_1basic__ipv4__address-members.html @@ -83,7 +83,7 @@ $(function() { basic_ipv4_address(const std::shared_ptr< basic_parser< T > > &digit_0, const std::shared_ptr< basic_parser< T > > &digit_1, const std::shared_ptr< basic_parser< T > > &digit_2, const std::shared_ptr< basic_parser< T > > &digit_3, const std::shared_ptr< basic_parser< T > > &digit_4, const std::shared_ptr< basic_parser< T > > &digit_5, const std::shared_ptr< basic_parser< T > > &digit_6, const std::shared_ptr< basic_parser< T > > &digit_7, const std::shared_ptr< basic_parser< T > > &digit_8, const std::shared_ptr< basic_parser< T > > &digit_9, const std::shared_ptr< basic_parser< T > > &separator, const std::locale &locale=std::locale()) (defined in stdex::parser::basic_ipv4_address< T >)stdex::parser::basic_ipv4_address< T >inline basic_parser(const std::locale &locale=std::locale()) (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inline componentsstdex::parser::basic_ipv4_address< T > - intervalstdex::parser::basic_parser< T > + intervalstdex::parser::basic_parser< T > invalidate() (defined in stdex::parser::basic_ipv4_address< T >)stdex::parser::basic_ipv4_address< T >inlinevirtual m_digit_0 (defined in stdex::parser::basic_ipv4_address< T >)stdex::parser::basic_ipv4_address< T >protected m_digit_1 (defined in stdex::parser::basic_ipv4_address< T >)stdex::parser::basic_ipv4_address< T >protected @@ -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 1687e07e3..ff53bf250 100644 --- a/classstdex_1_1parser_1_1basic__ipv4__address.html +++ b/classstdex_1_1parser_1_1basic__ipv4__address.html @@ -129,10 +129,10 @@ Public Attributes  IPv4 address value.
  - Public Attributes inherited from stdex::parser::basic_parser< T > - -interval< size_tinterval - Region of the last match.
-  + +stdex::interval< size_tinterval + Region of the last match.
+  @@ -265,7 +265,7 @@ template<clas diff --git a/classstdex_1_1parser_1_1basic__ipv6__address-members.html b/classstdex_1_1parser_1_1basic__ipv6__address-members.html index 711a51e83..f9a237785 100644 --- a/classstdex_1_1parser_1_1basic__ipv6__address-members.html +++ b/classstdex_1_1parser_1_1basic__ipv6__address-members.html @@ -83,7 +83,7 @@ $(function() { - + @@ -113,7 +113,7 @@ $(function() {

Protected Attributes

basic_ipv6_address(const std::shared_ptr< basic_parser< T > > &digit_0, const std::shared_ptr< basic_parser< T > > &digit_1, const std::shared_ptr< basic_parser< T > > &digit_2, const std::shared_ptr< basic_parser< T > > &digit_3, const std::shared_ptr< basic_parser< T > > &digit_4, const std::shared_ptr< basic_parser< T > > &digit_5, const std::shared_ptr< basic_parser< T > > &digit_6, const std::shared_ptr< basic_parser< T > > &digit_7, const std::shared_ptr< basic_parser< T > > &digit_8, const std::shared_ptr< basic_parser< T > > &digit_9, const std::shared_ptr< basic_parser< T > > &digit_10, const std::shared_ptr< basic_parser< T > > &digit_11, const std::shared_ptr< basic_parser< T > > &digit_12, const std::shared_ptr< basic_parser< T > > &digit_13, const std::shared_ptr< basic_parser< T > > &digit_14, const std::shared_ptr< basic_parser< T > > &digit_15, const std::shared_ptr< basic_parser< T > > &separator, const std::shared_ptr< basic_parser< T > > &scope_id_separator=nullptr, const std::shared_ptr< basic_parser< T > > &_scope_id=nullptr, const std::locale &locale=std::locale()) (defined in stdex::parser::basic_ipv6_address< T >)stdex::parser::basic_ipv6_address< T >inline
basic_parser(const std::locale &locale=std::locale()) (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inline
componentsstdex::parser::basic_ipv6_address< T >
intervalstdex::parser::basic_parser< T >
intervalstdex::parser::basic_parser< T >
invalidate() (defined in stdex::parser::basic_ipv6_address< T >)stdex::parser::basic_ipv6_address< T >inlinevirtual
m_digit_0 (defined in stdex::parser::basic_ipv6_address< T >)stdex::parser::basic_ipv6_address< T >protected
m_digit_1 (defined in stdex::parser::basic_ipv6_address< T >)stdex::parser::basic_ipv6_address< T >protected
diff --git a/classstdex_1_1parser_1_1basic__ipv6__address.html b/classstdex_1_1parser_1_1basic__ipv6__address.html index 5454ed6c7..02fdd0d7d 100644 --- a/classstdex_1_1parser_1_1basic__ipv6__address.html +++ b/classstdex_1_1parser_1_1basic__ipv6__address.html @@ -133,10 +133,10 @@ std::shared_ptr<  Scope ID (e.g. NIC index with link-local addresses)
  - Public Attributes inherited from
stdex::parser::basic_parser< T > - -interval< size_tinterval - Region of the last match.
-  + +stdex::interval< size_tinterval + Region of the last match.
+  @@ -290,7 +290,7 @@ template<clas 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 7dd32abed..4d6860c72 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 @@ -82,7 +82,7 @@ $(function() {

Protected Attributes

- + @@ -92,7 +92,7 @@ $(function() {
basic_ipv6_scope_id_char(const std::locale &locale=std::locale()) (defined in stdex::parser::basic_ipv6_scope_id_char< T >)stdex::parser::basic_ipv6_scope_id_char< T >inline
basic_parser(const std::locale &locale=std::locale()) (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inline
intervalstdex::parser::basic_parser< T >
intervalstdex::parser::basic_parser< T >
invalidate() (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inlinevirtual
m_locale (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >protected
match(_In_reads_or_z_(end) const T *text, size_t start=0, size_t end=(size_t) -1, int flags=match_default) (defined in stdex::parser::basic_ipv6_scope_id_char< T >)stdex::parser::basic_ipv6_scope_id_char< T >inlinevirtual
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 818fcec16..23bc5f053 100644 --- a/classstdex_1_1parser_1_1basic__ipv6__scope__id__char.html +++ b/classstdex_1_1parser_1_1basic__ipv6__scope__id__char.html @@ -120,10 +120,10 @@ template<clas

Additional Inherited Members

- Public Attributes inherited from stdex::parser::basic_parser< T > - -interval< size_tinterval - Region of the last match.
-  + +stdex::interval< size_tinterval + Region of the last match.
- Protected Attributes inherited from stdex::parser::basic_parser< T > std::locale m_locale @@ -191,7 +191,7 @@ template<clas diff --git a/classstdex_1_1parser_1_1basic__iterations-members.html b/classstdex_1_1parser_1_1basic__iterations-members.html index 5f04101aa..ea36ed2e5 100644 --- a/classstdex_1_1parser_1_1basic__iterations-members.html +++ b/classstdex_1_1parser_1_1basic__iterations-members.html @@ -82,7 +82,7 @@ $(function() { - + @@ -96,7 +96,7 @@ $(function() {
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) (defined in stdex::parser::basic_iterations< T >)stdex::parser::basic_iterations< T >inline
basic_parser(const std::locale &locale=std::locale()) (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inline
intervalstdex::parser::basic_parser< T >
intervalstdex::parser::basic_parser< T >
invalidate() (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inlinevirtual
m_elstdex::parser::basic_iterations< T >protected
m_greedystdex::parser::basic_iterations< T >protected
diff --git a/classstdex_1_1parser_1_1basic__iterations.html b/classstdex_1_1parser_1_1basic__iterations.html index 9c80d1732..3223d018e 100644 --- a/classstdex_1_1parser_1_1basic__iterations.html +++ b/classstdex_1_1parser_1_1basic__iterations.html @@ -144,10 +144,10 @@ std::locale m_locale

Additional Inherited Members

- Public Attributes inherited from stdex::parser::basic_parser< T > - -interval< size_tinterval - Region of the last match.
-  + +stdex::interval< size_tinterval + Region of the last match.

Detailed Description

template<class T>
@@ -211,7 +211,7 @@ template<clas
diff --git a/classstdex_1_1parser_1_1basic__json__string-members.html b/classstdex_1_1parser_1_1basic__json__string-members.html index 2b48fce55..c6a11e5f3 100644 --- a/classstdex_1_1parser_1_1basic__json__string-members.html +++ b/classstdex_1_1parser_1_1basic__json__string-members.html @@ -82,7 +82,7 @@ $(function() { - + @@ -104,7 +104,7 @@ $(function() {
basic_json_string(const std::shared_ptr< basic_parser< T > > &quote, const std::shared_ptr< basic_parser< T > > &chr, const std::shared_ptr< basic_parser< T > > &escape, const std::shared_ptr< basic_parser< T > > &sol, const std::shared_ptr< basic_parser< T > > &bs, const std::shared_ptr< basic_parser< T > > &ff, const std::shared_ptr< basic_parser< T > > &lf, const std::shared_ptr< basic_parser< T > > &cr, const std::shared_ptr< basic_parser< T > > &htab, const std::shared_ptr< basic_parser< T > > &uni, const std::shared_ptr< basic_integer16< T > > &hex, const std::locale &locale=std::locale()) (defined in stdex::parser::basic_json_string< T >)stdex::parser::basic_json_string< T >inline
basic_parser(const std::locale &locale=std::locale()) (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inline
intervalstdex::parser::basic_parser< T >
intervalstdex::parser::basic_parser< T >
invalidate() (defined in stdex::parser::basic_json_string< T >)stdex::parser::basic_json_string< T >inlinevirtual
m_bs (defined in stdex::parser::basic_json_string< T >)stdex::parser::basic_json_string< T >protected
m_chr (defined in stdex::parser::basic_json_string< T >)stdex::parser::basic_json_string< T >protected
diff --git a/classstdex_1_1parser_1_1basic__json__string.html b/classstdex_1_1parser_1_1basic__json__string.html index 268879155..a5771b6f0 100644 --- a/classstdex_1_1parser_1_1basic__json__string.html +++ b/classstdex_1_1parser_1_1basic__json__string.html @@ -124,10 +124,10 @@ Public Attributes std::basic_string< T > value   - Public Attributes inherited from stdex::parser::basic_parser< T > - -interval< size_tinterval - Region of the last match.
-  + +stdex::interval< size_tinterval + Region of the last match.
+  @@ -260,7 +260,7 @@ template<clas diff --git a/classstdex_1_1parser_1_1basic__mixed__numeral-members.html b/classstdex_1_1parser_1_1basic__mixed__numeral-members.html index 461583df1..3e02d7fa5 100644 --- a/classstdex_1_1parser_1_1basic__mixed__numeral-members.html +++ b/classstdex_1_1parser_1_1basic__mixed__numeral-members.html @@ -84,7 +84,7 @@ $(function() { - + @@ -98,7 +98,7 @@ $(function() {

Protected Attributes

basic_parser(const std::locale &locale=std::locale()) (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inline
fractionstdex::parser::basic_mixed_numeral< T >
integerstdex::parser::basic_mixed_numeral< T >
intervalstdex::parser::basic_parser< T >
intervalstdex::parser::basic_parser< T >
invalidate() (defined in stdex::parser::basic_mixed_numeral< T >)stdex::parser::basic_mixed_numeral< T >inlinevirtual
m_locale (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >protected
m_space (defined in stdex::parser::basic_mixed_numeral< T >)stdex::parser::basic_mixed_numeral< T >protected
diff --git a/classstdex_1_1parser_1_1basic__mixed__numeral.html b/classstdex_1_1parser_1_1basic__mixed__numeral.html index cffc10845..f2df74a1d 100644 --- a/classstdex_1_1parser_1_1basic__mixed__numeral.html +++ b/classstdex_1_1parser_1_1basic__mixed__numeral.html @@ -141,10 +141,10 @@ std::shared_ptr<  fraction
  - Public Attributes inherited from
stdex::parser::basic_parser< T > - -interval< size_tinterval - Region of the last match.
-  + +stdex::interval< size_tinterval + Region of the last match.
+  @@ -247,7 +247,7 @@ template<clas diff --git a/classstdex_1_1parser_1_1basic__monetary__numeral-members.html b/classstdex_1_1parser_1_1basic__monetary__numeral-members.html index b1ca16cac..5221c285d 100644 --- a/classstdex_1_1parser_1_1basic__monetary__numeral-members.html +++ b/classstdex_1_1parser_1_1basic__monetary__numeral-members.html @@ -86,7 +86,7 @@ $(function() { - + @@ -99,7 +99,7 @@ $(function() {

Protected Attributes

decimalstdex::parser::basic_monetary_numeral< T >
decimal_separatorstdex::parser::basic_monetary_numeral< T >
integerstdex::parser::basic_monetary_numeral< T >
intervalstdex::parser::basic_parser< T >
intervalstdex::parser::basic_parser< T >
invalidate() (defined in stdex::parser::basic_monetary_numeral< T >)stdex::parser::basic_monetary_numeral< T >inlinevirtual
m_locale (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >protected
match(_In_reads_or_z_(end) const T *text, size_t start=0, size_t end=(size_t) -1, int flags=match_default) (defined in stdex::parser::basic_monetary_numeral< T >)stdex::parser::basic_monetary_numeral< T >inlinevirtual
diff --git a/classstdex_1_1parser_1_1basic__monetary__numeral.html b/classstdex_1_1parser_1_1basic__monetary__numeral.html index 7bb023941..89ed1fad1 100644 --- a/classstdex_1_1parser_1_1basic__monetary__numeral.html +++ b/classstdex_1_1parser_1_1basic__monetary__numeral.html @@ -148,10 +148,10 @@ std::shared_ptr<  Decimal part.
  - Public Attributes inherited from
stdex::parser::basic_parser< T > - -interval< size_tinterval - Region of the last match.
-  + +stdex::interval< size_tinterval + Region of the last match.
+  @@ -251,7 +251,7 @@ template<clas diff --git a/classstdex_1_1parser_1_1basic__noop-members.html b/classstdex_1_1parser_1_1basic__noop-members.html index 6f29f6ff6..ba04154a3 100644 --- a/classstdex_1_1parser_1_1basic__noop-members.html +++ b/classstdex_1_1parser_1_1basic__noop-members.html @@ -81,7 +81,7 @@ $(function() {

This is the complete list of members for stdex::parser::basic_noop< T >, including all inherited members.

Additional Inherited Members

- + @@ -91,7 +91,7 @@ $(function() {
basic_parser(const std::locale &locale=std::locale()) (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inline
intervalstdex::parser::basic_parser< T >
intervalstdex::parser::basic_parser< T >
invalidate() (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inlinevirtual
m_locale (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >protected
match(_In_reads_or_z_(end) const T *text, size_t start=0, size_t end=(size_t) -1, int flags=match_default) (defined in stdex::parser::basic_noop< T >)stdex::parser::basic_noop< T >inlinevirtual
diff --git a/classstdex_1_1parser_1_1basic__noop.html b/classstdex_1_1parser_1_1basic__noop.html index ec69f9e36..1156dd754 100644 --- a/classstdex_1_1parser_1_1basic__noop.html +++ b/classstdex_1_1parser_1_1basic__noop.html @@ -117,10 +117,10 @@ template<clas

Additional Inherited Members

- Public Attributes inherited from stdex::parser::basic_parser< T > - -interval< size_tinterval - Region of the last match.
-  + +stdex::interval< size_tinterval + Region of the last match.
- Protected Attributes inherited from stdex::parser::basic_parser< T > std::locale m_locale @@ -188,7 +188,7 @@ template<clas diff --git a/classstdex_1_1parser_1_1basic__parser-members.html b/classstdex_1_1parser_1_1basic__parser-members.html index edeb53de6..19c2191bd 100644 --- a/classstdex_1_1parser_1_1basic__parser-members.html +++ b/classstdex_1_1parser_1_1basic__parser-members.html @@ -81,7 +81,7 @@ $(function() {

This is the complete list of members for stdex::parser::basic_parser< T >, including all inherited members.

- + @@ -91,7 +91,7 @@ $(function() {
basic_parser(const std::locale &locale=std::locale()) (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inline
intervalstdex::parser::basic_parser< T >
intervalstdex::parser::basic_parser< T >
invalidate() (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inlinevirtual
m_locale (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >protected
match(_In_reads_or_z_(end) const T *text, size_t start=0, size_t end=(size_t) -1, int flags=match_default)=0 (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >pure virtual
diff --git a/classstdex_1_1parser_1_1basic__parser.html b/classstdex_1_1parser_1_1basic__parser.html index 6a6f3a0b8..6a9a9ae1b 100644 --- a/classstdex_1_1parser_1_1basic__parser.html +++ b/classstdex_1_1parser_1_1basic__parser.html @@ -168,10 +168,10 @@ template<clas - - - + + +

Public Attributes

-interval< size_tinterval
 Region of the last match.
 
+stdex::interval< size_tinterval
 Region of the last match.
 
@@ -188,7 +188,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 6f0fb3e55..18fd2a184 100644 --- a/classstdex_1_1parser_1_1basic__permutation-members.html +++ b/classstdex_1_1parser_1_1basic__permutation-members.html @@ -83,7 +83,7 @@ $(function() { - + @@ -98,7 +98,7 @@ $(function() {

Protected Attributes

basic_parser(const std::locale &locale=std::locale()) (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inline
basic_permutation(const std::shared_ptr< basic_parser< T > > *el=nullptr, size_t count=0, const std::locale &locale=std::locale()) (defined in stdex::parser::basic_permutation< T >)stdex::parser::basic_permutation< T >inline
basic_permutation(std::vector< std::shared_ptr< basic_parser< T > > > &&collection, const std::locale &locale=std::locale()) (defined in stdex::parser::basic_permutation< T >)stdex::parser::basic_permutation< T >inline
intervalstdex::parser::basic_parser< T >
intervalstdex::parser::basic_parser< T >
invalidate() (defined in stdex::parser::parser_collection< T >)stdex::parser::parser_collection< T >inlinevirtual
m_collection (defined in stdex::parser::parser_collection< T >)stdex::parser::parser_collection< T >protected
m_locale (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >protected
diff --git a/classstdex_1_1parser_1_1basic__permutation.html b/classstdex_1_1parser_1_1basic__permutation.html index 2b8637e08..d2e4fe0a5 100644 --- a/classstdex_1_1parser_1_1basic__permutation.html +++ b/classstdex_1_1parser_1_1basic__permutation.html @@ -141,10 +141,10 @@ Protected Member Functions

Additional Inherited Members

- Public Attributes inherited from stdex::parser::basic_parser< T > - -interval< size_tinterval - Region of the last match.
-  + +stdex::interval< size_tinterval + Region of the last match.
- Protected Attributes inherited from stdex::parser::parser_collection< T > std::vector< std::shared_ptr< basic_parser< T > > > m_collection @@ -216,7 +216,7 @@ template<clas diff --git a/classstdex_1_1parser_1_1basic__phone__number-members.html b/classstdex_1_1parser_1_1basic__phone__number-members.html index edc365198..b9a46440a 100644 --- a/classstdex_1_1parser_1_1basic__phone__number-members.html +++ b/classstdex_1_1parser_1_1basic__phone__number-members.html @@ -82,7 +82,7 @@ $(function() { - + @@ -99,7 +99,7 @@ $(function() {
basic_parser(const std::locale &locale=std::locale()) (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inline
basic_phone_number(const std::shared_ptr< basic_parser< T > > &digit, const std::shared_ptr< basic_parser< T > > &plus_sign, const std::shared_ptr< basic_set< T > > &lparenthesis, const std::shared_ptr< basic_set< T > > &rparenthesis, const std::shared_ptr< basic_parser< T > > &separator, const std::shared_ptr< basic_parser< T > > &space, const std::locale &locale=std::locale()) (defined in stdex::parser::basic_phone_number< T >)stdex::parser::basic_phone_number< T >inline
intervalstdex::parser::basic_parser< T >
intervalstdex::parser::basic_parser< T >
invalidate() (defined in stdex::parser::basic_phone_number< T >)stdex::parser::basic_phone_number< T >inlinevirtual
m_digit (defined in stdex::parser::basic_phone_number< T >)stdex::parser::basic_phone_number< T >protected
m_locale (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >protected
diff --git a/classstdex_1_1parser_1_1basic__phone__number.html b/classstdex_1_1parser_1_1basic__phone__number.html index e219416c9..9e83c292c 100644 --- a/classstdex_1_1parser_1_1basic__phone__number.html +++ b/classstdex_1_1parser_1_1basic__phone__number.html @@ -125,10 +125,10 @@ std::basic_string< T >   Normalized phone number.
  - Public Attributes inherited from stdex::parser::basic_parser< T > - -interval< size_tinterval - Region of the last match.
-  + +stdex::interval< size_tinterval + Region of the last match.
+  @@ -246,7 +246,7 @@ template<clas diff --git a/classstdex_1_1parser_1_1basic__punct__cu-members.html b/classstdex_1_1parser_1_1basic__punct__cu-members.html index 1bf857ca7..6d6386859 100644 --- a/classstdex_1_1parser_1_1basic__punct__cu-members.html +++ b/classstdex_1_1parser_1_1basic__punct__cu-members.html @@ -82,7 +82,7 @@ $(function() {

Protected Attributes

- + @@ -93,7 +93,7 @@ $(function() {
basic_parser(const std::locale &locale=std::locale()) (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inline
basic_punct_cu(bool invert=false, const std::locale &locale=std::locale()) (defined in stdex::parser::basic_punct_cu< T >)stdex::parser::basic_punct_cu< T >inline
intervalstdex::parser::basic_parser< T >
intervalstdex::parser::basic_parser< T >
invalidate() (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inlinevirtual
m_invert (defined in stdex::parser::basic_punct_cu< T >)stdex::parser::basic_punct_cu< T >protected
m_locale (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >protected
diff --git a/classstdex_1_1parser_1_1basic__punct__cu.html b/classstdex_1_1parser_1_1basic__punct__cu.html index 17182c222..8bbb9c759 100644 --- a/classstdex_1_1parser_1_1basic__punct__cu.html +++ b/classstdex_1_1parser_1_1basic__punct__cu.html @@ -131,10 +131,10 @@ std::locale m_locale

Additional Inherited Members

- Public Attributes inherited from stdex::parser::basic_parser< T > - -interval< size_tinterval - Region of the last match.
-  + +stdex::interval< size_tinterval + Region of the last match.

Detailed Description

template<class T>
@@ -198,7 +198,7 @@ template<clas
diff --git a/classstdex_1_1parser_1_1basic__roman__numeral-members.html b/classstdex_1_1parser_1_1basic__roman__numeral-members.html index a4448c95a..96a40320d 100644 --- a/classstdex_1_1parser_1_1basic__roman__numeral-members.html +++ b/classstdex_1_1parser_1_1basic__roman__numeral-members.html @@ -83,7 +83,7 @@ $(function() { basic_integer(const std::locale &locale=std::locale()) (defined in stdex::parser::basic_integer< T >)stdex::parser::basic_integer< T >inline basic_parser(const std::locale &locale=std::locale()) (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inline basic_roman_numeral(const std::shared_ptr< basic_parser< T > > &digit_1, const std::shared_ptr< basic_parser< T > > &digit_5, const std::shared_ptr< basic_parser< T > > &digit_10, const std::shared_ptr< basic_parser< T > > &digit_50, const std::shared_ptr< basic_parser< T > > &digit_100, const std::shared_ptr< basic_parser< T > > &digit_500, const std::shared_ptr< basic_parser< T > > &digit_1000, const std::shared_ptr< basic_parser< T > > &digit_5000, const std::shared_ptr< basic_parser< T > > &digit_10000, const std::locale &locale=std::locale()) (defined in stdex::parser::basic_roman_numeral< T >)stdex::parser::basic_roman_numeral< T >inline - intervalstdex::parser::basic_parser< T > + intervalstdex::parser::basic_parser< T > invalidate() (defined in stdex::parser::basic_integer< T >)stdex::parser::basic_integer< T >inlinevirtual m_digit_1 (defined in stdex::parser::basic_roman_numeral< T >)stdex::parser::basic_roman_numeral< T >protected m_digit_10 (defined in stdex::parser::basic_roman_numeral< T >)stdex::parser::basic_roman_numeral< T >protected @@ -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 2aa589c97..8f97a9179 100644 --- a/classstdex_1_1parser_1_1basic__roman__numeral.html +++ b/classstdex_1_1parser_1_1basic__roman__numeral.html @@ -164,10 +164,10 @@ Additional Inherited Members  Calculated value of the numeral.
  - Public Attributes inherited from stdex::parser::basic_parser< T > - -interval< size_tinterval - Region of the last match.
-  + +stdex::interval< size_tinterval + Region of the last match.

Detailed Description

template<class T>
@@ -231,7 +231,7 @@ template<clas
diff --git a/classstdex_1_1parser_1_1basic__scientific__numeral-members.html b/classstdex_1_1parser_1_1basic__scientific__numeral-members.html index 3e0e88abb..3e826d3d8 100644 --- a/classstdex_1_1parser_1_1basic__scientific__numeral-members.html +++ b/classstdex_1_1parser_1_1basic__scientific__numeral-members.html @@ -87,7 +87,7 @@ $(function() { exponentstdex::parser::basic_scientific_numeral< T > exponent_symbolstdex::parser::basic_scientific_numeral< T > integerstdex::parser::basic_scientific_numeral< T > - intervalstdex::parser::basic_parser< T > + intervalstdex::parser::basic_parser< T > invalidate() (defined in stdex::parser::basic_scientific_numeral< T >)stdex::parser::basic_scientific_numeral< T >inlinevirtual m_locale (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >protected match(_In_reads_or_z_(end) const T *text, size_t start=0, size_t end=(size_t) -1, int flags=match_default) (defined in stdex::parser::basic_scientific_numeral< T >)stdex::parser::basic_scientific_numeral< T >inlinevirtual @@ -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 5a507d956..989c58901 100644 --- a/classstdex_1_1parser_1_1basic__scientific__numeral.html +++ b/classstdex_1_1parser_1_1basic__scientific__numeral.html @@ -164,10 +164,10 @@ std::shared_ptr<  Calculated value of the numeral.
  - Public Attributes inherited from
stdex::parser::basic_parser< T > - -interval< size_tinterval - Region of the last match.
-  + +stdex::interval< size_tinterval + Region of the last match.
+  @@ -267,7 +267,7 @@ template<clas diff --git a/classstdex_1_1parser_1_1basic__score-members.html b/classstdex_1_1parser_1_1basic__score-members.html index 307822e0e..99a931f83 100644 --- a/classstdex_1_1parser_1_1basic__score-members.html +++ b/classstdex_1_1parser_1_1basic__score-members.html @@ -84,7 +84,7 @@ $(function() { - + @@ -96,7 +96,7 @@ $(function() {

Additional Inherited Members

basic_score(const std::shared_ptr< basic_parser< T > > &_home, const std::shared_ptr< basic_parser< T > > &_separator, const std::shared_ptr< basic_parser< T > > &_guest, const std::shared_ptr< basic_parser< T > > &space, const std::locale &locale=std::locale()) (defined in stdex::parser::basic_score< T >)stdex::parser::basic_score< T >inline
guest (defined in stdex::parser::basic_score< T >)stdex::parser::basic_score< T >
home (defined in stdex::parser::basic_score< T >)stdex::parser::basic_score< T >
intervalstdex::parser::basic_parser< T >
intervalstdex::parser::basic_parser< T >
invalidate() (defined in stdex::parser::basic_score< T >)stdex::parser::basic_score< T >inlinevirtual
m_locale (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >protected
m_space (defined in stdex::parser::basic_score< T >)stdex::parser::basic_score< T >protected
diff --git a/classstdex_1_1parser_1_1basic__score.html b/classstdex_1_1parser_1_1basic__score.html index 383e300f4..d9464515e 100644 --- a/classstdex_1_1parser_1_1basic__score.html +++ b/classstdex_1_1parser_1_1basic__score.html @@ -130,10 +130,10 @@ std::shared_ptr< basic_parser< T > > guest   - Public Attributes inherited from stdex::parser::basic_parser< T > - -interval< size_tinterval - Region of the last match.
-  + +stdex::interval< size_tinterval + Region of the last match.
+  @@ -236,7 +236,7 @@ template<clas diff --git a/classstdex_1_1parser_1_1basic__sequence-members.html b/classstdex_1_1parser_1_1basic__sequence-members.html index 993fd17c6..4ef1c9bfc 100644 --- a/classstdex_1_1parser_1_1basic__sequence-members.html +++ b/classstdex_1_1parser_1_1basic__sequence-members.html @@ -83,7 +83,7 @@ $(function() { - + @@ -97,7 +97,7 @@ $(function() {

Protected Attributes

basic_parser(const std::locale &locale=std::locale()) (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inline
basic_sequence(const std::shared_ptr< basic_parser< T > > *el=nullptr, size_t count=0, const std::locale &locale=std::locale()) (defined in stdex::parser::basic_sequence< T >)stdex::parser::basic_sequence< T >inline
basic_sequence(std::vector< std::shared_ptr< basic_parser< T > > > &&collection, const std::locale &locale=std::locale()) (defined in stdex::parser::basic_sequence< T >)stdex::parser::basic_sequence< T >inline
intervalstdex::parser::basic_parser< T >
intervalstdex::parser::basic_parser< T >
invalidate() (defined in stdex::parser::parser_collection< T >)stdex::parser::parser_collection< T >inlinevirtual
m_collection (defined in stdex::parser::parser_collection< T >)stdex::parser::parser_collection< T >protected
m_locale (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >protected
diff --git a/classstdex_1_1parser_1_1basic__sequence.html b/classstdex_1_1parser_1_1basic__sequence.html index c8b918402..837c22f3f 100644 --- a/classstdex_1_1parser_1_1basic__sequence.html +++ b/classstdex_1_1parser_1_1basic__sequence.html @@ -130,10 +130,10 @@ template<clas

Additional Inherited Members

- Public Attributes inherited from stdex::parser::basic_parser< T > - -interval< size_tinterval - Region of the last match.
-  + +stdex::interval< size_tinterval + Region of the last match.
- Protected Member Functions inherited from stdex::parser::parser_collection< T >  parser_collection (const std::locale &locale) @@ -209,7 +209,7 @@ template<clas diff --git a/classstdex_1_1parser_1_1basic__set-members.html b/classstdex_1_1parser_1_1basic__set-members.html index 698f091b2..ac159fffa 100644 --- a/classstdex_1_1parser_1_1basic__set-members.html +++ b/classstdex_1_1parser_1_1basic__set-members.html @@ -83,7 +83,7 @@ $(function() { basic_parser(const std::locale &locale=std::locale()) (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inline basic_set(bool invert=false, const std::locale &locale=std::locale()) (defined in stdex::parser::basic_set< T >)stdex::parser::basic_set< T >inline hit_offset (defined in stdex::parser::basic_set< T >)stdex::parser::basic_set< T > - intervalstdex::parser::basic_parser< T > + intervalstdex::parser::basic_parser< T > invalidate() (defined in stdex::parser::basic_set< T >)stdex::parser::basic_set< T >inlinevirtual m_invert (defined in stdex::parser::basic_set< T >)stdex::parser::basic_set< T >protected m_locale (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >protected @@ -94,7 +94,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__set.html b/classstdex_1_1parser_1_1basic__set.html index 930f40784..786e1a9e4 100644 --- a/classstdex_1_1parser_1_1basic__set.html +++ b/classstdex_1_1parser_1_1basic__set.html @@ -120,10 +120,10 @@ Public Attributes size_t hit_offset   - Public Attributes inherited from stdex::parser::basic_parser< T > - -interval< size_tinterval - Region of the last match.
-  + +stdex::interval< size_tinterval + Region of the last match.
+  @@ -223,7 +223,7 @@ template<clas diff --git a/classstdex_1_1parser_1_1basic__si__reference-members.html b/classstdex_1_1parser_1_1basic__si__reference-members.html index 6d8c78692..44432f589 100644 --- a/classstdex_1_1parser_1_1basic__si__reference-members.html +++ b/classstdex_1_1parser_1_1basic__si__reference-members.html @@ -85,7 +85,7 @@ $(function() { - + @@ -102,7 +102,7 @@ $(function() {

Protected Attributes

check11(const T *part1, size_t num_part1) (defined in stdex::parser::basic_si_reference< T >)stdex::parser::basic_si_reference< T >inlineprotectedstatic
check11(const T *part1, size_t num_part1, const T *part2, size_t num_part2) (defined in stdex::parser::basic_si_reference< T >)stdex::parser::basic_si_reference< T >inlineprotectedstatic
check11(const T *part1, size_t num_part1, const T *part2, size_t num_part2, const T *part3, size_t num_part3) (defined in stdex::parser::basic_si_reference< T >)stdex::parser::basic_si_reference< T >inlineprotectedstatic
intervalstdex::parser::basic_parser< T >
intervalstdex::parser::basic_parser< T >
invalidate() (defined in stdex::parser::basic_si_reference< T >)stdex::parser::basic_si_reference< T >inlinevirtual
is_validstdex::parser::basic_si_reference< T >
m_delimiter (defined in stdex::parser::basic_si_reference< T >)stdex::parser::basic_si_reference< T >protected
diff --git a/classstdex_1_1parser_1_1basic__si__reference.html b/classstdex_1_1parser_1_1basic__si__reference.html index 8639d9e1d..1f1661119 100644 --- a/classstdex_1_1parser_1_1basic__si__reference.html +++ b/classstdex_1_1parser_1_1basic__si__reference.html @@ -142,10 +142,10 @@ T model [3]  Is reference valid.
  - Public Attributes inherited from stdex::parser::basic_parser< T > - -interval< size_tinterval - Region of the last match.
-  + +stdex::interval< size_tinterval + Region of the last match.
+  @@ -265,7 +265,7 @@ template<clas diff --git a/classstdex_1_1parser_1_1basic__si__reference__delimiter-members.html b/classstdex_1_1parser_1_1basic__si__reference__delimiter-members.html index 46e2199b6..1e38e96c8 100644 --- a/classstdex_1_1parser_1_1basic__si__reference__delimiter-members.html +++ b/classstdex_1_1parser_1_1basic__si__reference__delimiter-members.html @@ -82,7 +82,7 @@ $(function() {

Static Protected Member Functions

- + @@ -92,7 +92,7 @@ $(function() {
basic_parser(const std::locale &locale=std::locale()) (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inline
basic_si_reference_delimiter(const std::locale &locale=std::locale()) (defined in stdex::parser::basic_si_reference_delimiter< T >)stdex::parser::basic_si_reference_delimiter< T >inline
intervalstdex::parser::basic_parser< T >
intervalstdex::parser::basic_parser< T >
invalidate() (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inlinevirtual
m_locale (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >protected
match(_In_reads_or_z_(end) const T *text, size_t start=0, size_t end=(size_t) -1, int flags=match_default) (defined in stdex::parser::basic_si_reference_delimiter< T >)stdex::parser::basic_si_reference_delimiter< T >inlinevirtual
diff --git a/classstdex_1_1parser_1_1basic__si__reference__delimiter.html b/classstdex_1_1parser_1_1basic__si__reference__delimiter.html index beac72c38..d98d278d8 100644 --- a/classstdex_1_1parser_1_1basic__si__reference__delimiter.html +++ b/classstdex_1_1parser_1_1basic__si__reference__delimiter.html @@ -120,10 +120,10 @@ template<clas

Additional Inherited Members

- Public Attributes inherited from stdex::parser::basic_parser< T > - -interval< size_tinterval - Region of the last match.
-  + +stdex::interval< size_tinterval + Region of the last match.
- Protected Attributes inherited from stdex::parser::basic_parser< T > std::locale m_locale @@ -192,7 +192,7 @@ template<clas diff --git a/classstdex_1_1parser_1_1basic__si__reference__part-members.html b/classstdex_1_1parser_1_1basic__si__reference__part-members.html index 0f7201427..2b4fa2507 100644 --- a/classstdex_1_1parser_1_1basic__si__reference__part-members.html +++ b/classstdex_1_1parser_1_1basic__si__reference__part-members.html @@ -82,7 +82,7 @@ $(function() { - + @@ -92,7 +92,7 @@ $(function() {
basic_parser(const std::locale &locale=std::locale()) (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inline
basic_si_reference_part(const std::locale &locale=std::locale()) (defined in stdex::parser::basic_si_reference_part< T >)stdex::parser::basic_si_reference_part< T >inline
intervalstdex::parser::basic_parser< T >
intervalstdex::parser::basic_parser< T >
invalidate() (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inlinevirtual
m_locale (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >protected
match(_In_reads_or_z_(end) const T *text, size_t start=0, size_t end=(size_t) -1, int flags=match_default) (defined in stdex::parser::basic_si_reference_part< T >)stdex::parser::basic_si_reference_part< T >inlinevirtual
diff --git a/classstdex_1_1parser_1_1basic__si__reference__part.html b/classstdex_1_1parser_1_1basic__si__reference__part.html index 15760dc84..6e4157239 100644 --- a/classstdex_1_1parser_1_1basic__si__reference__part.html +++ b/classstdex_1_1parser_1_1basic__si__reference__part.html @@ -120,10 +120,10 @@ template<clas

Additional Inherited Members

- Public Attributes inherited from stdex::parser::basic_parser< T > - -interval< size_tinterval - Region of the last match.
-  + +stdex::interval< size_tinterval + Region of the last match.
- Protected Attributes inherited from stdex::parser::basic_parser< T > std::locale m_locale @@ -192,7 +192,7 @@ template<clas diff --git a/classstdex_1_1parser_1_1basic__signed__numeral-members.html b/classstdex_1_1parser_1_1basic__signed__numeral-members.html index dd53ebc06..fd343ab92 100644 --- a/classstdex_1_1parser_1_1basic__signed__numeral-members.html +++ b/classstdex_1_1parser_1_1basic__signed__numeral-members.html @@ -82,7 +82,7 @@ $(function() { - + @@ -96,7 +96,7 @@ $(function() {
basic_parser(const std::locale &locale=std::locale()) (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inline
basic_signed_numeral(const std::shared_ptr< basic_parser< T > > &_positive_sign, const std::shared_ptr< basic_parser< T > > &_negative_sign, const std::shared_ptr< basic_parser< T > > &_special_sign, const std::shared_ptr< basic_parser< T > > &_number, const std::locale &locale=std::locale()) (defined in stdex::parser::basic_signed_numeral< T >)stdex::parser::basic_signed_numeral< T >inline
intervalstdex::parser::basic_parser< T >
intervalstdex::parser::basic_parser< T >
invalidate() (defined in stdex::parser::basic_signed_numeral< T >)stdex::parser::basic_signed_numeral< T >inlinevirtual
m_locale (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >protected
match(_In_reads_or_z_(end) const T *text, size_t start=0, size_t end=(size_t) -1, int flags=match_default) (defined in stdex::parser::basic_signed_numeral< T >)stdex::parser::basic_signed_numeral< T >inlinevirtual
diff --git a/classstdex_1_1parser_1_1basic__signed__numeral.html b/classstdex_1_1parser_1_1basic__signed__numeral.html index c9fdd0c7b..c54144a46 100644 --- a/classstdex_1_1parser_1_1basic__signed__numeral.html +++ b/classstdex_1_1parser_1_1basic__signed__numeral.html @@ -136,10 +136,10 @@ std::shared_ptr<  Number.
  - Public Attributes inherited from
stdex::parser::basic_parser< T > - -interval< size_tinterval - Region of the last match.
-  + +stdex::interval< size_tinterval + Region of the last match.
+  @@ -239,7 +239,7 @@ template<clas diff --git a/classstdex_1_1parser_1_1basic__space__cu-members.html b/classstdex_1_1parser_1_1basic__space__cu-members.html index b657d0b04..1d284350c 100644 --- a/classstdex_1_1parser_1_1basic__space__cu-members.html +++ b/classstdex_1_1parser_1_1basic__space__cu-members.html @@ -82,7 +82,7 @@ $(function() {

Additional Inherited Members

- + @@ -93,7 +93,7 @@ $(function() {
basic_parser(const std::locale &locale=std::locale()) (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inline
basic_space_cu(bool invert=false, const std::locale &locale=std::locale()) (defined in stdex::parser::basic_space_cu< T >)stdex::parser::basic_space_cu< T >inline
intervalstdex::parser::basic_parser< T >
intervalstdex::parser::basic_parser< T >
invalidate() (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inlinevirtual
m_invert (defined in stdex::parser::basic_space_cu< T >)stdex::parser::basic_space_cu< T >protected
m_locale (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >protected
diff --git a/classstdex_1_1parser_1_1basic__space__cu.html b/classstdex_1_1parser_1_1basic__space__cu.html index 579c8ce7f..6b73fe8f2 100644 --- a/classstdex_1_1parser_1_1basic__space__cu.html +++ b/classstdex_1_1parser_1_1basic__space__cu.html @@ -131,10 +131,10 @@ std::locale m_locale

Additional Inherited Members

- Public Attributes inherited from stdex::parser::basic_parser< T > - -interval< size_tinterval - Region of the last match.
-  + +stdex::interval< size_tinterval + Region of the last match.

Detailed Description

template<class T>
@@ -198,7 +198,7 @@ template<clas
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 9cd4cabbb..137b82726 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 @@ -82,7 +82,7 @@ $(function() { - + @@ -93,7 +93,7 @@ $(function() {
basic_parser(const std::locale &locale=std::locale()) (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inline
basic_space_or_punct_cu(bool invert=false, const std::locale &locale=std::locale()) (defined in stdex::parser::basic_space_or_punct_cu< T >)stdex::parser::basic_space_or_punct_cu< T >inline
intervalstdex::parser::basic_parser< T >
intervalstdex::parser::basic_parser< T >
invalidate() (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inlinevirtual
m_invert (defined in stdex::parser::basic_space_or_punct_cu< T >)stdex::parser::basic_space_or_punct_cu< T >protected
m_locale (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >protected
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 e801a8a0b..678e43dac 100644 --- a/classstdex_1_1parser_1_1basic__space__or__punct__cu.html +++ b/classstdex_1_1parser_1_1basic__space__or__punct__cu.html @@ -131,10 +131,10 @@ std::locale m_locale

Additional Inherited Members

- Public Attributes inherited from stdex::parser::basic_parser< T > - -interval< size_tinterval - Region of the last match.
-  + +stdex::interval< size_tinterval + Region of the last match.

Detailed Description

template<class T>
@@ -198,7 +198,7 @@ template<clas
diff --git a/classstdex_1_1parser_1_1basic__string-members.html b/classstdex_1_1parser_1_1basic__string-members.html index d57fe27e6..d539fa16f 100644 --- a/classstdex_1_1parser_1_1basic__string-members.html +++ b/classstdex_1_1parser_1_1basic__string-members.html @@ -82,7 +82,7 @@ $(function() { - + @@ -93,7 +93,7 @@ $(function() {
basic_parser(const std::locale &locale=std::locale()) (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inline
basic_string(_In_reads_or_z_(count) const T *str, size_t count=(size_t) -1, const std::locale &locale=std::locale()) (defined in stdex::parser::basic_string< T >)stdex::parser::basic_string< T >inline
intervalstdex::parser::basic_parser< T >
intervalstdex::parser::basic_parser< T >
invalidate() (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inlinevirtual
m_locale (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >protected
m_str (defined in stdex::parser::basic_string< T >)stdex::parser::basic_string< T >protected
diff --git a/classstdex_1_1parser_1_1basic__string.html b/classstdex_1_1parser_1_1basic__string.html index 6fd5eaa79..c449b085d 100644 --- a/classstdex_1_1parser_1_1basic__string.html +++ b/classstdex_1_1parser_1_1basic__string.html @@ -131,10 +131,10 @@ std::locale m_locale

Additional Inherited Members

- Public Attributes inherited from stdex::parser::basic_parser< T > - -interval< size_tinterval - Region of the last match.
-  + +stdex::interval< size_tinterval + Region of the last match.

Detailed Description

template<class T>
@@ -198,7 +198,7 @@ template<clas
diff --git a/classstdex_1_1parser_1_1basic__string__branch-members.html b/classstdex_1_1parser_1_1basic__string__branch-members.html index 791e15869..c55a43f41 100644 --- a/classstdex_1_1parser_1_1basic__string__branch-members.html +++ b/classstdex_1_1parser_1_1basic__string__branch-members.html @@ -90,7 +90,7 @@ $(function() { build(const T *str_z, size_t count) (defined in stdex::parser::basic_string_branch< T, T_parser >)stdex::parser::basic_string_branch< T, T_parser >inlineprotected build(const T *str, va_list params) (defined in stdex::parser::basic_string_branch< T, T_parser >)stdex::parser::basic_string_branch< T, T_parser >inlineprotected hit_offset (defined in stdex::parser::basic_branch< T >)stdex::parser::basic_branch< T > - intervalstdex::parser::basic_parser< T > + intervalstdex::parser::basic_parser< T > invalidate() (defined in stdex::parser::basic_branch< T >)stdex::parser::basic_branch< T >inlinevirtual m_collection (defined in stdex::parser::parser_collection< T >)stdex::parser::parser_collection< T >protected m_locale (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >protected @@ -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 c0dac4f79..94c107fc0 100644 --- a/classstdex_1_1parser_1_1basic__string__branch.html +++ b/classstdex_1_1parser_1_1basic__string__branch.html @@ -163,10 +163,10 @@ Additional Inherited Members size_t hit_offset   - Public Attributes inherited from stdex::parser::basic_parser< T > - -interval< size_tinterval - Region of the last match.
-  + +stdex::interval< size_tinterval + Region of the last match.
- Protected Attributes inherited from stdex::parser::parser_collection< T > std::vector< std::shared_ptr< basic_parser< T > > > m_collection @@ -185,7 +185,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 a65371dcd..85db02d17 100644 --- a/classstdex_1_1parser_1_1basic__time-members.html +++ b/classstdex_1_1parser_1_1basic__time-members.html @@ -83,7 +83,7 @@ $(function() { basic_parser(const std::locale &locale=std::locale()) (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inline basic_time(const std::shared_ptr< basic_integer10< T > > &_hour, const std::shared_ptr< basic_integer10< T > > &_minute, const std::shared_ptr< basic_integer10< T > > &_second, const std::shared_ptr< basic_integer10< T > > &_millisecond, const std::shared_ptr< basic_set< T > > &separator, const std::shared_ptr< basic_parser< T > > &millisecond_separator, const std::locale &locale=std::locale()) (defined in stdex::parser::basic_time< T >)stdex::parser::basic_time< T >inline hour (defined in stdex::parser::basic_time< T >)stdex::parser::basic_time< T > - intervalstdex::parser::basic_parser< T > + intervalstdex::parser::basic_parser< T > invalidate() (defined in stdex::parser::basic_time< T >)stdex::parser::basic_time< T >inlinevirtual m_locale (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >protected m_millisecond_separator (defined in stdex::parser::basic_time< T >)stdex::parser::basic_time< T >protected @@ -98,7 +98,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__time.html b/classstdex_1_1parser_1_1basic__time.html index 7777cc3a3..ae594bcc5 100644 --- a/classstdex_1_1parser_1_1basic__time.html +++ b/classstdex_1_1parser_1_1basic__time.html @@ -133,10 +133,10 @@ std::shared_ptr< basic_integer10< T > > millisecond   - Public Attributes inherited from stdex::parser::basic_parser< T > - -interval< size_tinterval - Region of the last match.
-  + +stdex::interval< size_tinterval + Region of the last match.
+  @@ -242,7 +242,7 @@ template<clas diff --git a/classstdex_1_1parser_1_1basic__url-members.html b/classstdex_1_1parser_1_1basic__url-members.html index ff8aa2a7a..b7d32c805 100644 --- a/classstdex_1_1parser_1_1basic__url-members.html +++ b/classstdex_1_1parser_1_1basic__url-members.html @@ -86,7 +86,7 @@ $(function() { - + @@ -108,7 +108,7 @@ $(function() {

Protected Attributes

file_scheme (defined in stdex::parser::basic_url< T >)stdex::parser::basic_url< T >
ftp_scheme (defined in stdex::parser::basic_url< T >)stdex::parser::basic_url< T >
http_scheme (defined in stdex::parser::basic_url< T >)stdex::parser::basic_url< T >
intervalstdex::parser::basic_parser< T >
intervalstdex::parser::basic_parser< T >
invalidate() (defined in stdex::parser::basic_url< T >)stdex::parser::basic_url< T >inlinevirtual
ipv4_host (defined in stdex::parser::basic_url< T >)stdex::parser::basic_url< T >
ipv6_host (defined in stdex::parser::basic_url< T >)stdex::parser::basic_url< T >
diff --git a/classstdex_1_1parser_1_1basic__url.html b/classstdex_1_1parser_1_1basic__url.html index aaee0043b..f91f0762f 100644 --- a/classstdex_1_1parser_1_1basic__url.html +++ b/classstdex_1_1parser_1_1basic__url.html @@ -154,10 +154,10 @@ std::shared_ptr< basic_parser< T > > path   - Public Attributes inherited from stdex::parser::basic_parser< T > - -interval< size_tinterval - Region of the last match.
-  + +stdex::interval< size_tinterval + Region of the last match.
+  @@ -272,7 +272,7 @@ template<clas 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 e48204b23..69f5092af 100644 --- a/classstdex_1_1parser_1_1basic__url__password__char-members.html +++ b/classstdex_1_1parser_1_1basic__url__password__char-members.html @@ -82,7 +82,7 @@ $(function() {

Protected Attributes

- + @@ -92,7 +92,7 @@ $(function() {
basic_parser(const std::locale &locale=std::locale()) (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inline
basic_url_password_char(const std::locale &locale=std::locale()) (defined in stdex::parser::basic_url_password_char< T >)stdex::parser::basic_url_password_char< T >inline
intervalstdex::parser::basic_parser< T >
intervalstdex::parser::basic_parser< T >
invalidate() (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inlinevirtual
m_locale (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >protected
match(_In_reads_or_z_(end) const T *text, size_t start=0, size_t end=(size_t) -1, int flags=match_default) (defined in stdex::parser::basic_url_password_char< T >)stdex::parser::basic_url_password_char< T >inlinevirtual
diff --git a/classstdex_1_1parser_1_1basic__url__password__char.html b/classstdex_1_1parser_1_1basic__url__password__char.html index 4112e0f38..b056b71c4 100644 --- a/classstdex_1_1parser_1_1basic__url__password__char.html +++ b/classstdex_1_1parser_1_1basic__url__password__char.html @@ -120,10 +120,10 @@ template<clas

Additional Inherited Members

- Public Attributes inherited from stdex::parser::basic_parser< T > - -interval< size_tinterval - Region of the last match.
-  + +stdex::interval< size_tinterval + Region of the last match.
- Protected Attributes inherited from stdex::parser::basic_parser< T > std::locale m_locale @@ -191,7 +191,7 @@ template<clas diff --git a/classstdex_1_1parser_1_1basic__url__path-members.html b/classstdex_1_1parser_1_1basic__url__path-members.html index 8bffdd27f..975787922 100644 --- a/classstdex_1_1parser_1_1basic__url__path-members.html +++ b/classstdex_1_1parser_1_1basic__url__path-members.html @@ -83,7 +83,7 @@ $(function() { basic_parser(const std::locale &locale=std::locale()) (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inline basic_url_path(const std::shared_ptr< basic_parser< T > > &path_char, const std::shared_ptr< basic_parser< T > > &query_start, const std::shared_ptr< basic_parser< T > > &bookmark_start, const std::locale &locale=std::locale()) (defined in stdex::parser::basic_url_path< T >)stdex::parser::basic_url_path< T >inline bookmark (defined in stdex::parser::basic_url_path< T >)stdex::parser::basic_url_path< T > - intervalstdex::parser::basic_parser< T > + intervalstdex::parser::basic_parser< T > invalidate() (defined in stdex::parser::basic_url_path< T >)stdex::parser::basic_url_path< T >inlinevirtual m_bookmark_start (defined in stdex::parser::basic_url_path< T >)stdex::parser::basic_url_path< T >protected m_locale (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >protected @@ -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 420b6cec8..9afbbd92e 100644 --- a/classstdex_1_1parser_1_1basic__url__path.html +++ b/classstdex_1_1parser_1_1basic__url__path.html @@ -130,10 +130,10 @@ Public Attributes stdex::interval< size_tbookmark   - Public Attributes inherited from stdex::parser::basic_parser< T > - -interval< size_tinterval - Region of the last match.
-  + +stdex::interval< size_tinterval + Region of the last match.
+  @@ -242,7 +242,7 @@ template<clas 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 2b6dee078..05ccbb011 100644 --- a/classstdex_1_1parser_1_1basic__url__path__char-members.html +++ b/classstdex_1_1parser_1_1basic__url__path__char-members.html @@ -82,7 +82,7 @@ $(function() {

Protected Attributes

- + @@ -92,7 +92,7 @@ $(function() {
basic_parser(const std::locale &locale=std::locale()) (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inline
basic_url_path_char(const std::locale &locale=std::locale()) (defined in stdex::parser::basic_url_path_char< T >)stdex::parser::basic_url_path_char< T >inline
intervalstdex::parser::basic_parser< T >
intervalstdex::parser::basic_parser< T >
invalidate() (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inlinevirtual
m_locale (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >protected
match(_In_reads_or_z_(end) const T *text, size_t start=0, size_t end=(size_t) -1, int flags=match_default) (defined in stdex::parser::basic_url_path_char< T >)stdex::parser::basic_url_path_char< T >inlinevirtual
diff --git a/classstdex_1_1parser_1_1basic__url__path__char.html b/classstdex_1_1parser_1_1basic__url__path__char.html index a82c590d8..303936b99 100644 --- a/classstdex_1_1parser_1_1basic__url__path__char.html +++ b/classstdex_1_1parser_1_1basic__url__path__char.html @@ -120,10 +120,10 @@ template<clas

Additional Inherited Members

- Public Attributes inherited from stdex::parser::basic_parser< T > - -interval< size_tinterval - Region of the last match.
-  + +stdex::interval< size_tinterval + Region of the last match.
- Protected Attributes inherited from stdex::parser::basic_parser< T > std::locale m_locale @@ -191,7 +191,7 @@ template<clas 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 515914750..3614706fa 100644 --- a/classstdex_1_1parser_1_1basic__url__username__char-members.html +++ b/classstdex_1_1parser_1_1basic__url__username__char-members.html @@ -82,7 +82,7 @@ $(function() { - + @@ -92,7 +92,7 @@ $(function() {
basic_parser(const std::locale &locale=std::locale()) (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inline
basic_url_username_char(const std::locale &locale=std::locale()) (defined in stdex::parser::basic_url_username_char< T >)stdex::parser::basic_url_username_char< T >inline
intervalstdex::parser::basic_parser< T >
intervalstdex::parser::basic_parser< T >
invalidate() (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inlinevirtual
m_locale (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >protected
match(_In_reads_or_z_(end) const T *text, size_t start=0, size_t end=(size_t) -1, int flags=match_default) (defined in stdex::parser::basic_url_username_char< T >)stdex::parser::basic_url_username_char< T >inlinevirtual
diff --git a/classstdex_1_1parser_1_1basic__url__username__char.html b/classstdex_1_1parser_1_1basic__url__username__char.html index 9932b1c8a..df4f0cd1e 100644 --- a/classstdex_1_1parser_1_1basic__url__username__char.html +++ b/classstdex_1_1parser_1_1basic__url__username__char.html @@ -120,10 +120,10 @@ template<clas

Additional Inherited Members

- Public Attributes inherited from stdex::parser::basic_parser< T > - -interval< size_tinterval - Region of the last match.
-  + +stdex::interval< size_tinterval + Region of the last match.
- Protected Attributes inherited from stdex::parser::basic_parser< T > std::locale m_locale @@ -191,7 +191,7 @@ template<clas diff --git a/classstdex_1_1parser_1_1http__agent-members.html b/classstdex_1_1parser_1_1http__agent-members.html index 2e186499a..ffc5a2690 100644 --- a/classstdex_1_1parser_1_1http__agent-members.html +++ b/classstdex_1_1parser_1_1http__agent-members.html @@ -80,7 +80,7 @@ $(function() {

This is the complete list of members for stdex::parser::http_agent, including all inherited members.

- + @@ -88,7 +88,7 @@ $(function() {
intervalstdex::parser::basic_parser< char >
intervalstdex::parser::basic_parser< char >
invalidate() (defined in stdex::parser::http_agent)stdex::parser::http_agentinlinevirtual
match(_In_reads_or_z_(end) const char *text, size_t start=0, size_t end=(size_t) -1, int flags=match_default) (defined in stdex::parser::http_agent)stdex::parser::http_agentinlinevirtual
type (defined in stdex::parser::http_agent)stdex::parser::http_agent
diff --git a/classstdex_1_1parser_1_1http__agent.html b/classstdex_1_1parser_1_1http__agent.html index dad37abc0..9daef6d11 100644 --- a/classstdex_1_1parser_1_1http__agent.html +++ b/classstdex_1_1parser_1_1http__agent.html @@ -122,10 +122,10 @@ Public Attributes stdex::interval< size_tversion   - Public Attributes inherited from stdex::parser::basic_parser< char > - -interval< size_tinterval - Region of the last match.
-  + +stdex::interval< size_tinterval + Region of the last match.
+  @@ -220,7 +220,7 @@ std::locale  - - - + + + @@ -184,7 +184,7 @@ std::locale  - - - + + + @@ -184,7 +184,7 @@ std::locale  - - - + + +

Additional Inherited Members

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 9fad7e8db..27c8bbf1d 100644 --- a/classstdex_1_1parser_1_1http__any__type-members.html +++ b/classstdex_1_1parser_1_1http__any__type-members.html @@ -80,12 +80,12 @@ $(function() {

This is the complete list of members for stdex::parser::http_any_type, including all inherited members.

- +
intervalstdex::parser::basic_parser< char >
intervalstdex::parser::basic_parser< char >
match(_In_reads_or_z_(end) const char *text, size_t start=0, size_t end=(size_t) -1, int flags=match_default) (defined in stdex::parser::http_any_type)stdex::parser::http_any_typeinlinevirtual
diff --git a/classstdex_1_1parser_1_1http__any__type.html b/classstdex_1_1parser_1_1http__any__type.html index baad360c7..5fca3df46 100644 --- a/classstdex_1_1parser_1_1http__any__type.html +++ b/classstdex_1_1parser_1_1http__any__type.html @@ -116,10 +116,10 @@ Public Member Functions

Additional Inherited Members

- Public Attributes inherited from stdex::parser::basic_parser< char >
-interval< size_tinterval
 Region of the last match.
 
+stdex::interval< size_tinterval
 Region of the last match.
 
- Protected Attributes inherited from stdex::parser::basic_parser< char >
std::locale m_locale
m_locale diff --git a/classstdex_1_1parser_1_1http__asterisk-members.html b/classstdex_1_1parser_1_1http__asterisk-members.html index 89011ac3a..a039b667e 100644 --- a/classstdex_1_1parser_1_1http__asterisk-members.html +++ b/classstdex_1_1parser_1_1http__asterisk-members.html @@ -80,12 +80,12 @@ $(function() {

This is the complete list of members for stdex::parser::http_asterisk, including all inherited members.

- +
intervalstdex::parser::basic_parser< char >
intervalstdex::parser::basic_parser< char >
match(_In_reads_or_z_(end) const char *text, size_t start=0, size_t end=(size_t) -1, int flags=match_default) (defined in stdex::parser::http_asterisk)stdex::parser::http_asteriskinlinevirtual
diff --git a/classstdex_1_1parser_1_1http__asterisk.html b/classstdex_1_1parser_1_1http__asterisk.html index 79d7c2bd9..2532a7fe2 100644 --- a/classstdex_1_1parser_1_1http__asterisk.html +++ b/classstdex_1_1parser_1_1http__asterisk.html @@ -116,10 +116,10 @@ Public Member Functions

Additional Inherited Members

- Public Attributes inherited from stdex::parser::basic_parser< char >
-interval< size_tinterval
 Region of the last match.
 
+stdex::interval< size_tinterval
 Region of the last match.
 
- Protected Attributes inherited from stdex::parser::basic_parser< char >
std::locale m_locale
m_locale diff --git a/classstdex_1_1parser_1_1http__cookie-members.html b/classstdex_1_1parser_1_1http__cookie-members.html index a52debe64..1d0544929 100644 --- a/classstdex_1_1parser_1_1http__cookie-members.html +++ b/classstdex_1_1parser_1_1http__cookie-members.html @@ -80,7 +80,7 @@ $(function() {

This is the complete list of members for stdex::parser::http_cookie, including all inherited members.

- + @@ -90,7 +90,7 @@ $(function() {
intervalstdex::parser::basic_parser< char >
intervalstdex::parser::basic_parser< char >
invalidate() (defined in stdex::parser::http_cookie)stdex::parser::http_cookieinlinevirtual
m_space (defined in stdex::parser::http_cookie)stdex::parser::http_cookieprotected
match(_In_reads_or_z_(end) const char *text, size_t start=0, size_t end=(size_t) -1, int flags=match_default) (defined in stdex::parser::http_cookie)stdex::parser::http_cookieinlinevirtual
diff --git a/classstdex_1_1parser_1_1http__cookie.html b/classstdex_1_1parser_1_1http__cookie.html index 22eee3160..98609a733 100644 --- a/classstdex_1_1parser_1_1http__cookie.html +++ b/classstdex_1_1parser_1_1http__cookie.html @@ -129,10 +129,10 @@ std::list<
 List of cookie parameters.
 
- Public Attributes inherited from stdex::parser::basic_parser< char >
-interval< size_tinterval
 Region of the last match.
 
+stdex::interval< size_tinterval
 Region of the last match.
 
@@ -230,7 +230,7 @@ std::locale http_value  - - - + + +

Protected Attributes

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 66196ed7c..a949d6ff1 100644 --- a/classstdex_1_1parser_1_1http__cookie__parameter-members.html +++ b/classstdex_1_1parser_1_1http__cookie__parameter-members.html @@ -80,7 +80,7 @@ $(function() {

This is the complete list of members for stdex::parser::http_cookie_parameter, including all inherited members.

- + @@ -89,7 +89,7 @@ $(function() {
intervalstdex::parser::basic_parser< char >
intervalstdex::parser::basic_parser< char >
invalidate() (defined in stdex::parser::http_cookie_parameter)stdex::parser::http_cookie_parameterinlinevirtual
m_space (defined in stdex::parser::http_cookie_parameter)stdex::parser::http_cookie_parameterprotected
match(_In_reads_or_z_(end) const char *text, size_t start=0, size_t end=(size_t) -1, int flags=match_default) (defined in stdex::parser::http_cookie_parameter)stdex::parser::http_cookie_parameterinlinevirtual
diff --git a/classstdex_1_1parser_1_1http__cookie__parameter.html b/classstdex_1_1parser_1_1http__cookie__parameter.html index f870c38e4..381c8c569 100644 --- a/classstdex_1_1parser_1_1http__cookie__parameter.html +++ b/classstdex_1_1parser_1_1http__cookie__parameter.html @@ -123,10 +123,10 @@ Public Attributes
value
 
- Public Attributes inherited from stdex::parser::basic_parser< char >
-interval< size_tinterval
 Region of the last match.
 
+stdex::interval< size_tinterval
 Region of the last match.
 
@@ -224,7 +224,7 @@ std::locale stdex::interval< size_t >  - - - + + +

Protected Attributes

m_locale diff --git a/classstdex_1_1parser_1_1http__header-members.html b/classstdex_1_1parser_1_1http__header-members.html index 2b0ba2038..ed7ca6ace 100644 --- a/classstdex_1_1parser_1_1http__header-members.html +++ b/classstdex_1_1parser_1_1http__header-members.html @@ -80,7 +80,7 @@ $(function() {

This is the complete list of members for stdex::parser::http_header, including all inherited members.

- + @@ -89,7 +89,7 @@ $(function() {
intervalstdex::parser::basic_parser< char >
intervalstdex::parser::basic_parser< char >
invalidate() (defined in stdex::parser::http_header)stdex::parser::http_headerinlinevirtual
m_line_break (defined in stdex::parser::http_header)stdex::parser::http_headerprotected
match(_In_reads_or_z_(end) const char *text, size_t start=0, size_t end=(size_t) -1, int flags=match_default) (defined in stdex::parser::http_header)stdex::parser::http_headerinlinevirtual
diff --git a/classstdex_1_1parser_1_1http__header.html b/classstdex_1_1parser_1_1http__header.html index f3a591a11..82a681798 100644 --- a/classstdex_1_1parser_1_1http__header.html +++ b/classstdex_1_1parser_1_1http__header.html @@ -123,10 +123,10 @@ Public Attributes
value
 
- Public Attributes inherited from stdex::parser::basic_parser< char >
-interval< size_tinterval
 Region of the last match.
 
+stdex::interval< size_tinterval
 Region of the last match.
 
@@ -224,7 +224,7 @@ std::locale  std::vector< stdex::interval< size_t > >  - - - + + +

Protected Attributes

m_locale diff --git a/classstdex_1_1parser_1_1http__language-members.html b/classstdex_1_1parser_1_1http__language-members.html index 9058c158f..9369a0d51 100644 --- a/classstdex_1_1parser_1_1http__language-members.html +++ b/classstdex_1_1parser_1_1http__language-members.html @@ -81,13 +81,13 @@ $(function() {

This is the complete list of members for stdex::parser::http_language, including all inherited members.

- +
components (defined in stdex::parser::http_language)stdex::parser::http_language
intervalstdex::parser::basic_parser< char >
intervalstdex::parser::basic_parser< char >
invalidate() (defined in stdex::parser::http_language)stdex::parser::http_languageinlinevirtual
match(_In_reads_or_z_(end) const char *text, size_t start=0, size_t end=(size_t) -1, int flags=match_default) (defined in stdex::parser::http_language)stdex::parser::http_languageinlinevirtual
diff --git a/classstdex_1_1parser_1_1http__language.html b/classstdex_1_1parser_1_1http__language.html index cebdaaada..bd30871f4 100644 --- a/classstdex_1_1parser_1_1http__language.html +++ b/classstdex_1_1parser_1_1http__language.html @@ -119,10 +119,10 @@ Public Attributes
components
 
- Public Attributes inherited from stdex::parser::basic_parser< char >
-interval< size_tinterval
 Region of the last match.
 
+stdex::interval< size_tinterval
 Region of the last match.
 
@@ -217,7 +217,7 @@ std::locale  - - - + + + @@ -184,7 +184,7 @@ std::locale http_token  - - - + + +

Additional Inherited Members

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 acf6a1530..26b7a53a5 100644 --- a/classstdex_1_1parser_1_1http__line__break-members.html +++ b/classstdex_1_1parser_1_1http__line__break-members.html @@ -80,12 +80,12 @@ $(function() {

This is the complete list of members for stdex::parser::http_line_break, including all inherited members.

- +
intervalstdex::parser::basic_parser< char >
intervalstdex::parser::basic_parser< char >
match(_In_reads_or_z_(end) const char *text, size_t start=0, size_t end=(size_t) -1, int flags=match_default) (defined in stdex::parser::http_line_break)stdex::parser::http_line_breakinlinevirtual
diff --git a/classstdex_1_1parser_1_1http__line__break.html b/classstdex_1_1parser_1_1http__line__break.html index 5d60a4a3e..ebb166df3 100644 --- a/classstdex_1_1parser_1_1http__line__break.html +++ b/classstdex_1_1parser_1_1http__line__break.html @@ -116,10 +116,10 @@ Public Member Functions

Additional Inherited Members

- Public Attributes inherited from stdex::parser::basic_parser< char >
-interval< size_tinterval
 Region of the last match.
 
+stdex::interval< size_tinterval
 Region of the last match.
 
- Protected Attributes inherited from stdex::parser::basic_parser< char >
std::locale m_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 70a851335..8c249cd6b 100644 --- a/classstdex_1_1parser_1_1http__media__range-members.html +++ b/classstdex_1_1parser_1_1http__media__range-members.html @@ -80,7 +80,7 @@ $(function() {

This is the complete list of members for stdex::parser::http_media_range, including all inherited members.

- + @@ -89,7 +89,7 @@ $(function() {
intervalstdex::parser::basic_parser< char >
intervalstdex::parser::basic_parser< char >
invalidate() (defined in stdex::parser::http_media_range)stdex::parser::http_media_rangeinlinevirtual
m_space (defined in stdex::parser::http_media_range)stdex::parser::http_media_rangeprotected
match(_In_reads_or_z_(end) const char *text, size_t start=0, size_t end=(size_t) -1, int flags=match_default) (defined in stdex::parser::http_media_range)stdex::parser::http_media_rangeinlinevirtual
diff --git a/classstdex_1_1parser_1_1http__media__range.html b/classstdex_1_1parser_1_1http__media__range.html index 7bb7e2c99..7cb179b18 100644 --- a/classstdex_1_1parser_1_1http__media__range.html +++ b/classstdex_1_1parser_1_1http__media__range.html @@ -124,10 +124,10 @@ Public Attributes
subtype
 
- Public Attributes inherited from stdex::parser::basic_parser< char >
-interval< size_tinterval
 Region of the last match.
 
+stdex::interval< size_tinterval
 Region of the last match.
 
@@ -225,7 +225,7 @@ std::locale  - - - + + +

Protected Attributes

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 92b96760b..4c886487f 100644 --- a/classstdex_1_1parser_1_1http__media__type-members.html +++ b/classstdex_1_1parser_1_1http__media__type-members.html @@ -80,7 +80,7 @@ $(function() {

This is the complete list of members for stdex::parser::http_media_type, including all inherited members.

- + @@ -90,7 +90,7 @@ $(function() {
intervalstdex::parser::basic_parser< char >
intervalstdex::parser::basic_parser< char >
invalidate() (defined in stdex::parser::http_media_type)stdex::parser::http_media_typeinlinevirtual
m_space (defined in stdex::parser::http_media_range)stdex::parser::http_media_rangeprotected
match(_In_reads_or_z_(end) const char *text, size_t start=0, size_t end=(size_t) -1, int flags=match_default) (defined in stdex::parser::http_media_type)stdex::parser::http_media_typeinlinevirtual
diff --git a/classstdex_1_1parser_1_1http__media__type.html b/classstdex_1_1parser_1_1http__media__type.html index d533a2736..c17824bea 100644 --- a/classstdex_1_1parser_1_1http__media__type.html +++ b/classstdex_1_1parser_1_1http__media__type.html @@ -127,10 +127,10 @@ std::list< http_token 
subtype
 
- Public Attributes inherited from stdex::parser::basic_parser< char >
-interval< size_tinterval
 Region of the last match.
 
+stdex::interval< size_tinterval
 Region of the last match.
 
@@ -229,7 +229,7 @@ std::locale  - - - + + +

Additional Inherited Members

m_locale diff --git a/classstdex_1_1parser_1_1http__parameter-members.html b/classstdex_1_1parser_1_1http__parameter-members.html index dd9bc865e..e9b39846e 100644 --- a/classstdex_1_1parser_1_1http__parameter-members.html +++ b/classstdex_1_1parser_1_1http__parameter-members.html @@ -80,7 +80,7 @@ $(function() {

This is the complete list of members for stdex::parser::http_parameter, including all inherited members.

- + @@ -89,7 +89,7 @@ $(function() {
intervalstdex::parser::basic_parser< char >
intervalstdex::parser::basic_parser< char >
invalidate() (defined in stdex::parser::http_parameter)stdex::parser::http_parameterinlinevirtual
m_space (defined in stdex::parser::http_parameter)stdex::parser::http_parameterprotected
match(_In_reads_or_z_(end) const char *text, size_t start=0, size_t end=(size_t) -1, int flags=match_default) (defined in stdex::parser::http_parameter)stdex::parser::http_parameterinlinevirtual
diff --git a/classstdex_1_1parser_1_1http__parameter.html b/classstdex_1_1parser_1_1http__parameter.html index 561de11db..3e8a552b2 100644 --- a/classstdex_1_1parser_1_1http__parameter.html +++ b/classstdex_1_1parser_1_1http__parameter.html @@ -125,10 +125,10 @@ Public Attributes
 Parameter value.
 
- Public Attributes inherited from stdex::parser::basic_parser< char >
-interval< size_tinterval
 Region of the last match.
 
+stdex::interval< size_tinterval
 Region of the last match.
 
@@ -226,7 +226,7 @@ std::locale  - - - + + +

Protected Attributes

m_locale diff --git a/classstdex_1_1parser_1_1http__protocol-members.html b/classstdex_1_1parser_1_1http__protocol-members.html index de70406ff..caff02850 100644 --- a/classstdex_1_1parser_1_1http__protocol-members.html +++ b/classstdex_1_1parser_1_1http__protocol-members.html @@ -81,7 +81,7 @@ $(function() {

This is the complete list of members for stdex::parser::http_protocol, including all inherited members.

- + @@ -91,7 +91,7 @@ $(function() {
http_protocol(const std::locale &locale=std::locale()) (defined in stdex::parser::http_protocol)stdex::parser::http_protocolinline
intervalstdex::parser::basic_parser< char >
intervalstdex::parser::basic_parser< char >
invalidate() (defined in stdex::parser::http_protocol)stdex::parser::http_protocolinlinevirtual
match(_In_reads_or_z_(end) const char *text, size_t start=0, size_t end=(size_t) -1, int flags=match_default) (defined in stdex::parser::http_protocol)stdex::parser::http_protocolinlinevirtual
type (defined in stdex::parser::http_protocol)stdex::parser::http_protocol
diff --git a/classstdex_1_1parser_1_1http__protocol.html b/classstdex_1_1parser_1_1http__protocol.html index a7f993acd..2228400f5 100644 --- a/classstdex_1_1parser_1_1http__protocol.html +++ b/classstdex_1_1parser_1_1http__protocol.html @@ -132,10 +132,10 @@ Public Attributes
 HTTP protocol version: 0x100 = 1.0, 0x101 = 1.1...
 
- Public Attributes inherited from stdex::parser::basic_parser< char >
-interval< size_tinterval
 Region of the last match.
 
+stdex::interval< size_tinterval
 Region of the last match.
 
@@ -230,7 +230,7 @@ std::locale  - - - + + +

Additional Inherited Members

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 e012c9218..62234b29b 100644 --- a/classstdex_1_1parser_1_1http__quoted__string-members.html +++ b/classstdex_1_1parser_1_1http__quoted__string-members.html @@ -81,14 +81,14 @@ $(function() {

This is the complete list of members for stdex::parser::http_quoted_string, including all inherited members.

- +
contentstdex::parser::http_quoted_string
intervalstdex::parser::basic_parser< char >
intervalstdex::parser::basic_parser< char >
invalidate() (defined in stdex::parser::http_quoted_string)stdex::parser::http_quoted_stringinlinevirtual
m_chr (defined in stdex::parser::http_quoted_string)stdex::parser::http_quoted_stringprotected
match(_In_reads_or_z_(end) const char *text, size_t start=0, size_t end=(size_t) -1, int flags=match_default) (defined in stdex::parser::http_quoted_string)stdex::parser::http_quoted_stringinlinevirtual
diff --git a/classstdex_1_1parser_1_1http__quoted__string.html b/classstdex_1_1parser_1_1http__quoted__string.html index e45670f7b..80460bca6 100644 --- a/classstdex_1_1parser_1_1http__quoted__string.html +++ b/classstdex_1_1parser_1_1http__quoted__string.html @@ -121,10 +121,10 @@ Public Attributes
 String content (without quotes)
 
- Public Attributes inherited from stdex::parser::basic_parser< char >
-interval< size_tinterval
 Region of the last match.
 
+stdex::interval< size_tinterval
 Region of the last match.
 
@@ -222,7 +222,7 @@ std::locale http_protocol  - - - + + +

Protected Attributes

m_locale diff --git a/classstdex_1_1parser_1_1http__request-members.html b/classstdex_1_1parser_1_1http__request-members.html index 726e7157a..76e0cc3ad 100644 --- a/classstdex_1_1parser_1_1http__request-members.html +++ b/classstdex_1_1parser_1_1http__request-members.html @@ -81,7 +81,7 @@ $(function() {

This is the complete list of members for stdex::parser::http_request, including all inherited members.

- + @@ -91,7 +91,7 @@ $(function() {
http_request(const std::locale &locale=std::locale()) (defined in stdex::parser::http_request)stdex::parser::http_requestinline
intervalstdex::parser::basic_parser< char >
intervalstdex::parser::basic_parser< char >
invalidate() (defined in stdex::parser::http_request)stdex::parser::http_requestinlinevirtual
m_line_break (defined in stdex::parser::http_request)stdex::parser::http_requestprotected
match(_In_reads_or_z_(end) const char *text, size_t start=0, size_t end=(size_t) -1, int flags=match_default) (defined in stdex::parser::http_request)stdex::parser::http_requestinlinevirtual
diff --git a/classstdex_1_1parser_1_1http__request.html b/classstdex_1_1parser_1_1http__request.html index f3b738879..a3772d464 100644 --- a/classstdex_1_1parser_1_1http__request.html +++ b/classstdex_1_1parser_1_1http__request.html @@ -129,10 +129,10 @@ Public Attributes
protocol
 
- Public Attributes inherited from stdex::parser::basic_parser< char >
-interval< size_tinterval
 Region of the last match.
 
+stdex::interval< size_tinterval
 Region of the last match.
 
@@ -230,7 +230,7 @@ std::locale  - - - + + +

Protected Attributes

m_locale diff --git a/classstdex_1_1parser_1_1http__space-members.html b/classstdex_1_1parser_1_1http__space-members.html index dc476855f..89a21a04e 100644 --- a/classstdex_1_1parser_1_1http__space-members.html +++ b/classstdex_1_1parser_1_1http__space-members.html @@ -80,13 +80,13 @@ $(function() {

This is the complete list of members for stdex::parser::http_space, including all inherited members.

- +
intervalstdex::parser::basic_parser< char >
intervalstdex::parser::basic_parser< char >
m_line_break (defined in stdex::parser::http_space)stdex::parser::http_spaceprotected
match(_In_reads_or_z_(end) const char *text, size_t start=0, size_t end=(size_t) -1, int flags=match_default) (defined in stdex::parser::http_space)stdex::parser::http_spaceinlinevirtual
diff --git a/classstdex_1_1parser_1_1http__space.html b/classstdex_1_1parser_1_1http__space.html index 32de5cb1d..f2d95463b 100644 --- a/classstdex_1_1parser_1_1http__space.html +++ b/classstdex_1_1parser_1_1http__space.html @@ -127,10 +127,10 @@ std::locale 
m_locale

Additional Inherited Members

- Public Attributes inherited from stdex::parser::basic_parser< char >
-interval< size_tinterval
 Region of the last match.
 
+stdex::interval< size_tinterval
 Region of the last match.
 

Detailed Description

Test for HTTP space (RFC2616: LWS)

@@ -191,7 +191,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 c41babea6..7fdb88b34 100644 --- a/classstdex_1_1parser_1_1http__text__char-members.html +++ b/classstdex_1_1parser_1_1http__text__char-members.html @@ -80,13 +80,13 @@ $(function() {

This is the complete list of members for stdex::parser::http_text_char, including all inherited members.

- +
intervalstdex::parser::basic_parser< char >
intervalstdex::parser::basic_parser< char >
m_space (defined in stdex::parser::http_text_char)stdex::parser::http_text_charprotected
match(_In_reads_or_z_(end) const char *text, size_t start=0, size_t end=(size_t) -1, int flags=match_default) (defined in stdex::parser::http_text_char)stdex::parser::http_text_charinlinevirtual
diff --git a/classstdex_1_1parser_1_1http__text__char.html b/classstdex_1_1parser_1_1http__text__char.html index dbe13108a..e4bbc0420 100644 --- a/classstdex_1_1parser_1_1http__text__char.html +++ b/classstdex_1_1parser_1_1http__text__char.html @@ -127,10 +127,10 @@ std::locale m_locale

Additional Inherited Members

- Public Attributes inherited from stdex::parser::basic_parser< char > - -interval< size_tinterval - Region of the last match.
-  + +stdex::interval< size_tinterval + Region of the last match.

Detailed Description

Test for HTTP text character (RFC2616: TEXT)

@@ -191,7 +191,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 50bd16e3b..8a50e212f 100644 --- a/classstdex_1_1parser_1_1http__token-members.html +++ b/classstdex_1_1parser_1_1http__token-members.html @@ -80,12 +80,12 @@ $(function() {

This is the complete list of members for stdex::parser::http_token, including all inherited members.

- +
intervalstdex::parser::basic_parser< char >
intervalstdex::parser::basic_parser< char >
match(_In_reads_or_z_(end) const char *text, size_t start=0, size_t end=(size_t) -1, int flags=match_default) (defined in stdex::parser::http_token)stdex::parser::http_tokeninlinevirtual
diff --git a/classstdex_1_1parser_1_1http__token.html b/classstdex_1_1parser_1_1http__token.html index 2e0f80646..9873d405d 100644 --- a/classstdex_1_1parser_1_1http__token.html +++ b/classstdex_1_1parser_1_1http__token.html @@ -116,10 +116,10 @@ Public Member Functions

Additional Inherited Members

- Public Attributes inherited from stdex::parser::basic_parser< char > - -interval< size_tinterval - Region of the last match.
-  + +stdex::interval< size_tinterval + Region of the last match.
- Protected Attributes inherited from stdex::parser::basic_parser< char > std::locale m_locale @@ -184,7 +184,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 aabdd89da..0b161eca6 100644 --- a/classstdex_1_1parser_1_1http__url-members.html +++ b/classstdex_1_1parser_1_1http__url-members.html @@ -81,7 +81,7 @@ $(function() {

This is the complete list of members for stdex::parser::http_url, including all inherited members.

- + @@ -91,7 +91,7 @@ $(function() {
http_url(const std::locale &locale=std::locale()) (defined in stdex::parser::http_url)stdex::parser::http_urlinline
intervalstdex::parser::basic_parser< char >
intervalstdex::parser::basic_parser< char >
invalidate() (defined in stdex::parser::http_url)stdex::parser::http_urlinlinevirtual
match(_In_reads_or_z_(end) const char *text, size_t start=0, size_t end=(size_t) -1, int flags=match_default) (defined in stdex::parser::http_url)stdex::parser::http_urlinlinevirtual
params (defined in stdex::parser::http_url)stdex::parser::http_url
diff --git a/classstdex_1_1parser_1_1http__url.html b/classstdex_1_1parser_1_1http__url.html index fced268ba..0d7db3a6e 100644 --- a/classstdex_1_1parser_1_1http__url.html +++ b/classstdex_1_1parser_1_1http__url.html @@ -131,10 +131,10 @@ Public Attributes std::list< http_url_parameterparams   - Public Attributes inherited from stdex::parser::basic_parser< char > - -interval< size_tinterval - Region of the last match.
-  + +stdex::interval< size_tinterval + Region of the last match.
+  @@ -229,7 +229,7 @@ std::locale stdex::interval< size_t >  - - - + + +

Additional Inherited Members

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 84864383e..2dcef7330 100644 --- a/classstdex_1_1parser_1_1http__url__parameter-members.html +++ b/classstdex_1_1parser_1_1http__url__parameter-members.html @@ -80,7 +80,7 @@ $(function() {

This is the complete list of members for stdex::parser::http_url_parameter, including all inherited members.

- + @@ -88,7 +88,7 @@ $(function() {
intervalstdex::parser::basic_parser< char >
intervalstdex::parser::basic_parser< char >
invalidate() (defined in stdex::parser::http_url_parameter)stdex::parser::http_url_parameterinlinevirtual
match(_In_reads_or_z_(end) const char *text, size_t start=0, size_t end=(size_t) -1, int flags=match_default) (defined in stdex::parser::http_url_parameter)stdex::parser::http_url_parameterinlinevirtual
name (defined in stdex::parser::http_url_parameter)stdex::parser::http_url_parameter
diff --git a/classstdex_1_1parser_1_1http__url__parameter.html b/classstdex_1_1parser_1_1http__url__parameter.html index b686e5aea..728a39c6d 100644 --- a/classstdex_1_1parser_1_1http__url__parameter.html +++ b/classstdex_1_1parser_1_1http__url__parameter.html @@ -122,10 +122,10 @@ Public Attributes
value
 
- Public Attributes inherited from stdex::parser::basic_parser< char >
-interval< size_tinterval
 Region of the last match.
 
+stdex::interval< size_tinterval
 Region of the last match.
 
@@ -220,7 +220,7 @@ std::locale  - - - + + +

Additional Inherited Members

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 c8b03512c..8c7df5ebd 100644 --- a/classstdex_1_1parser_1_1http__url__path-members.html +++ b/classstdex_1_1parser_1_1http__url__path-members.html @@ -80,14 +80,14 @@ $(function() {

This is the complete list of members for stdex::parser::http_url_path, including all inherited members.

- +
intervalstdex::parser::basic_parser< char >
intervalstdex::parser::basic_parser< char >
invalidate() (defined in stdex::parser::http_url_path)stdex::parser::http_url_pathinlinevirtual
match(_In_reads_or_z_(end) const char *text, size_t start=0, size_t end=(size_t) -1, int flags=match_default) (defined in stdex::parser::http_url_path)stdex::parser::http_url_pathinlinevirtual
segmentsstdex::parser::http_url_path
diff --git a/classstdex_1_1parser_1_1http__url__path.html b/classstdex_1_1parser_1_1http__url__path.html index 461e80eab..d7145aa14 100644 --- a/classstdex_1_1parser_1_1http__url__path.html +++ b/classstdex_1_1parser_1_1http__url__path.html @@ -120,10 +120,10 @@ std::vector<
 Path segments.
 
- Public Attributes inherited from stdex::parser::basic_parser< char >
-interval< size_tinterval
 Region of the last match.
 
+stdex::interval< size_tinterval
 Region of the last match.
 
@@ -218,7 +218,7 @@ std::locale  - - - + + + @@ -184,7 +184,7 @@ std::locale uint16_t  - - - + + +

Additional Inherited Members

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 bc59e9531..24b3f19bd 100644 --- a/classstdex_1_1parser_1_1http__url__path__segment-members.html +++ b/classstdex_1_1parser_1_1http__url__path__segment-members.html @@ -80,12 +80,12 @@ $(function() {

This is the complete list of members for stdex::parser::http_url_path_segment, including all inherited members.

- +
intervalstdex::parser::basic_parser< char >
intervalstdex::parser::basic_parser< char >
match(_In_reads_or_z_(end) const char *text, size_t start=0, size_t end=(size_t) -1, int flags=match_default) (defined in stdex::parser::http_url_path_segment)stdex::parser::http_url_path_segmentinlinevirtual
diff --git a/classstdex_1_1parser_1_1http__url__path__segment.html b/classstdex_1_1parser_1_1http__url__path__segment.html index 495942db3..57172ec6c 100644 --- a/classstdex_1_1parser_1_1http__url__path__segment.html +++ b/classstdex_1_1parser_1_1http__url__path__segment.html @@ -116,10 +116,10 @@ Public Member Functions

Additional Inherited Members

- Public Attributes inherited from stdex::parser::basic_parser< char >
-interval< size_tinterval
 Region of the last match.
 
+stdex::interval< size_tinterval
 Region of the last match.
 
- Protected Attributes inherited from stdex::parser::basic_parser< char >
std::locale m_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 fc67b8df9..37599a9d6 100644 --- a/classstdex_1_1parser_1_1http__url__port-members.html +++ b/classstdex_1_1parser_1_1http__url__port-members.html @@ -81,14 +81,14 @@ $(function() {

This is the complete list of members for stdex::parser::http_url_port, including all inherited members.

- +
http_url_port(const std::locale &locale=std::locale()) (defined in stdex::parser::http_url_port)stdex::parser::http_url_portinline
intervalstdex::parser::basic_parser< char >
intervalstdex::parser::basic_parser< char >
invalidate() (defined in stdex::parser::http_url_port)stdex::parser::http_url_portinlinevirtual
match(_In_reads_or_z_(end) const char *text, size_t start=0, size_t end=(size_t) -1, int flags=match_default) (defined in stdex::parser::http_url_port)stdex::parser::http_url_portinlinevirtual
value (defined in stdex::parser::http_url_port)stdex::parser::http_url_port
diff --git a/classstdex_1_1parser_1_1http__url__port.html b/classstdex_1_1parser_1_1http__url__port.html index b79e5a655..fd98d9637 100644 --- a/classstdex_1_1parser_1_1http__url__port.html +++ b/classstdex_1_1parser_1_1http__url__port.html @@ -122,10 +122,10 @@ Public Attributes
value
 
- Public Attributes inherited from stdex::parser::basic_parser< char >
-interval< size_tinterval
 Region of the last match.
 
+stdex::interval< size_tinterval
 Region of the last match.
 
@@ -220,7 +220,7 @@ std::locale  - - - + + + @@ -184,7 +184,7 @@ std::locale  - - - + + +

Additional Inherited Members

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 641c9420e..bfa7ac950 100644 --- a/classstdex_1_1parser_1_1http__url__server-members.html +++ b/classstdex_1_1parser_1_1http__url__server-members.html @@ -80,12 +80,12 @@ $(function() {

This is the complete list of members for stdex::parser::http_url_server, including all inherited members.

- +
intervalstdex::parser::basic_parser< char >
intervalstdex::parser::basic_parser< char >
match(_In_reads_or_z_(end) const char *text, size_t start=0, size_t end=(size_t) -1, int flags=match_default) (defined in stdex::parser::http_url_server)stdex::parser::http_url_serverinlinevirtual
diff --git a/classstdex_1_1parser_1_1http__url__server.html b/classstdex_1_1parser_1_1http__url__server.html index 4071b00d8..6125886ca 100644 --- a/classstdex_1_1parser_1_1http__url__server.html +++ b/classstdex_1_1parser_1_1http__url__server.html @@ -116,10 +116,10 @@ Public Member Functions

Additional Inherited Members

- Public Attributes inherited from stdex::parser::basic_parser< char >
-interval< size_tinterval
 Region of the last match.
 
+stdex::interval< size_tinterval
 Region of the last match.
 
- Protected Attributes inherited from stdex::parser::basic_parser< char >
std::locale m_locale
m_locale diff --git a/classstdex_1_1parser_1_1http__value-members.html b/classstdex_1_1parser_1_1http__value-members.html index ec9ce00a1..f18560bcd 100644 --- a/classstdex_1_1parser_1_1http__value-members.html +++ b/classstdex_1_1parser_1_1http__value-members.html @@ -80,7 +80,7 @@ $(function() {

This is the complete list of members for stdex::parser::http_value, including all inherited members.

- + @@ -88,7 +88,7 @@ $(function() {
intervalstdex::parser::basic_parser< char >
intervalstdex::parser::basic_parser< char >
invalidate() (defined in stdex::parser::http_value)stdex::parser::http_valueinlinevirtual
match(_In_reads_or_z_(end) const char *text, size_t start=0, size_t end=(size_t) -1, int flags=match_default) (defined in stdex::parser::http_value)stdex::parser::http_valueinlinevirtual
stringstdex::parser::http_value
diff --git a/classstdex_1_1parser_1_1http__value.html b/classstdex_1_1parser_1_1http__value.html index ca8d2e4e4..c3cf76dc8 100644 --- a/classstdex_1_1parser_1_1http__value.html +++ b/classstdex_1_1parser_1_1http__value.html @@ -124,10 +124,10 @@ Public Attributes
 Value when matched as token.
 
- Public Attributes inherited from stdex::parser::basic_parser< char >
-interval< size_tinterval
 Region of the last match.
 
+stdex::interval< size_tinterval
 Region of the last match.
 
@@ -222,7 +222,7 @@ std::locale 

Additional Inherited Members

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 3223caa97..2b3bbec40 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 32c109c3b..10fbe109c 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< _Key, T >

Collection o

diff --git a/classstdex_1_1parser_1_1http__weight-members.html b/classstdex_1_1parser_1_1http__weight-members.html index d3817d86d..c847523a5 100644 --- a/classstdex_1_1parser_1_1http__weight-members.html +++ b/classstdex_1_1parser_1_1http__weight-members.html @@ -81,14 +81,14 @@ $(function() {

This is the complete list of members for stdex::parser::http_weight, including all inherited members.

- +
http_weight(const std::locale &locale=std::locale()) (defined in stdex::parser::http_weight)stdex::parser::http_weightinline
intervalstdex::parser::basic_parser< char >
intervalstdex::parser::basic_parser< char >
invalidate() (defined in stdex::parser::http_weight)stdex::parser::http_weightinlinevirtual
match(_In_reads_or_z_(end) const char *text, size_t start=0, size_t end=(size_t) -1, int flags=match_default) (defined in stdex::parser::http_weight)stdex::parser::http_weightinlinevirtual
valuestdex::parser::http_weight
diff --git a/classstdex_1_1parser_1_1http__weight.html b/classstdex_1_1parser_1_1http__weight.html index df3e15956..604c9535a 100644 --- a/classstdex_1_1parser_1_1http__weight.html +++ b/classstdex_1_1parser_1_1http__weight.html @@ -123,10 +123,10 @@ Public Attributes  Calculated value of the weight factor.
  - Public Attributes inherited from stdex::parser::basic_parser< char > - -interval< size_tinterval - Region of the last match.
-  + +stdex::interval< size_tinterval + Region of the last match.
+  @@ -221,7 +221,7 @@ std::locale  - +

Additional Inherited Members

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 3562663ae..bf38aba61 100644 --- a/classstdex_1_1parser_1_1http__weighted__value-members.html +++ b/classstdex_1_1parser_1_1http__weighted__value-members.html @@ -83,14 +83,14 @@ $(function() {
asterisk (defined in stdex::parser::http_weighted_value< T, T_asterisk >)stdex::parser::http_weighted_value< T, T_asterisk >
factor (defined in stdex::parser::http_weighted_value< T, T_asterisk >)stdex::parser::http_weighted_value< T, T_asterisk >
http_weighted_value(const std::locale &locale=std::locale()) (defined in stdex::parser::http_weighted_value< T, T_asterisk >)stdex::parser::http_weighted_value< T, T_asterisk >inline
intervalstdex::parser::basic_parser< char >
intervalstdex::parser::basic_parser< char >
invalidate() (defined in stdex::parser::http_weighted_value< T, T_asterisk >)stdex::parser::http_weighted_value< T, T_asterisk >inlinevirtual
match(_In_reads_or_z_(end) const char *text, size_t start=0, size_t end=(size_t) -1, int flags=match_default) (defined in stdex::parser::http_weighted_value< T, T_asterisk >)stdex::parser::http_weighted_value< T, T_asterisk >inlinevirtual
value (defined in stdex::parser::http_weighted_value< T, T_asterisk >)stdex::parser::http_weighted_value< T, T_asterisk >
diff --git a/classstdex_1_1parser_1_1http__weighted__value.html b/classstdex_1_1parser_1_1http__weighted__value.html index ff09b05be..869e98271 100644 --- a/classstdex_1_1parser_1_1http__weighted__value.html +++ b/classstdex_1_1parser_1_1http__weighted__value.html @@ -128,10 +128,10 @@ T value http_weight factor   - Public Attributes inherited from stdex::parser::basic_parser< char > - -interval< size_tinterval - Region of the last match.
-  + +stdex::interval< size_tinterval + Region of the last match.
+  @@ -231,7 +231,7 @@ template<clas diff --git a/classstdex_1_1parser_1_1parser__collection-members.html b/classstdex_1_1parser_1_1parser__collection-members.html index e56bb8496..d32eb36da 100644 --- a/classstdex_1_1parser_1_1parser__collection-members.html +++ b/classstdex_1_1parser_1_1parser__collection-members.html @@ -81,7 +81,7 @@ $(function() {

This is the complete list of members for stdex::parser::parser_collection< T >, including all inherited members.

Additional Inherited Members

- + @@ -95,7 +95,7 @@ $(function() {
basic_parser(const std::locale &locale=std::locale()) (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inline
intervalstdex::parser::basic_parser< T >
intervalstdex::parser::basic_parser< T >
invalidate() (defined in stdex::parser::parser_collection< T >)stdex::parser::parser_collection< T >inlinevirtual
m_collection (defined in stdex::parser::parser_collection< T >)stdex::parser::parser_collection< T >protected
m_locale (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >protected
diff --git a/classstdex_1_1parser_1_1parser__collection.html b/classstdex_1_1parser_1_1parser__collection.html index f438615f8..d9671a8c5 100644 --- a/classstdex_1_1parser_1_1parser__collection.html +++ b/classstdex_1_1parser_1_1parser__collection.html @@ -145,10 +145,10 @@ std::locale m_locale

Additional Inherited Members

- Public Attributes inherited from stdex::parser::basic_parser< T > - -interval< size_tinterval - Region of the last match.
-  + +stdex::interval< size_tinterval + Region of the last match.

Detailed Description

template<class T>
@@ -189,7 +189,7 @@ template<clas
diff --git a/classstdex_1_1parser_1_1sgml__any__cp-members.html b/classstdex_1_1parser_1_1sgml__any__cp-members.html index cd5f22d0d..522788ebc 100644 --- a/classstdex_1_1parser_1_1sgml__any__cp-members.html +++ b/classstdex_1_1parser_1_1sgml__any__cp-members.html @@ -81,7 +81,7 @@ $(function() {

This is the complete list of members for stdex::parser::sgml_any_cp, including all inherited members.

- + @@ -93,7 +93,7 @@ $(function() {
basic_parser(const std::locale &locale=std::locale()) (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inline
intervalstdex::parser::basic_parser< T >
intervalstdex::parser::basic_parser< T >
invalidate() (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inlinevirtual
m_locale (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >protected
match(_In_reads_or_z_(end) const char *text, size_t start=0, size_t end=(size_t) -1, int flags=match_default) (defined in stdex::parser::sgml_any_cp)stdex::parser::sgml_any_cpinlinevirtual
diff --git a/classstdex_1_1parser_1_1sgml__any__cp.html b/classstdex_1_1parser_1_1sgml__any__cp.html index c00b32bf7..d446218fd 100644 --- a/classstdex_1_1parser_1_1sgml__any__cp.html +++ b/classstdex_1_1parser_1_1sgml__any__cp.html @@ -128,10 +128,10 @@ template<clas

Additional Inherited Members

- Public Attributes inherited from stdex::parser::basic_parser< T > - -interval< size_tinterval - Region of the last match.
-  + +stdex::interval< size_tinterval + Region of the last match.
- Protected Attributes inherited from stdex::parser::basic_parser< T > std::locale m_locale @@ -196,7 +196,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 d9b14a59e..c2ea11a90 100644 --- a/classstdex_1_1parser_1_1sgml__cp-members.html +++ b/classstdex_1_1parser_1_1sgml__cp-members.html @@ -80,7 +80,7 @@ $(function() {

This is the complete list of members for stdex::parser::sgml_cp, including all inherited members.

- + @@ -88,7 +88,7 @@ $(function() {
intervalstdex::parser::basic_parser< char >
intervalstdex::parser::basic_parser< char >
m_chr (defined in stdex::parser::sgml_cp)stdex::parser::sgml_cpprotected
m_invert (defined in stdex::parser::sgml_cp)stdex::parser::sgml_cpprotected
match(_In_reads_or_z_(end) const char *text, size_t start=0, size_t end=(size_t) -1, int flags=match_default) (defined in stdex::parser::sgml_cp)stdex::parser::sgml_cpinlinevirtual
diff --git a/classstdex_1_1parser_1_1sgml__cp.html b/classstdex_1_1parser_1_1sgml__cp.html index be8c8f583..484de76ab 100644 --- a/classstdex_1_1parser_1_1sgml__cp.html +++ b/classstdex_1_1parser_1_1sgml__cp.html @@ -133,10 +133,10 @@ std::locale m_locale

Additional Inherited Members

- Public Attributes inherited from stdex::parser::basic_parser< char > - -interval< size_tinterval - Region of the last match.
-  + +stdex::interval< size_tinterval + Region of the last match.

Detailed Description

Test for specific SGML code point.

@@ -197,7 +197,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 b08d02791..b1c5316fa 100644 --- a/classstdex_1_1parser_1_1sgml__cp__set-members.html +++ b/classstdex_1_1parser_1_1sgml__cp__set-members.html @@ -81,7 +81,7 @@ $(function() {

This is the complete list of members for stdex::parser::sgml_cp_set, including all inherited members.

- + @@ -93,7 +93,7 @@ $(function() {
basic_parser(const std::locale &locale=std::locale()) (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inline
intervalstdex::parser::basic_parser< T >
intervalstdex::parser::basic_parser< T >
m_locale (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >protected
m_set (defined in stdex::parser::sgml_cp_set)stdex::parser::sgml_cp_setprotected
match(_In_reads_or_z_(end) const char *text, size_t start=0, size_t end=(size_t) -1, int flags=match_default) (defined in stdex::parser::sgml_cp_set)stdex::parser::sgml_cp_setinlinevirtual
diff --git a/classstdex_1_1parser_1_1sgml__cp__set.html b/classstdex_1_1parser_1_1sgml__cp__set.html index 36ab237c1..d8ea443d3 100644 --- a/classstdex_1_1parser_1_1sgml__cp__set.html +++ b/classstdex_1_1parser_1_1sgml__cp__set.html @@ -146,10 +146,10 @@ Additional Inherited Members size_t hit_offset   - Public Attributes inherited from stdex::parser::basic_parser< T > - -interval< size_tinterval - Region of the last match.
-  + +stdex::interval< size_tinterval + Region of the last match.

Detailed Description

Test for any SGML code point from a given string of SGML code points.

@@ -210,7 +210,7 @@ Additional Inherited Members
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 8c75638c4..75ebacac2 100644 --- a/classstdex_1_1parser_1_1sgml__dns__domain__char-members.html +++ b/classstdex_1_1parser_1_1sgml__dns__domain__char-members.html @@ -82,7 +82,7 @@ $(function() { - + @@ -94,7 +94,7 @@ $(function() {
allow_on_edgestdex::parser::basic_dns_domain_char< char >
basic_parser(const std::locale &locale=std::locale()) (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inline
intervalstdex::parser::basic_parser< T >
intervalstdex::parser::basic_parser< T >
invalidate() (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inlinevirtual
m_locale (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >protected
match(_In_reads_or_z_(end) const char *text, size_t start=0, size_t end=(size_t) -1, int flags=match_default) (defined in stdex::parser::sgml_dns_domain_char)stdex::parser::sgml_dns_domain_charinlinevirtual
diff --git a/classstdex_1_1parser_1_1sgml__dns__domain__char.html b/classstdex_1_1parser_1_1sgml__dns__domain__char.html index b53eae38d..4691e19b0 100644 --- a/classstdex_1_1parser_1_1sgml__dns__domain__char.html +++ b/classstdex_1_1parser_1_1sgml__dns__domain__char.html @@ -133,10 +133,10 @@ Additional Inherited Members  Is character allowed at the beginning or an end of a DNS domain?
  - Public Attributes inherited from stdex::parser::basic_parser< T > - -interval< size_tinterval - Region of the last match.
-  + +stdex::interval< size_tinterval + Region of the last match.
- Protected Attributes inherited from stdex::parser::basic_dns_domain_char< char > bool m_allow_idn @@ -205,7 +205,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 b4d1a6f78..661c32436 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 @@ -80,13 +80,13 @@ $(function() {

This is the complete list of members for stdex::parser::sgml_ipv6_scope_id_char, including all inherited members.

- +
intervalstdex::parser::basic_parser< char >
intervalstdex::parser::basic_parser< char >
match(_In_reads_or_z_(end) const char *text, size_t start=0, size_t end=(size_t) -1, int flags=match_default) (defined in stdex::parser::sgml_ipv6_scope_id_char)stdex::parser::sgml_ipv6_scope_id_charinlinevirtual
sgml_ipv6_scope_id_char(const std::locale &locale=std::locale()) (defined in stdex::parser::sgml_ipv6_scope_id_char)stdex::parser::sgml_ipv6_scope_id_charinline
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 1a2ac9c36..dfb5bad21 100644 --- a/classstdex_1_1parser_1_1sgml__ipv6__scope__id__char.html +++ b/classstdex_1_1parser_1_1sgml__ipv6__scope__id__char.html @@ -119,10 +119,10 @@ Public Member Functions

Additional Inherited Members

- Public Attributes inherited from stdex::parser::basic_parser< char > - -interval< size_tinterval - Region of the last match.
-  + +stdex::interval< size_tinterval + Region of the last match.
- Protected Attributes inherited from stdex::parser::basic_parser< char > std::locale m_locale @@ -187,7 +187,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 01f621436..3473a61d4 100644 --- a/classstdex_1_1parser_1_1sgml__punct__cp-members.html +++ b/classstdex_1_1parser_1_1sgml__punct__cp-members.html @@ -81,7 +81,7 @@ $(function() {

This is the complete list of members for stdex::parser::sgml_punct_cp, including all inherited members.

- + @@ -93,7 +93,7 @@ $(function() {
basic_parser(const std::locale &locale=std::locale()) (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inline
intervalstdex::parser::basic_parser< T >
intervalstdex::parser::basic_parser< T >
invalidate() (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inlinevirtual
m_locale (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >protected
match(_In_reads_or_z_(end) const char *text, size_t start=0, size_t end=(size_t) -1, int flags=match_default) (defined in stdex::parser::sgml_punct_cp)stdex::parser::sgml_punct_cpinlinevirtual
diff --git a/classstdex_1_1parser_1_1sgml__punct__cp.html b/classstdex_1_1parser_1_1sgml__punct__cp.html index b21ba4a55..86c86a427 100644 --- a/classstdex_1_1parser_1_1sgml__punct__cp.html +++ b/classstdex_1_1parser_1_1sgml__punct__cp.html @@ -128,10 +128,10 @@ template<clas

Additional Inherited Members

- Public Attributes inherited from stdex::parser::basic_parser< T > - -interval< size_tinterval - Region of the last match.
-  + +stdex::interval< size_tinterval + Region of the last match.
- Protected Attributes inherited from stdex::parser::basic_punct_cu< char > bool m_invert @@ -200,7 +200,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 6ef335dec..3f4c0d7b0 100644 --- a/classstdex_1_1parser_1_1sgml__space__cp-members.html +++ b/classstdex_1_1parser_1_1sgml__space__cp-members.html @@ -81,7 +81,7 @@ $(function() {

This is the complete list of members for stdex::parser::sgml_space_cp, including all inherited members.

- + @@ -93,7 +93,7 @@ $(function() {
basic_parser(const std::locale &locale=std::locale()) (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inline
intervalstdex::parser::basic_parser< T >
intervalstdex::parser::basic_parser< T >
invalidate() (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inlinevirtual
m_locale (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >protected
match(_In_reads_or_z_(end) const char *text, size_t start=0, size_t end=(size_t) -1, int flags=match_default) (defined in stdex::parser::sgml_space_cp)stdex::parser::sgml_space_cpinlinevirtual
diff --git a/classstdex_1_1parser_1_1sgml__space__cp.html b/classstdex_1_1parser_1_1sgml__space__cp.html index e183065dc..81cbb50c1 100644 --- a/classstdex_1_1parser_1_1sgml__space__cp.html +++ b/classstdex_1_1parser_1_1sgml__space__cp.html @@ -128,10 +128,10 @@ template<clas

Additional Inherited Members

- Public Attributes inherited from stdex::parser::basic_parser< T > - -interval< size_tinterval - Region of the last match.
-  + +stdex::interval< size_tinterval + Region of the last match.
- Protected Attributes inherited from stdex::parser::basic_space_cu< char > bool m_invert @@ -200,7 +200,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 068cb881e..940971eab 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 @@ -81,7 +81,7 @@ $(function() {

This is the complete list of members for stdex::parser::sgml_space_or_punct_cp, including all inherited members.

- + @@ -93,7 +93,7 @@ $(function() {
basic_parser(const std::locale &locale=std::locale()) (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inline
intervalstdex::parser::basic_parser< T >
intervalstdex::parser::basic_parser< T >
invalidate() (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inlinevirtual
m_locale (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >protected
match(_In_reads_or_z_(end) const char *text, size_t start=0, size_t end=(size_t) -1, int flags=match_default) (defined in stdex::parser::sgml_space_or_punct_cp)stdex::parser::sgml_space_or_punct_cpinlinevirtual
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 baf8b1b7e..607033088 100644 --- a/classstdex_1_1parser_1_1sgml__space__or__punct__cp.html +++ b/classstdex_1_1parser_1_1sgml__space__or__punct__cp.html @@ -128,10 +128,10 @@ template<clas

Additional Inherited Members

- Public Attributes inherited from stdex::parser::basic_parser< T > - -interval< size_tinterval - Region of the last match.
-  + +stdex::interval< size_tinterval + Region of the last match.
- Protected Attributes inherited from stdex::parser::basic_space_or_punct_cu< char > bool m_invert @@ -200,7 +200,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 20d1d3511..86b26fe71 100644 --- a/classstdex_1_1parser_1_1sgml__string-members.html +++ b/classstdex_1_1parser_1_1sgml__string-members.html @@ -80,14 +80,14 @@ $(function() {

This is the complete list of members for stdex::parser::sgml_string, including all inherited members.

- +
intervalstdex::parser::basic_parser< char >
intervalstdex::parser::basic_parser< char >
m_str (defined in stdex::parser::sgml_string)stdex::parser::sgml_stringprotected
match(_In_reads_or_z_(end) const char *text, size_t start=0, size_t end=(size_t) -1, int flags=match_default) (defined in stdex::parser::sgml_string)stdex::parser::sgml_stringinlinevirtual
sgml_string(const char *str, size_t count=(size_t) -1, const std::locale &locale=std::locale()) (defined in stdex::parser::sgml_string)stdex::parser::sgml_stringinline
diff --git a/classstdex_1_1parser_1_1sgml__string.html b/classstdex_1_1parser_1_1sgml__string.html index 720a3eda2..4c034a606 100644 --- a/classstdex_1_1parser_1_1sgml__string.html +++ b/classstdex_1_1parser_1_1sgml__string.html @@ -130,10 +130,10 @@ std::locale m_locale

Additional Inherited Members

- Public Attributes inherited from stdex::parser::basic_parser< char > - -interval< size_tinterval - Region of the last match.
-  + +stdex::interval< size_tinterval + Region of the last match.

Detailed Description

Test for SGML given string.

@@ -194,7 +194,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 94ffadcf1..80122d299 100644 --- a/classstdex_1_1parser_1_1sgml__url__password__char-members.html +++ b/classstdex_1_1parser_1_1sgml__url__password__char-members.html @@ -81,7 +81,7 @@ $(function() {

This is the complete list of members for stdex::parser::sgml_url_password_char, including all inherited members.

- + @@ -93,7 +93,7 @@ $(function() {
basic_parser(const std::locale &locale=std::locale()) (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inline
intervalstdex::parser::basic_parser< T >
intervalstdex::parser::basic_parser< T >
invalidate() (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inlinevirtual
m_locale (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >protected
match(_In_reads_or_z_(end) const char *text, size_t start=0, size_t end=(size_t) -1, int flags=match_default) (defined in stdex::parser::sgml_url_password_char)stdex::parser::sgml_url_password_charinlinevirtual
diff --git a/classstdex_1_1parser_1_1sgml__url__password__char.html b/classstdex_1_1parser_1_1sgml__url__password__char.html index 3d5823531..0f491d75f 100644 --- a/classstdex_1_1parser_1_1sgml__url__password__char.html +++ b/classstdex_1_1parser_1_1sgml__url__password__char.html @@ -128,10 +128,10 @@ template<clas

Additional Inherited Members

- Public Attributes inherited from stdex::parser::basic_parser< T > - -interval< size_tinterval - Region of the last match.
-  + +stdex::interval< size_tinterval + Region of the last match.
- Protected Attributes inherited from stdex::parser::basic_parser< T > std::locale m_locale @@ -196,7 +196,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 d3769d898..f952b472b 100644 --- a/classstdex_1_1parser_1_1sgml__url__path__char-members.html +++ b/classstdex_1_1parser_1_1sgml__url__path__char-members.html @@ -81,7 +81,7 @@ $(function() {

This is the complete list of members for stdex::parser::sgml_url_path_char, including all inherited members.

- + @@ -93,7 +93,7 @@ $(function() {
basic_parser(const std::locale &locale=std::locale()) (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inline
intervalstdex::parser::basic_parser< T >
intervalstdex::parser::basic_parser< T >
invalidate() (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inlinevirtual
m_locale (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >protected
match(_In_reads_or_z_(end) const char *text, size_t start=0, size_t end=(size_t) -1, int flags=match_default) (defined in stdex::parser::sgml_url_path_char)stdex::parser::sgml_url_path_charinlinevirtual
diff --git a/classstdex_1_1parser_1_1sgml__url__path__char.html b/classstdex_1_1parser_1_1sgml__url__path__char.html index 0df71924a..5e384db53 100644 --- a/classstdex_1_1parser_1_1sgml__url__path__char.html +++ b/classstdex_1_1parser_1_1sgml__url__path__char.html @@ -128,10 +128,10 @@ template<clas

Additional Inherited Members

- Public Attributes inherited from stdex::parser::basic_parser< T > - -interval< size_tinterval - Region of the last match.
-  + +stdex::interval< size_tinterval + Region of the last match.
- Protected Attributes inherited from stdex::parser::basic_parser< T > std::locale m_locale @@ -196,7 +196,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 2f0902b78..dab628779 100644 --- a/classstdex_1_1parser_1_1sgml__url__username__char-members.html +++ b/classstdex_1_1parser_1_1sgml__url__username__char-members.html @@ -81,7 +81,7 @@ $(function() {

This is the complete list of members for stdex::parser::sgml_url_username_char, including all inherited members.

- + @@ -93,7 +93,7 @@ $(function() {
basic_parser(const std::locale &locale=std::locale()) (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inline
intervalstdex::parser::basic_parser< T >
intervalstdex::parser::basic_parser< T >
invalidate() (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >inlinevirtual
m_locale (defined in stdex::parser::basic_parser< T >)stdex::parser::basic_parser< T >protected
match(_In_reads_or_z_(end) const char *text, size_t start=0, size_t end=(size_t) -1, int flags=match_default) (defined in stdex::parser::sgml_url_username_char)stdex::parser::sgml_url_username_charinlinevirtual
diff --git a/classstdex_1_1parser_1_1sgml__url__username__char.html b/classstdex_1_1parser_1_1sgml__url__username__char.html index b255e65ab..238c00f9f 100644 --- a/classstdex_1_1parser_1_1sgml__url__username__char.html +++ b/classstdex_1_1parser_1_1sgml__url__username__char.html @@ -128,10 +128,10 @@ template<clas

Additional Inherited Members

- Public Attributes inherited from stdex::parser::basic_parser< T > - -interval< size_tinterval - Region of the last match.
-  + +stdex::interval< size_tinterval + Region of the last match.
- Protected Attributes inherited from stdex::parser::basic_parser< T > std::locale m_locale @@ -196,7 +196,7 @@ std::locale m_locale diff --git a/classstdex_1_1progress-members.html b/classstdex_1_1progress-members.html index 5c7d0969c..5512287c1 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 84ab79029..7c5f73352 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 081609ff3..6fcccbb30 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 b4e74ac09..3eaf09cda 100644 --- a/classstdex_1_1progress__switcher.html +++ b/classstdex_1_1progress__switcher.html @@ -163,7 +163,7 @@ class stdex::progress_switcher< T >

Progress indicator switcher. <

diff --git a/classstdex_1_1ring-members.html b/classstdex_1_1ring-members.html index c9c523acd..c85e5cb0d 100644 --- a/classstdex_1_1ring-members.html +++ b/classstdex_1_1ring-members.html @@ -100,7 +100,7 @@ $(function() { diff --git a/classstdex_1_1ring.html b/classstdex_1_1ring.html index 7037abc91..4a13b0ca2 100644 --- a/classstdex_1_1ring.html +++ b/classstdex_1_1ring.html @@ -296,7 +296,7 @@ template<class T , size_t CAPACITY> diff --git a/classstdex_1_1sha1__hash-members.html b/classstdex_1_1sha1__hash-members.html index 6fbc6bfb2..0d59600db 100644 --- a/classstdex_1_1sha1__hash-members.html +++ b/classstdex_1_1sha1__hash-members.html @@ -93,7 +93,7 @@ $(function() { diff --git a/classstdex_1_1sha1__hash.html b/classstdex_1_1sha1__hash.html index 8d51bbfa3..27592f1b4 100644 --- a/classstdex_1_1sha1__hash.html +++ b/classstdex_1_1sha1__hash.html @@ -259,7 +259,7 @@ uint32_t m_temp [16] diff --git a/classstdex_1_1stream_1_1async__reader-members.html b/classstdex_1_1stream_1_1async__reader-members.html index a3919da55..94129c7cb 100644 --- a/classstdex_1_1stream_1_1async__reader-members.html +++ b/classstdex_1_1stream_1_1async__reader-members.html @@ -155,7 +155,7 @@ $(function() { diff --git a/classstdex_1_1stream_1_1async__reader.html b/classstdex_1_1stream_1_1async__reader.html index ffe0c9b19..1096d72eb 100644 --- a/classstdex_1_1stream_1_1async__reader.html +++ b/classstdex_1_1stream_1_1async__reader.html @@ -414,7 +414,7 @@ template<size_t CAPACITY = default_async_limit> diff --git a/classstdex_1_1stream_1_1async__writer-members.html b/classstdex_1_1stream_1_1async__writer-members.html index 075273c5f..4e728d37d 100644 --- a/classstdex_1_1stream_1_1async__writer-members.html +++ b/classstdex_1_1stream_1_1async__writer-members.html @@ -155,7 +155,7 @@ $(function() { diff --git a/classstdex_1_1stream_1_1async__writer.html b/classstdex_1_1stream_1_1async__writer.html index c1b4cab2b..461aac58b 100644 --- a/classstdex_1_1stream_1_1async__writer.html +++ b/classstdex_1_1stream_1_1async__writer.html @@ -445,7 +445,7 @@ template<size_t CAPACITY = default_async_limit> diff --git a/classstdex_1_1stream_1_1basic-members.html b/classstdex_1_1stream_1_1basic-members.html index b4c1897c6..7fd479530 100644 --- a/classstdex_1_1stream_1_1basic-members.html +++ b/classstdex_1_1stream_1_1basic-members.html @@ -148,7 +148,7 @@ $(function() { diff --git a/classstdex_1_1stream_1_1basic.html b/classstdex_1_1stream_1_1basic.html index e9773bb74..cd55c240c 100644 --- a/classstdex_1_1stream_1_1basic.html +++ b/classstdex_1_1stream_1_1basic.html @@ -1400,7 +1400,7 @@ template<class T > diff --git a/classstdex_1_1stream_1_1basic__file-members.html b/classstdex_1_1stream_1_1basic__file-members.html index e07c46783..dd2ca1eac 100644 --- a/classstdex_1_1stream_1_1basic__file-members.html +++ b/classstdex_1_1stream_1_1basic__file-members.html @@ -164,7 +164,7 @@ $(function() { diff --git a/classstdex_1_1stream_1_1basic__file.html b/classstdex_1_1stream_1_1basic__file.html index 8f60eb61d..db75560e6 100644 --- a/classstdex_1_1stream_1_1basic__file.html +++ b/classstdex_1_1stream_1_1basic__file.html @@ -961,7 +961,7 @@ state_t m_state diff --git a/classstdex_1_1stream_1_1basic__sys-members.html b/classstdex_1_1stream_1_1basic__sys-members.html index 9feadcffa..8522977a4 100644 --- a/classstdex_1_1stream_1_1basic__sys-members.html +++ b/classstdex_1_1stream_1_1basic__sys-members.html @@ -160,7 +160,7 @@ $(function() { diff --git a/classstdex_1_1stream_1_1basic__sys.html b/classstdex_1_1stream_1_1basic__sys.html index c630d4de3..30caf3a5b 100644 --- a/classstdex_1_1stream_1_1basic__sys.html +++ b/classstdex_1_1stream_1_1basic__sys.html @@ -527,7 +527,7 @@ sys_handle m_h diff --git a/classstdex_1_1stream_1_1buffer-members.html b/classstdex_1_1stream_1_1buffer-members.html index 34c6cc996..d2fd47786 100644 --- a/classstdex_1_1stream_1_1buffer-members.html +++ b/classstdex_1_1stream_1_1buffer-members.html @@ -155,7 +155,7 @@ $(function() { diff --git a/classstdex_1_1stream_1_1buffer.html b/classstdex_1_1stream_1_1buffer.html index 677862e1c..85a3e4703 100644 --- a/classstdex_1_1stream_1_1buffer.html +++ b/classstdex_1_1stream_1_1buffer.html @@ -489,7 +489,7 @@ state_t m_state diff --git a/classstdex_1_1stream_1_1buffered__sys-members.html b/classstdex_1_1stream_1_1buffered__sys-members.html index 18f41945b..33ca3a5fa 100644 --- a/classstdex_1_1stream_1_1buffered__sys-members.html +++ b/classstdex_1_1stream_1_1buffered__sys-members.html @@ -157,7 +157,7 @@ $(function() { diff --git a/classstdex_1_1stream_1_1buffered__sys.html b/classstdex_1_1stream_1_1buffered__sys.html index 85982a72c..e52b7b703 100644 --- a/classstdex_1_1stream_1_1buffered__sys.html +++ b/classstdex_1_1stream_1_1buffered__sys.html @@ -365,7 +365,7 @@ void flush_write () diff --git a/classstdex_1_1stream_1_1cache-members.html b/classstdex_1_1stream_1_1cache-members.html index da13d7152..61d562c0b 100644 --- a/classstdex_1_1stream_1_1cache-members.html +++ b/classstdex_1_1stream_1_1cache-members.html @@ -166,7 +166,7 @@ $(function() { diff --git a/classstdex_1_1stream_1_1cache.html b/classstdex_1_1stream_1_1cache.html index 849c9979e..6ae8685b2 100644 --- a/classstdex_1_1stream_1_1cache.html +++ b/classstdex_1_1stream_1_1cache.html @@ -925,7 +925,7 @@ state_t m_state diff --git a/classstdex_1_1stream_1_1cached__file-members.html b/classstdex_1_1stream_1_1cached__file-members.html index dec85ece3..c8ab107b1 100644 --- a/classstdex_1_1stream_1_1cached__file-members.html +++ b/classstdex_1_1stream_1_1cached__file-members.html @@ -173,7 +173,7 @@ $(function() { diff --git a/classstdex_1_1stream_1_1cached__file.html b/classstdex_1_1stream_1_1cached__file.html index e3fa1b62e..518f9248b 100644 --- a/classstdex_1_1stream_1_1cached__file.html +++ b/classstdex_1_1stream_1_1cached__file.html @@ -600,7 +600,7 @@ state_t m_state diff --git a/classstdex_1_1stream_1_1converter-members.html b/classstdex_1_1stream_1_1converter-members.html index 289e4733f..ab4ec5937 100644 --- a/classstdex_1_1stream_1_1converter-members.html +++ b/classstdex_1_1stream_1_1converter-members.html @@ -150,7 +150,7 @@ $(function() { diff --git a/classstdex_1_1stream_1_1converter.html b/classstdex_1_1stream_1_1converter.html index b5510eafa..a600bb658 100644 --- a/classstdex_1_1stream_1_1converter.html +++ b/classstdex_1_1stream_1_1converter.html @@ -507,7 +507,7 @@ state_t m_state diff --git a/classstdex_1_1stream_1_1diag__file-members.html b/classstdex_1_1stream_1_1diag__file-members.html index 6ccbbba43..b8e8adcd3 100644 --- a/classstdex_1_1stream_1_1diag__file-members.html +++ b/classstdex_1_1stream_1_1diag__file-members.html @@ -167,7 +167,7 @@ $(function() { diff --git a/classstdex_1_1stream_1_1diag__file.html b/classstdex_1_1stream_1_1diag__file.html index e75f5c72a..8cf8b49b3 100644 --- a/classstdex_1_1stream_1_1diag__file.html +++ b/classstdex_1_1stream_1_1diag__file.html @@ -754,7 +754,7 @@ state_t m_state diff --git a/classstdex_1_1stream_1_1fifo-members.html b/classstdex_1_1stream_1_1fifo-members.html index 9feac6477..f94c1b26e 100644 --- a/classstdex_1_1stream_1_1fifo-members.html +++ b/classstdex_1_1stream_1_1fifo-members.html @@ -155,7 +155,7 @@ $(function() { diff --git a/classstdex_1_1stream_1_1fifo.html b/classstdex_1_1stream_1_1fifo.html index b82975d46..1a1d791aa 100644 --- a/classstdex_1_1stream_1_1fifo.html +++ b/classstdex_1_1stream_1_1fifo.html @@ -479,7 +479,7 @@ state_t m_state diff --git a/classstdex_1_1stream_1_1file-members.html b/classstdex_1_1stream_1_1file-members.html index a3a25f2bb..9fdef1f90 100644 --- a/classstdex_1_1stream_1_1file-members.html +++ b/classstdex_1_1stream_1_1file-members.html @@ -189,7 +189,7 @@ $(function() { diff --git a/classstdex_1_1stream_1_1file.html b/classstdex_1_1stream_1_1file.html index 16b5669c5..45dff91b8 100644 --- a/classstdex_1_1stream_1_1file.html +++ b/classstdex_1_1stream_1_1file.html @@ -1161,7 +1161,7 @@ sys_handle m_h diff --git a/classstdex_1_1stream_1_1file__window-members.html b/classstdex_1_1stream_1_1file__window-members.html index e6e67bc78..1817653b9 100644 --- a/classstdex_1_1stream_1_1file__window-members.html +++ b/classstdex_1_1stream_1_1file__window-members.html @@ -168,7 +168,7 @@ $(function() { diff --git a/classstdex_1_1stream_1_1file__window.html b/classstdex_1_1stream_1_1file__window.html index 893272af2..a8de94e5c 100644 --- a/classstdex_1_1stream_1_1file__window.html +++ b/classstdex_1_1stream_1_1file__window.html @@ -787,7 +787,7 @@ state_t m_state diff --git a/classstdex_1_1stream_1_1limiter-members.html b/classstdex_1_1stream_1_1limiter-members.html index b06389eff..bc572be70 100644 --- a/classstdex_1_1stream_1_1limiter-members.html +++ b/classstdex_1_1stream_1_1limiter-members.html @@ -153,7 +153,7 @@ $(function() { diff --git a/classstdex_1_1stream_1_1limiter.html b/classstdex_1_1stream_1_1limiter.html index e58d8fc59..acf946409 100644 --- a/classstdex_1_1stream_1_1limiter.html +++ b/classstdex_1_1stream_1_1limiter.html @@ -456,7 +456,7 @@ state_t m_state diff --git a/classstdex_1_1stream_1_1memory__file-members.html b/classstdex_1_1stream_1_1memory__file-members.html index 01c2333e1..19cb16973 100644 --- a/classstdex_1_1stream_1_1memory__file-members.html +++ b/classstdex_1_1stream_1_1memory__file-members.html @@ -208,7 +208,7 @@ $(function() { diff --git a/classstdex_1_1stream_1_1memory__file.html b/classstdex_1_1stream_1_1memory__file.html index 587eb2c18..1baa9d328 100644 --- a/classstdex_1_1stream_1_1memory__file.html +++ b/classstdex_1_1stream_1_1memory__file.html @@ -1690,7 +1690,7 @@ template<class T > diff --git a/classstdex_1_1stream_1_1replicator-members.html b/classstdex_1_1stream_1_1replicator-members.html index 3688d8414..79cf5c331 100644 --- a/classstdex_1_1stream_1_1replicator-members.html +++ b/classstdex_1_1stream_1_1replicator-members.html @@ -153,7 +153,7 @@ $(function() { diff --git a/classstdex_1_1stream_1_1replicator.html b/classstdex_1_1stream_1_1replicator.html index 1c91e0382..e1dc9c55b 100644 --- a/classstdex_1_1stream_1_1replicator.html +++ b/classstdex_1_1stream_1_1replicator.html @@ -462,7 +462,7 @@ state_t m_state diff --git a/classstdex_1_1stream_1_1replicator_1_1worker-members.html b/classstdex_1_1stream_1_1replicator_1_1worker-members.html index e7d6ceedc..7bdbe1a04 100644 --- a/classstdex_1_1stream_1_1replicator_1_1worker-members.html +++ b/classstdex_1_1stream_1_1replicator_1_1worker-members.html @@ -93,7 +93,7 @@ $(function() { diff --git a/classstdex_1_1stream_1_1replicator_1_1worker.html b/classstdex_1_1stream_1_1replicator_1_1worker.html index 86021a6c0..df6bbeecf 100644 --- a/classstdex_1_1stream_1_1replicator_1_1worker.html +++ b/classstdex_1_1stream_1_1replicator_1_1worker.html @@ -149,7 +149,7 @@ void process_op () diff --git a/classstdex_1_1stream_1_1socket-members.html b/classstdex_1_1stream_1_1socket-members.html index ff6afedee..9e8272e4c 100644 --- a/classstdex_1_1stream_1_1socket-members.html +++ b/classstdex_1_1stream_1_1socket-members.html @@ -156,7 +156,7 @@ $(function() { diff --git a/classstdex_1_1stream_1_1socket.html b/classstdex_1_1stream_1_1socket.html index 40b009ce8..c4524c711 100644 --- a/classstdex_1_1stream_1_1socket.html +++ b/classstdex_1_1stream_1_1socket.html @@ -533,7 +533,7 @@ state_t m_state diff --git a/classstdex_1_1stream_1_1window-members.html b/classstdex_1_1stream_1_1window-members.html index 3b2d5775f..3872d7b04 100644 --- a/classstdex_1_1stream_1_1window-members.html +++ b/classstdex_1_1stream_1_1window-members.html @@ -156,7 +156,7 @@ $(function() { diff --git a/classstdex_1_1stream_1_1window.html b/classstdex_1_1stream_1_1window.html index 20e69f4fc..1368baec1 100644 --- a/classstdex_1_1stream_1_1window.html +++ b/classstdex_1_1stream_1_1window.html @@ -465,7 +465,7 @@ state_t m_state diff --git a/classstdex_1_1stream__hasher-members.html b/classstdex_1_1stream__hasher-members.html index a0c2ee98b..20e85827a 100644 --- a/classstdex_1_1stream__hasher-members.html +++ b/classstdex_1_1stream__hasher-members.html @@ -152,7 +152,7 @@ $(function() { diff --git a/classstdex_1_1stream__hasher.html b/classstdex_1_1stream__hasher.html index 8b65b8519..799cdbfd7 100644 --- a/classstdex_1_1stream__hasher.html +++ b/classstdex_1_1stream__hasher.html @@ -448,7 +448,7 @@ template<class T > diff --git a/classstdex_1_1sys__object-members.html b/classstdex_1_1sys__object-members.html index 12a9a6cdc..25d75ec80 100644 --- a/classstdex_1_1sys__object-members.html +++ b/classstdex_1_1sys__object-members.html @@ -95,7 +95,7 @@ $(function() { diff --git a/classstdex_1_1sys__object.html b/classstdex_1_1sys__object.html index dc854590b..530772e07 100644 --- a/classstdex_1_1sys__object.html +++ b/classstdex_1_1sys__object.html @@ -182,7 +182,7 @@ sys_handle m_h diff --git a/classstdex_1_1user__cancelled-members.html b/classstdex_1_1user__cancelled-members.html index 88fbcb834..6a01a9113 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 87a2c4cc3..cccb0e6a2 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 20dac077c..2f6835c21 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 c6427bf9e..e60dce9e5 100644 --- a/classstdex_1_1vector__queue.html +++ b/classstdex_1_1vector__queue.html @@ -795,7 +795,7 @@ template<class T > diff --git a/classstdex_1_1watchdog-members.html b/classstdex_1_1watchdog-members.html index 60fe43d28..2229d33ad 100644 --- a/classstdex_1_1watchdog-members.html +++ b/classstdex_1_1watchdog-members.html @@ -94,7 +94,7 @@ $(function() { diff --git a/classstdex_1_1watchdog.html b/classstdex_1_1watchdog.html index 018a61c07..2069e46e5 100644 --- a/classstdex_1_1watchdog.html +++ b/classstdex_1_1watchdog.html @@ -223,7 +223,7 @@ template<class _Clock , class _Duration = typename _Clock::duration> diff --git a/dir_4be4f7b278e009bf0f1906cf31fb73bd.html b/dir_4be4f7b278e009bf0f1906cf31fb73bd.html index a738cb8f3..1d771be72 100644 --- a/dir_4be4f7b278e009bf0f1906cf31fb73bd.html +++ b/dir_4be4f7b278e009bf0f1906cf31fb73bd.html @@ -104,7 +104,7 @@ Files diff --git a/dir_d44c64559bbebec7f509842c48db8b23.html b/dir_d44c64559bbebec7f509842c48db8b23.html index bcc005f91..5fa593edc 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 59a9f797a..47e624aad 100644 --- a/dir_fca3c47b2ea228727bd6729832f89576.html +++ b/dir_fca3c47b2ea228727bd6729832f89576.html @@ -124,6 +124,8 @@ Files    unicode.hpp   + uuid.hpp vector_queue.hpp    watchdog.hpp @@ -134,7 +136,7 @@ Files diff --git a/endian_8hpp_source.html b/endian_8hpp_source.html index f24585e39..0a643f19f 100644 --- a/endian_8hpp_source.html +++ b/endian_8hpp_source.html @@ -225,7 +225,7 @@ $(document).ready(function() { init_codefold(0); }); diff --git a/exception_8hpp_source.html b/exception_8hpp_source.html index 41f508491..bd081dbad 100644 --- a/exception_8hpp_source.html +++ b/exception_8hpp_source.html @@ -107,7 +107,7 @@ $(document).ready(function() { init_codefold(0); }); diff --git a/files.html b/files.html index 55a41476c..703ef619a 100644 --- a/files.html +++ b/files.html @@ -99,26 +99,27 @@ $(function() {  sys_info.hpp  system.hpp  unicode.hpp - vector_queue.hpp - watchdog.hpp - windows.h -  UnitTests - compat.hpp - hash.cpp - math.cpp - parser.cpp - pch.hpp - ring.cpp - sgml.cpp - stream.cpp - unicode.cpp - watchdog.cpp + uuid.hpp + vector_queue.hpp + watchdog.hpp + windows.h +  UnitTests + compat.hpp + hash.cpp + math.cpp + parser.cpp + pch.hpp + ring.cpp + sgml.cpp + stream.cpp + unicode.cpp + watchdog.cpp diff --git a/functions.html b/functions.html index d15f76f9b..6491c15b5 100644 --- a/functions.html +++ b/functions.html @@ -85,7 +85,7 @@ $(function() { diff --git a/functions_b.html b/functions_b.html index d0bd88ce0..42be350b4 100644 --- a/functions_b.html +++ b/functions_b.html @@ -82,7 +82,7 @@ $(function() { diff --git a/functions_c.html b/functions_c.html index 4a05ca34d..43202fcec 100644 --- a/functions_c.html +++ b/functions_c.html @@ -92,7 +92,7 @@ $(function() { diff --git a/functions_d.html b/functions_d.html index 0be931398..56c4f808b 100644 --- a/functions_d.html +++ b/functions_d.html @@ -87,7 +87,7 @@ $(function() { diff --git a/functions_e.html b/functions_e.html index 8aefe7563..9a9cf0235 100644 --- a/functions_e.html +++ b/functions_e.html @@ -87,7 +87,7 @@ $(function() { diff --git a/functions_f.html b/functions_f.html index f0de55e97..cc615df73 100644 --- a/functions_f.html +++ b/functions_f.html @@ -87,7 +87,7 @@ $(function() { diff --git a/functions_func.html b/functions_func.html index 5ba9bcaf3..b0e20d618 100644 --- a/functions_func.html +++ b/functions_func.html @@ -82,7 +82,7 @@ $(function() { diff --git a/functions_func_b.html b/functions_func_b.html index 42aca6ba3..914d417bf 100644 --- a/functions_func_b.html +++ b/functions_func_b.html @@ -80,7 +80,7 @@ $(function() { diff --git a/functions_func_c.html b/functions_func_c.html index c12acdcaa..89312b42b 100644 --- a/functions_func_c.html +++ b/functions_func_c.html @@ -85,7 +85,7 @@ $(function() { diff --git a/functions_func_d.html b/functions_func_d.html index ed73a8524..2a0a22894 100644 --- a/functions_func_d.html +++ b/functions_func_d.html @@ -84,7 +84,7 @@ $(function() { diff --git a/functions_func_e.html b/functions_func_e.html index 2b15e187f..064f6785f 100644 --- a/functions_func_e.html +++ b/functions_func_e.html @@ -81,7 +81,7 @@ $(function() { diff --git a/functions_func_f.html b/functions_func_f.html index 772b93677..2dc164603 100644 --- a/functions_func_f.html +++ b/functions_func_f.html @@ -86,7 +86,7 @@ $(function() { diff --git a/functions_func_g.html b/functions_func_g.html index 19c888c57..03eee9c37 100644 --- a/functions_func_g.html +++ b/functions_func_g.html @@ -79,7 +79,7 @@ $(function() { diff --git a/functions_func_h.html b/functions_func_h.html index 61c129ab0..fb3724870 100644 --- a/functions_func_h.html +++ b/functions_func_h.html @@ -81,7 +81,7 @@ $(function() { diff --git a/functions_func_i.html b/functions_func_i.html index 7438d0408..36441aaf4 100644 --- a/functions_func_i.html +++ b/functions_func_i.html @@ -80,7 +80,7 @@ $(function() { diff --git a/functions_func_l.html b/functions_func_l.html index ea5db7359..980edf3cf 100644 --- a/functions_func_l.html +++ b/functions_func_l.html @@ -80,7 +80,7 @@ $(function() { diff --git a/functions_func_m.html b/functions_func_m.html index 36b023c66..a9c8e4e06 100644 --- a/functions_func_m.html +++ b/functions_func_m.html @@ -80,7 +80,7 @@ $(function() { diff --git a/functions_func_n.html b/functions_func_n.html index 793f19087..4f1b7ae16 100644 --- a/functions_func_n.html +++ b/functions_func_n.html @@ -78,7 +78,7 @@ $(function() { diff --git a/functions_func_o.html b/functions_func_o.html index f63df36f3..dd846ecb9 100644 --- a/functions_func_o.html +++ b/functions_func_o.html @@ -90,7 +90,7 @@ $(function() { diff --git a/functions_func_p.html b/functions_func_p.html index fad3429dc..02df648dc 100644 --- a/functions_func_p.html +++ b/functions_func_p.html @@ -83,7 +83,7 @@ $(function() { diff --git a/functions_func_q.html b/functions_func_q.html index 13825e84b..683127279 100644 --- a/functions_func_q.html +++ b/functions_func_q.html @@ -78,7 +78,7 @@ $(function() { diff --git a/functions_func_r.html b/functions_func_r.html index a6d4e5b0d..abd78bf79 100644 --- a/functions_func_r.html +++ b/functions_func_r.html @@ -91,7 +91,7 @@ $(function() { diff --git a/functions_func_s.html b/functions_func_s.html index 6e3647125..f528eca1b 100644 --- a/functions_func_s.html +++ b/functions_func_s.html @@ -98,7 +98,7 @@ $(function() { diff --git a/functions_func_t.html b/functions_func_t.html index dde27f92b..0f6c4b984 100644 --- a/functions_func_t.html +++ b/functions_func_t.html @@ -83,7 +83,7 @@ $(function() { diff --git a/functions_func_u.html b/functions_func_u.html index 98d402e68..1d8ea3ff0 100644 --- a/functions_func_u.html +++ b/functions_func_u.html @@ -79,7 +79,7 @@ $(function() { diff --git a/functions_func_v.html b/functions_func_v.html index abda6321f..a4242dcc9 100644 --- a/functions_func_v.html +++ b/functions_func_v.html @@ -78,7 +78,7 @@ $(function() { diff --git a/functions_func_w.html b/functions_func_w.html index c831cdbba..6edd34f2b 100644 --- a/functions_func_w.html +++ b/functions_func_w.html @@ -87,7 +87,7 @@ $(function() { diff --git a/functions_func_~.html b/functions_func_~.html index 112095e3f..c0622ddff 100644 --- a/functions_func_~.html +++ b/functions_func_~.html @@ -79,7 +79,7 @@ $(function() { diff --git a/functions_g.html b/functions_g.html index d06546900..ebb733b59 100644 --- a/functions_g.html +++ b/functions_g.html @@ -79,7 +79,7 @@ $(function() { diff --git a/functions_h.html b/functions_h.html index 97811ef09..ca22f411d 100644 --- a/functions_h.html +++ b/functions_h.html @@ -82,7 +82,7 @@ $(function() { diff --git a/functions_i.html b/functions_i.html index 785b9fd29..6af06a91f 100644 --- a/functions_i.html +++ b/functions_i.html @@ -76,14 +76,14 @@ $(function() {
  • id() : stdex::idrec::record< T, T_ID, ID, T_SIZE, ALIGN >
  • integer : stdex::parser::basic_mixed_numeral< T >, stdex::parser::basic_monetary_numeral< T >, stdex::parser::basic_scientific_numeral< T >
  • interactive_process : stdex::sys_info_t
  • -
  • interval() : stdex::interval< T >, stdex::parser::basic_parser< T >
  • +
  • interval() : stdex::interval< T >, stdex::parser::basic_parser< T >
  • invalidate() : stdex::interval< T >
  • is_valid : stdex::parser::basic_creditor_reference< T >, stdex::parser::basic_iban< T >, stdex::parser::basic_si_reference< T >
  • diff --git a/functions_l.html b/functions_l.html index 92ff4590d..46d1d7058 100644 --- a/functions_l.html +++ b/functions_l.html @@ -81,7 +81,7 @@ $(function() { diff --git a/functions_m.html b/functions_m.html index 3b4fb3716..58ef2cd76 100644 --- a/functions_m.html +++ b/functions_m.html @@ -105,7 +105,7 @@ $(function() { diff --git a/functions_n.html b/functions_n.html index 0a1b74f5b..013df5c33 100644 --- a/functions_n.html +++ b/functions_n.html @@ -85,7 +85,7 @@ $(function() { diff --git a/functions_o.html b/functions_o.html index 77a8c7440..fcce1fef9 100644 --- a/functions_o.html +++ b/functions_o.html @@ -94,7 +94,7 @@ $(function() { diff --git a/functions_p.html b/functions_p.html index 0d23e1a6f..acf485b9b 100644 --- a/functions_p.html +++ b/functions_p.html @@ -90,7 +90,7 @@ $(function() { diff --git a/functions_q.html b/functions_q.html index 5f7b5907d..39ff448fc 100644 --- a/functions_q.html +++ b/functions_q.html @@ -78,7 +78,7 @@ $(function() { diff --git a/functions_r.html b/functions_r.html index 537d6157d..4b6f61281 100644 --- a/functions_r.html +++ b/functions_r.html @@ -94,7 +94,7 @@ $(function() { diff --git a/functions_rela.html b/functions_rela.html index 948129337..94714b7bb 100644 --- a/functions_rela.html +++ b/functions_rela.html @@ -77,7 +77,7 @@ $(function() { diff --git a/functions_s.html b/functions_s.html index 0da330aaa..36c8577f5 100644 --- a/functions_s.html +++ b/functions_s.html @@ -104,7 +104,7 @@ $(function() { diff --git a/functions_t.html b/functions_t.html index f8016260e..3580cf69f 100644 --- a/functions_t.html +++ b/functions_t.html @@ -84,7 +84,7 @@ $(function() { diff --git a/functions_type.html b/functions_type.html index 291630dad..2053f229d 100644 --- a/functions_type.html +++ b/functions_type.html @@ -81,7 +81,7 @@ $(function() { diff --git a/functions_u.html b/functions_u.html index ad83456cf..c60a36d48 100644 --- a/functions_u.html +++ b/functions_u.html @@ -79,7 +79,7 @@ $(function() { diff --git a/functions_v.html b/functions_v.html index 93c45a85d..3e8a6c9ac 100644 --- a/functions_v.html +++ b/functions_v.html @@ -81,7 +81,7 @@ $(function() { diff --git a/functions_vars.html b/functions_vars.html index 03a191b66..112b3edfd 100644 --- a/functions_vars.html +++ b/functions_vars.html @@ -125,7 +125,7 @@ $(function() {

    - i -

    @@ -225,7 +225,7 @@ $(function() { diff --git a/functions_w.html b/functions_w.html index 0427f4d7c..de7326d9f 100644 --- a/functions_w.html +++ b/functions_w.html @@ -89,7 +89,7 @@ $(function() { diff --git a/functions_~.html b/functions_~.html index 881687b3c..f685f660f 100644 --- a/functions_~.html +++ b/functions_~.html @@ -79,7 +79,7 @@ $(function() { diff --git a/hash_8cpp_source.html b/hash_8cpp_source.html index 6852c7e1a..e66ea5109 100644 --- a/hash_8cpp_source.html +++ b/hash_8cpp_source.html @@ -164,7 +164,7 @@ $(document).ready(function() { init_codefold(0); }); diff --git a/hash_8hpp_source.html b/hash_8hpp_source.html index d417a3772..4568c8d68 100644 --- a/hash_8hpp_source.html +++ b/hash_8hpp_source.html @@ -730,10 +730,10 @@ $(document).ready(function() { init_codefold(0); });
    stdex::sha1_hash
    Hashes as SHA1.
    Definition hash.hpp:504
    stdex::sha1_hash::clear
    virtual void clear()
    Initializes hash value and internal state.
    Definition hash.hpp:511
    stdex::sha1_hash::finalize
    virtual void finalize()
    Finalizes hash value.
    Definition hash.hpp:523
    -
    stdex::stream::basic
    ‍UTF-8 byte-order-mark
    Definition stream.hpp:78
    -
    stdex::stream::converter
    Modifies data on the fly when reading from/writing to a source stream. Could also be used to modify r...
    Definition stream.hpp:1021
    -
    stdex::stream::converter::read
    virtual size_t read(_Out_writes_bytes_to_opt_(length, return) void *data, size_t length)
    Reads block of data from the stream.
    Definition stream.hpp:1050
    -
    stdex::stream::converter::write
    virtual size_t write(_In_reads_bytes_opt_(length) const void *data, size_t length)
    Writes block of data to the stream.
    Definition stream.hpp:1058
    +
    stdex::stream::basic
    ‍UTF-8 byte-order-mark
    Definition stream.hpp:79
    +
    stdex::stream::converter
    Modifies data on the fly when reading from/writing to a source stream. Could also be used to modify r...
    Definition stream.hpp:1022
    +
    stdex::stream::converter::read
    virtual size_t read(_Out_writes_bytes_to_opt_(length, return) void *data, size_t length)
    Reads block of data from the stream.
    Definition stream.hpp:1051
    +
    stdex::stream::converter::write
    virtual size_t write(_In_reads_bytes_opt_(length) const void *data, size_t length)
    Writes block of data to the stream.
    Definition stream.hpp:1059
    stdex::stream_hasher
    Hashes read to or write from data of the stream.
    Definition hash.hpp:138
    stdex::stream_hasher::read
    virtual size_t read(_Out_writes_bytes_to_opt_(length, return) void *data, size_t length)
    Reads block of data from the stream.
    Definition hash.hpp:145
    stdex::stream_hasher::write
    virtual size_t write(_In_reads_bytes_opt_(length) const void *data, size_t length)
    Writes block of data to the stream.
    Definition hash.hpp:153
    @@ -743,7 +743,7 @@ $(document).ready(function() { init_codefold(0); }); diff --git a/hex_8hpp_source.html b/hex_8hpp_source.html index a873b3a23..4aaf01eaf 100644 --- a/hex_8hpp_source.html +++ b/hex_8hpp_source.html @@ -231,7 +231,7 @@ $(document).ready(function() { init_codefold(0); }); diff --git a/hierarchy.html b/hierarchy.html index 311ca7c20..f282c6df0 100644 --- a/hierarchy.html +++ b/hierarchy.html @@ -256,7 +256,7 @@ $(function() { diff --git a/idrec_8hpp_source.html b/idrec_8hpp_source.html index c1d80cf74..4424f6129 100644 --- a/idrec_8hpp_source.html +++ b/idrec_8hpp_source.html @@ -459,19 +459,19 @@ $(document).ready(function() { init_codefold(0); });
    stdex::idrec::record::operator<<
    friend std::ostream & operator<<(std::ostream &stream, const record< T, T_ID, ID, T_SIZE, ALIGN > r)
    Writes record to a stream.
    Definition idrec.hpp:405
    stdex::idrec::record::record
    record(const T &d)
    Constructs the class.
    Definition idrec.hpp:292
    stdex::idrec::record::close
    static std::streamoff close(std::ostream &stream, std::streamoff start)
    Updates record header.
    Definition idrec.hpp:347
    -
    stdex::stream::basic_file
    Basic seekable stream operations.
    Definition stream.hpp:823
    -
    stdex::stream::basic
    ‍UTF-8 byte-order-mark
    Definition stream.hpp:78
    -
    stdex::stream::basic::ok
    bool ok() const
    Returns true if the stream state is clean i.e. previous operation was succesful.
    Definition stream.hpp:174
    -
    stdex::stream::basic::skip
    virtual void skip(fsize_t amount)
    Skips given amount of bytes of data on the stream.
    Definition stream.hpp:141
    -
    stdex::stream::limiter
    Limits reading from/writing to stream to a predefined number of bytes.
    Definition stream.hpp:1550
    -
    stdex::stream::limiter::read_limit
    fsize_t read_limit
    Number of bytes left that may be read from the stream.
    Definition stream.hpp:1602
    -
    stdex::stream::memory_file
    In-memory file.
    Definition stream.hpp:3171
    -
    stdex::stream::memory_file::seek
    virtual fpos_t seek(foff_t offset, seek_t how=seek_t::beg)
    Seeks to specified relative file position.
    Definition stream.hpp:3732
    -
    stdex::stream::memory_file::data
    const void * data() const
    Returns pointer to data.
    Definition stream.hpp:3381
    +
    stdex::stream::basic_file
    Basic seekable stream operations.
    Definition stream.hpp:824
    +
    stdex::stream::basic
    ‍UTF-8 byte-order-mark
    Definition stream.hpp:79
    +
    stdex::stream::basic::ok
    bool ok() const
    Returns true if the stream state is clean i.e. previous operation was succesful.
    Definition stream.hpp:175
    +
    stdex::stream::basic::skip
    virtual void skip(fsize_t amount)
    Skips given amount of bytes of data on the stream.
    Definition stream.hpp:142
    +
    stdex::stream::limiter
    Limits reading from/writing to stream to a predefined number of bytes.
    Definition stream.hpp:1551
    +
    stdex::stream::limiter::read_limit
    fsize_t read_limit
    Number of bytes left that may be read from the stream.
    Definition stream.hpp:1603
    +
    stdex::stream::memory_file
    In-memory file.
    Definition stream.hpp:3172
    +
    stdex::stream::memory_file::seek
    virtual fpos_t seek(foff_t offset, seek_t how=seek_t::beg)
    Seeks to specified relative file position.
    Definition stream.hpp:3733
    +
    stdex::stream::memory_file::data
    const void * data() const
    Returns pointer to data.
    Definition stream.hpp:3382
    diff --git a/include_2stdex_2compat_8hpp_source.html b/include_2stdex_2compat_8hpp_source.html index 337c2133d..873fa55cf 100644 --- a/include_2stdex_2compat_8hpp_source.html +++ b/include_2stdex_2compat_8hpp_source.html @@ -145,157 +145,169 @@ $(document).ready(function() { init_codefold(0); });
    61#ifndef _In_reads_bytes_opt_
    62#define _In_reads_bytes_opt_(p)
    63#endif
    -
    64#ifndef _Printf_format_string_params_
    -
    65#define _Printf_format_string_params_(n)
    +
    64#ifndef _Printf_format_string_
    +
    65#define _Printf_format_string_
    66#endif
    -
    67
    -
    68#ifndef _Inout_
    -
    69#define _Inout_
    -
    70#endif
    -
    71#ifndef _Inout_opt_
    -
    72#define _Inout_opt_
    +
    67#ifndef _Printf_format_string_params_
    +
    68#define _Printf_format_string_params_(n)
    +
    69#endif
    +
    70
    +
    71#ifndef _Inout_
    +
    72#define _Inout_
    73#endif
    -
    74#ifndef _Inout_z_
    -
    75#define _Inout_z_
    +
    74#ifndef _Inout_opt_
    +
    75#define _Inout_opt_
    76#endif
    -
    77#ifndef _Inout_cap_
    -
    78#define _Inout_cap_(p)
    +
    77#ifndef _Inout_z_
    +
    78#define _Inout_z_
    79#endif
    -
    80#ifndef _Inout_count_
    -
    81#define _Inout_count_(p)
    +
    80#ifndef _Inout_z_count_
    +
    81#define _Inout_z_count_(p)
    82#endif
    -
    83#ifndef _Inout_updates_z_
    -
    84#define _Inout_updates_z_(p)
    +
    83#ifndef _Inout_cap_
    +
    84#define _Inout_cap_(p)
    85#endif
    -
    86
    -
    87#ifndef _Use_decl_annotations_
    -
    88#define _Use_decl_annotations_
    -
    89#endif
    -
    90
    -
    91#ifndef _Out_
    -
    92#define _Out_
    -
    93#endif
    -
    94#ifndef _Out_opt_
    -
    95#define _Out_opt_
    -
    96#endif
    -
    97#ifndef _Out_z_cap_
    -
    98#define _Out_z_cap_(p)
    +
    86#ifndef _Inout_count_
    +
    87#define _Inout_count_(p)
    +
    88#endif
    +
    89#ifndef _Inout_updates_z_
    +
    90#define _Inout_updates_z_(p)
    +
    91#endif
    +
    92
    +
    93#ifndef _Use_decl_annotations_
    +
    94#define _Use_decl_annotations_
    +
    95#endif
    +
    96
    +
    97#ifndef _Out_
    +
    98#define _Out_
    99#endif
    -
    100#ifndef _Out_writes_
    -
    101#define _Out_writes_(p)
    +
    100#ifndef _Out_opt_
    +
    101#define _Out_opt_
    102#endif
    -
    103#ifndef _Out_writes_opt_
    -
    104#define _Out_writes_opt_(p)
    +
    103#ifndef _Out_z_cap_
    +
    104#define _Out_z_cap_(p)
    105#endif
    -
    106#ifndef _Out_writes_opt_z_
    -
    107#define _Out_writes_opt_z_(p)
    +
    106#ifndef _Out_writes_
    +
    107#define _Out_writes_(p)
    108#endif
    -
    109#ifndef _Out_writes_bytes_
    -
    110#define _Out_writes_bytes_(p)
    +
    109#ifndef _Out_writes_opt_
    +
    110#define _Out_writes_opt_(p)
    111#endif
    -
    112#ifndef _Out_writes_to_
    -
    113#define _Out_writes_to_(p, q)
    +
    112#ifndef _Out_writes_opt_z_
    +
    113#define _Out_writes_opt_z_(p)
    114#endif
    -
    115#ifndef _Out_writes_all_
    -
    116#define _Out_writes_all_(p)
    +
    115#ifndef _Out_writes_bytes_
    +
    116#define _Out_writes_bytes_(p)
    117#endif
    -
    118#ifndef _Out_writes_z_
    -
    119#define _Out_writes_z_(p)
    +
    118#ifndef _Out_writes_to_
    +
    119#define _Out_writes_to_(p, q)
    120#endif
    -
    121#ifndef _Out_writes_bytes_to_opt_
    -
    122#define _Out_writes_bytes_to_opt_(p, q)
    +
    121#ifndef _Out_writes_all_
    +
    122#define _Out_writes_all_(p)
    123#endif
    -
    124
    -
    125#ifndef _Success_
    -
    126#define _Success_(p)
    -
    127#endif
    -
    128#ifndef _Ret_maybenull_
    -
    129#define _Ret_maybenull_
    -
    130#endif
    -
    131#ifndef _Ret_maybenull_z_
    -
    132#define _Ret_maybenull_z_
    +
    124#ifndef _Out_writes_z_
    +
    125#define _Out_writes_z_(p)
    +
    126#endif
    +
    127#ifndef _Out_writes_bytes_to_opt_
    +
    128#define _Out_writes_bytes_to_opt_(p, q)
    +
    129#endif
    +
    130
    +
    131#ifndef _Success_
    +
    132#define _Success_(p)
    133#endif
    -
    134#ifndef _Ret_notnull_
    -
    135#define _Ret_notnull_
    +
    134#ifndef _Ret_maybenull_
    +
    135#define _Ret_maybenull_
    136#endif
    -
    137#ifndef _Ret_z_
    -
    138#define _Ret_z_
    +
    137#ifndef _Ret_maybenull_z_
    +
    138#define _Ret_maybenull_z_
    139#endif
    -
    140#ifndef _Must_inspect_result_
    -
    141#define _Must_inspect_result_
    +
    140#ifndef _Ret_notnull_
    +
    141#define _Ret_notnull_
    142#endif
    -
    143#ifndef _Check_return_
    -
    144#define _Check_return_
    +
    143#ifndef _Ret_z_
    +
    144#define _Ret_z_
    145#endif
    -
    146#ifndef _Post_maybez_
    -
    147#define _Post_maybez_
    +
    146#ifndef _Must_inspect_result_
    +
    147#define _Must_inspect_result_
    148#endif
    -
    149#ifndef _Null_terminated_
    -
    150#define _Null_terminated_
    +
    149#ifndef _Check_return_
    +
    150#define _Check_return_
    151#endif
    -
    152
    -
    153#ifndef _Likely_
    -
    154#if _HAS_CXX20
    -
    155#define _Likely_ [[likely]]
    -
    156#else
    -
    157#define _Likely_
    -
    158#endif
    -
    159#endif
    -
    160
    -
    161#ifndef _Unlikely_
    -
    162#if _HAS_CXX20
    -
    163#define _Unlikely_ [[unlikely]]
    -
    164#else
    -
    165#define _Unlikely_
    -
    166#endif
    -
    167#endif
    -
    168
    -
    169#if _HAS_CXX17
    -
    170#define _Constexpr_ constexpr
    -
    171#else
    -
    172#define _Constexpr_
    +
    152#ifndef _Post_maybez_
    +
    153#define _Post_maybez_
    +
    154#endif
    +
    155#ifndef _Null_terminated_
    +
    156#define _Null_terminated_
    +
    157#endif
    +
    158
    +
    159#ifndef _Likely_
    +
    160#if _HAS_CXX20
    +
    161#define _Likely_ [[likely]]
    +
    162#else
    +
    163#define _Likely_
    +
    164#endif
    +
    165#endif
    +
    166
    +
    167#ifndef _Unlikely_
    +
    168#if _HAS_CXX20
    +
    169#define _Unlikely_ [[unlikely]]
    +
    170#else
    +
    171#define _Unlikely_
    +
    172#endif
    173#endif
    174
    -
    175#ifdef _MSC_VER
    -
    176#define _Deprecated_(message) __declspec(deprecated(message))
    +
    175#if _HAS_CXX17
    +
    176#define _Constexpr_ constexpr
    177#else
    -
    178#define _Deprecated_(message) [[deprecated(message)]]
    +
    178#define _Constexpr_
    179#endif
    180
    -
    181#ifdef _WIN32
    -
    182#define _Unreferenced_(x) UNREFERENCED_PARAMETER(x)
    +
    181#ifdef _MSC_VER
    +
    182#define _Deprecated_(message) __declspec(deprecated(message))
    183#else
    -
    184#define _Unreferenced_(x)
    +
    184#define _Deprecated_(message) [[deprecated(message)]]
    185#endif
    186
    -
    187#ifndef _WIN32
    -
    188template <typename T, size_t N>
    -
    189size_t _countof(T (&arr)[N])
    -
    190{
    -
    191 return std::extent<T[N]>::value;
    -
    192}
    -
    193#endif
    -
    194
    -
    195#ifndef _Analysis_assume_
    -
    196#define _Analysis_assume_(p)
    -
    197#endif
    -
    198#ifdef NDEBUG
    -
    199#define _Assume_(p) _Analysis_assume_(p)
    -
    200#else
    -
    201#define _Assume_(p) assert(p)
    -
    202#endif
    -
    203
    -
    204#ifdef __APPLE__
    -
    205#define off64_t off_t
    -
    206#define lseek64 lseek
    -
    207#define lockf64 lockf
    -
    208#define ftruncate64 ftruncate
    -
    209#endif
    -
    210
    +
    187#ifdef _WIN32
    +
    188#define _Unreferenced_(x) UNREFERENCED_PARAMETER(x)
    +
    189#else
    +
    190#define _Unreferenced_(x)
    +
    191#endif
    +
    192
    +
    193#ifndef _WIN32
    +
    194template <typename T, size_t N>
    +
    195size_t _countof(T (&arr)[N])
    +
    196{
    +
    197 return std::extent<T[N]>::value;
    +
    198}
    +
    199#endif
    +
    200
    +
    201#ifndef _Analysis_assume_
    +
    202#define _Analysis_assume_(p)
    +
    203#endif
    +
    204#ifdef NDEBUG
    +
    205#define _Assume_(p) _Analysis_assume_(p)
    +
    206#else
    +
    207#define _Assume_(p) assert(p)
    +
    208#endif
    +
    209
    +
    210#ifdef __APPLE__
    +
    211#define off64_t off_t
    +
    212#define lseek64 lseek
    +
    213#define lockf64 lockf
    +
    214#define ftruncate64 ftruncate
    +
    215#endif
    +
    216
    +
    217#ifndef _WIN32
    +
    218typedef int SOCKET;
    +
    219#define INVALID_SOCKET ((SOCKET)-1)
    +
    220#define SOCKET_ERROR -1
    +
    221#define closesocket close
    +
    222#endif
    diff --git a/index.html b/index.html index 6b71d548f..de5a7db79 100644 --- a/index.html +++ b/index.html @@ -78,7 +78,7 @@ $(function() { diff --git a/interval_8hpp_source.html b/interval_8hpp_source.html index 27378c489..176296e22 100644 --- a/interval_8hpp_source.html +++ b/interval_8hpp_source.html @@ -126,7 +126,7 @@ $(document).ready(function() { init_codefold(0); });
    88 inline interval<T> operator+(_In_ const interval<T>& other) const
    89 {
    -
    90 return interval<T>(start + other.start, end + other.end);i.
    +
    90 return interval<T>(start + other.start, end + other.end);
    91 }
    92
    @@ -231,7 +231,7 @@ $(document).ready(function() { init_codefold(0); }); diff --git a/mapping_8hpp_source.html b/mapping_8hpp_source.html index 69313d282..fd00f4f11 100644 --- a/mapping_8hpp_source.html +++ b/mapping_8hpp_source.html @@ -124,7 +124,7 @@ $(document).ready(function() { init_codefold(0); }); diff --git a/math_8cpp_source.html b/math_8cpp_source.html index ac308acdf..3bb4d625b 100644 --- a/math_8cpp_source.html +++ b/math_8cpp_source.html @@ -129,7 +129,7 @@ $(document).ready(function() { init_codefold(0); }); diff --git a/math_8hpp_source.html b/math_8hpp_source.html index 2d8f3431a..6e05dbbc4 100644 --- a/math_8hpp_source.html +++ b/math_8hpp_source.html @@ -147,7 +147,7 @@ $(document).ready(function() { init_codefold(0); }); diff --git a/memory_8hpp_source.html b/memory_8hpp_source.html index 76d622be5..e44be963f 100644 --- a/memory_8hpp_source.html +++ b/memory_8hpp_source.html @@ -129,7 +129,7 @@ $(document).ready(function() { init_codefold(0); }); diff --git a/parser_8cpp_source.html b/parser_8cpp_source.html index 2c5b3e153..57be8f58d 100644 --- a/parser_8cpp_source.html +++ b/parser_8cpp_source.html @@ -119,55 +119,55 @@ $(document).ready(function() { init_codefold(0); });
    35 {
    36 wnoop p;
    37 Assert::IsTrue(p.match(text));
    -
    38 Assert::AreEqual((size_t)0, p.interval.start);
    -
    39 Assert::AreEqual((size_t)0, p.interval.end);
    +
    38 Assert::AreEqual((size_t)0, p.interval.start);
    +
    39 Assert::AreEqual((size_t)0, p.interval.end);
    40 }
    41
    42 {
    43 wcu p(L't');
    44 Assert::IsFalse(p.match(text));
    45 Assert::IsTrue(p.match(text, 0, _countof(text), match_case_insensitive));
    -
    46 Assert::AreEqual((size_t)0, p.interval.start);
    -
    47 Assert::AreEqual((size_t)1, p.interval.end);
    +
    46 Assert::AreEqual((size_t)0, p.interval.start);
    +
    47 Assert::AreEqual((size_t)1, p.interval.end);
    48 }
    49
    50 {
    51 wspace_cu p;
    52 Assert::IsFalse(p.match(text));
    53 Assert::IsTrue(p.match(text, 4));
    -
    54 Assert::AreEqual((size_t)4, p.interval.start);
    -
    55 Assert::AreEqual((size_t)5, p.interval.end);
    +
    54 Assert::AreEqual((size_t)4, p.interval.start);
    +
    55 Assert::AreEqual((size_t)5, p.interval.end);
    56 }
    57
    58 {
    59 wpunct_cu p;
    60 Assert::IsFalse(p.match(text));
    61 Assert::IsTrue(p.match(text, 14));
    -
    62 Assert::AreEqual((size_t)14, p.interval.start);
    -
    63 Assert::AreEqual((size_t)15, p.interval.end);
    +
    62 Assert::AreEqual((size_t)14, p.interval.start);
    +
    63 Assert::AreEqual((size_t)15, p.interval.end);
    64 }
    65
    66 {
    67 wspace_or_punct_cu p;
    68 Assert::IsFalse(p.match(text));
    69 Assert::IsTrue(p.match(text, 4));
    -
    70 Assert::AreEqual((size_t)4, p.interval.start);
    -
    71 Assert::AreEqual((size_t)5, p.interval.end);
    +
    70 Assert::AreEqual((size_t)4, p.interval.start);
    +
    71 Assert::AreEqual((size_t)5, p.interval.end);
    72 Assert::IsTrue(p.match(text, 14));
    -
    73 Assert::AreEqual((size_t)14, p.interval.start);
    -
    74 Assert::AreEqual((size_t)15, p.interval.end);
    +
    73 Assert::AreEqual((size_t)14, p.interval.start);
    +
    74 Assert::AreEqual((size_t)15, p.interval.end);
    75 }
    76
    77 {
    78 wbol p;
    79 Assert::IsTrue(p.match(text));
    -
    80 Assert::AreEqual((size_t)0, p.interval.start);
    -
    81 Assert::AreEqual((size_t)0, p.interval.end);
    +
    80 Assert::AreEqual((size_t)0, p.interval.start);
    +
    81 Assert::AreEqual((size_t)0, p.interval.end);
    82 Assert::IsFalse(p.match(text, 1));
    83 Assert::IsFalse(p.match(text, 15));
    84 Assert::IsTrue(p.match(text, 16));
    -
    85 Assert::AreEqual((size_t)16, p.interval.start);
    -
    86 Assert::AreEqual((size_t)16, p.interval.end);
    +
    85 Assert::AreEqual((size_t)16, p.interval.start);
    +
    86 Assert::AreEqual((size_t)16, p.interval.end);
    87 }
    88
    89 {
    @@ -175,8 +175,8 @@ $(document).ready(function() { init_codefold(0); });
    91 Assert::IsFalse(p.match(text));
    92 Assert::IsFalse(p.match(text, 1));
    93 Assert::IsTrue(p.match(text, 15));
    -
    94 Assert::AreEqual((size_t)15, p.interval.start);
    -
    95 Assert::AreEqual((size_t)15, p.interval.end);
    +
    94 Assert::AreEqual((size_t)15, p.interval.start);
    +
    95 Assert::AreEqual((size_t)15, p.interval.end);
    96 Assert::IsFalse(p.match(text, 16));
    97 }
    98
    @@ -184,13 +184,13 @@ $(document).ready(function() { init_codefold(0); });
    100 wcu_set p(L"abcD");
    101 Assert::IsFalse(p.match(text));
    102 Assert::IsTrue(p.match(text, 8));
    -
    103 Assert::AreEqual((size_t)8, p.interval.start);
    -
    104 Assert::AreEqual((size_t)9, p.interval.end);
    +
    103 Assert::AreEqual((size_t)8, p.interval.start);
    +
    104 Assert::AreEqual((size_t)9, p.interval.end);
    105 Assert::AreEqual((size_t)0, p.hit_offset);
    106 Assert::IsFalse(p.match(text, 21));
    107 Assert::IsTrue(p.match(text, 21, _countof(text), match_case_insensitive));
    -
    108 Assert::AreEqual((size_t)21, p.interval.start);
    -
    109 Assert::AreEqual((size_t)22, p.interval.end);
    +
    108 Assert::AreEqual((size_t)21, p.interval.start);
    +
    109 Assert::AreEqual((size_t)22, p.interval.end);
    110 Assert::AreEqual((size_t)3, p.hit_offset);
    111 }
    112
    @@ -198,24 +198,24 @@ $(document).ready(function() { init_codefold(0); });
    114 stdex::parser::wstring p(L"this");
    115 Assert::IsFalse(p.match(text));
    116 Assert::IsTrue(p.match(text, 0, sizeof(text), match_case_insensitive));
    -
    117 Assert::AreEqual((size_t)0, p.interval.start);
    -
    118 Assert::AreEqual((size_t)4, p.interval.end);
    +
    117 Assert::AreEqual((size_t)0, p.interval.start);
    +
    118 Assert::AreEqual((size_t)4, p.interval.end);
    119 }
    120
    121 {
    122 wany_cu chr;
    123 witerations p(make_shared_no_delete(&chr), 1, 5);
    124 Assert::IsTrue(p.match(text));
    -
    125 Assert::AreEqual((size_t)0, p.interval.start);
    -
    126 Assert::AreEqual((size_t)5, p.interval.end);
    +
    125 Assert::AreEqual((size_t)0, p.interval.start);
    +
    126 Assert::AreEqual((size_t)5, p.interval.end);
    127 }
    128
    129 {
    130 wspace_cu nospace(true);
    131 witerations p(make_shared_no_delete(&nospace), 1);
    132 Assert::IsTrue(p.match(text));
    -
    133 Assert::AreEqual((size_t)0, p.interval.start);
    -
    134 Assert::AreEqual((size_t)4, p.interval.end);
    +
    133 Assert::AreEqual((size_t)0, p.interval.start);
    +
    134 Assert::AreEqual((size_t)4, p.interval.end);
    135 }
    136
    137 {
    @@ -229,8 +229,8 @@ $(document).ready(function() { init_codefold(0); });
    145 make_shared_no_delete(&space) });
    146 Assert::IsFalse(p.match(text));
    147 Assert::IsTrue(p.match(text, 0, _countof(text), match_case_insensitive));
    -
    148 Assert::AreEqual((size_t)0, p.interval.start);
    -
    149 Assert::AreEqual((size_t)5, p.interval.end);
    +
    148 Assert::AreEqual((size_t)0, p.interval.start);
    +
    149 Assert::AreEqual((size_t)5, p.interval.end);
    150 }
    151
    152 {
    @@ -244,8 +244,8 @@ $(document).ready(function() { init_codefold(0); });
    160 Assert::IsFalse(p.match(text));
    161 Assert::IsTrue(p.match(text, 0, _countof(text), match_case_insensitive));
    162 Assert::AreEqual((size_t)2, p.hit_offset);
    -
    163 Assert::AreEqual((size_t)0, p.interval.start);
    -
    164 Assert::AreEqual((size_t)4, p.interval.end);
    +
    163 Assert::AreEqual((size_t)0, p.interval.start);
    +
    164 Assert::AreEqual((size_t)4, p.interval.end);
    165 }
    166
    167 {
    @@ -253,8 +253,8 @@ $(document).ready(function() { init_codefold(0); });
    169 Assert::IsFalse(p.match(text));
    170 Assert::IsTrue(p.match(text, 0, _countof(text), match_case_insensitive));
    171 Assert::AreEqual((size_t)2, p.hit_offset);
    -
    172 Assert::AreEqual((size_t)0, p.interval.start);
    -
    173 Assert::AreEqual((size_t)4, p.interval.end);
    +
    172 Assert::AreEqual((size_t)0, p.interval.start);
    +
    173 Assert::AreEqual((size_t)4, p.interval.end);
    174 }
    175
    176 {
    @@ -266,8 +266,8 @@ $(document).ready(function() { init_codefold(0); });
    182 make_shared_no_delete(&chr_t) });
    183 Assert::IsFalse(p.match(text));
    184 Assert::IsTrue(p.match(text, 0, _countof(text), match_case_insensitive));
    -
    185 Assert::AreEqual((size_t)0, p.interval.start);
    -
    186 Assert::AreEqual((size_t)4, p.interval.end);
    +
    185 Assert::AreEqual((size_t)0, p.interval.start);
    +
    186 Assert::AreEqual((size_t)4, p.interval.end);
    187 }
    188
    189 {
    @@ -289,7 +289,7 @@ $(document).ready(function() { init_codefold(0); });
    205 Assert::IsTrue(p.match(L"si56 0231 2001 5226 972", 0, SIZE_MAX, match_case_insensitive));
    206 Assert::IsTrue(p.is_valid);
    207 Assert::IsTrue(p.match(L"SI56 0231 2001 5226 9720", 0, SIZE_MAX));
    -
    208 Assert::AreEqual(stdex::interval<size_t>(0, 23), p.interval);
    +
    208 Assert::AreEqual(stdex::interval<size_t>(0, 23), p.interval);
    209 Assert::IsTrue(p.is_valid);
    210 Assert::IsTrue(p.match(L"...SI56 0231 2001 5226 972...", 3, SIZE_MAX));
    211 Assert::IsTrue(p.is_valid);
    @@ -363,11 +363,11 @@ $(document).ready(function() { init_codefold(0); });
    279 Assert::IsTrue(p.match(L"SI121234567890120", 0, SIZE_MAX));
    280 Assert::IsTrue(p.is_valid);
    281 Assert::AreEqual(L"12", p.model);
    -
    282 Assert::AreEqual(stdex::interval<size_t>(4, 17), p.part1.interval);
    +
    282 Assert::AreEqual(stdex::interval<size_t>(4, 17), p.part1.interval);
    283 Assert::IsTrue(p.match(L"SI12 1234567890120", 0, SIZE_MAX));
    284 Assert::IsTrue(p.is_valid);
    285 Assert::AreEqual(L"12", p.model);
    -
    286 Assert::AreEqual(stdex::interval<size_t>(5, 18), p.part1.interval);
    +
    286 Assert::AreEqual(stdex::interval<size_t>(5, 18), p.part1.interval);
    287 Assert::IsFalse(p.match(L"si12 1234567890120", 0, SIZE_MAX));
    288 Assert::IsTrue(p.match(L"si12 1234567890120", 0, SIZE_MAX, match_case_insensitive));
    289 Assert::IsTrue(p.match(L"...SI12 1234567890120...", 3, SIZE_MAX));
    @@ -383,35 +383,35 @@ $(document).ready(function() { init_codefold(0); });
    299 {
    300 sgml_noop p;
    301 Assert::IsTrue(p.match(text));
    -
    302 Assert::AreEqual((size_t)0, p.interval.start);
    -
    303 Assert::AreEqual((size_t)0, p.interval.end);
    +
    302 Assert::AreEqual((size_t)0, p.interval.start);
    +
    303 Assert::AreEqual((size_t)0, p.interval.end);
    304 }
    305
    306 {
    307 sgml_cp p("v");
    308 Assert::IsFalse(p.match(text));
    309 Assert::IsTrue(p.match(text, 0, _countof(text), match_case_insensitive));
    -
    310 Assert::AreEqual((size_t)0, p.interval.start);
    -
    311 Assert::AreEqual((size_t)1, p.interval.end);
    +
    310 Assert::AreEqual((size_t)0, p.interval.start);
    +
    311 Assert::AreEqual((size_t)1, p.interval.end);
    312 }
    313
    314 {
    315 sgml_cp p("&Zcaron;", SIZE_MAX, false, locale_slSI);
    316 Assert::IsFalse(p.match(text, 4));
    317 Assert::IsTrue(p.match(text, 4, _countof(text), match_case_insensitive));
    -
    318 Assert::AreEqual((size_t)4, p.interval.start);
    -
    319 Assert::AreEqual((size_t)12, p.interval.end);
    +
    318 Assert::AreEqual((size_t)4, p.interval.start);
    +
    319 Assert::AreEqual((size_t)12, p.interval.end);
    320 }
    321
    322 {
    323 sgml_space_cp p(false, locale_slSI);
    324 Assert::IsFalse(p.match(text));
    325 Assert::IsTrue(p.match(text, 1));
    -
    326 Assert::AreEqual((size_t)1, p.interval.start);
    -
    327 Assert::AreEqual((size_t)2, p.interval.end);
    +
    326 Assert::AreEqual((size_t)1, p.interval.start);
    +
    327 Assert::AreEqual((size_t)2, p.interval.end);
    328 Assert::IsTrue(p.match(text, 79));
    -
    329 Assert::AreEqual((size_t)79, p.interval.start);
    -
    330 Assert::AreEqual((size_t)85, p.interval.end);
    +
    329 Assert::AreEqual((size_t)79, p.interval.start);
    +
    330 Assert::AreEqual((size_t)85, p.interval.end);
    331 }
    332
    333 {
    @@ -419,8 +419,8 @@ $(document).ready(function() { init_codefold(0); });
    335 Assert::IsFalse(p.match(text, 2));
    336 Assert::IsTrue(p.match(text, 2, _countof(text), match_case_insensitive));
    337 Assert::AreEqual((size_t)2, p.hit_offset);
    -
    338 Assert::AreEqual((size_t)2, p.interval.start);
    -
    339 Assert::AreEqual((size_t)31, p.interval.end);
    +
    338 Assert::AreEqual((size_t)2, p.interval.start);
    +
    339 Assert::AreEqual((size_t)31, p.interval.end);
    340 }
    341
    342 {
    @@ -441,7 +441,7 @@ $(document).ready(function() { init_codefold(0); });
    357 Assert::IsTrue(p.match("si56 0231 2001 5226 972", 0, SIZE_MAX, match_case_insensitive));
    358 Assert::IsTrue(p.is_valid);
    359 Assert::IsTrue(p.match("SI56 0231 2001 5226 9720", 0, SIZE_MAX));
    -
    360 Assert::AreEqual(stdex::interval<size_t>(0, 23), p.interval);
    +
    360 Assert::AreEqual(stdex::interval<size_t>(0, 23), p.interval);
    361 Assert::IsTrue(p.is_valid);
    362 Assert::IsTrue(p.match("...SI56 0231 2001 5226 972...", 3, SIZE_MAX));
    363 Assert::IsTrue(p.is_valid);
    @@ -478,11 +478,11 @@ $(document).ready(function() { init_codefold(0); });
    394 Assert::IsTrue(p.match("SI121234567890120", 0, SIZE_MAX));
    395 Assert::IsTrue(p.is_valid);
    396 Assert::AreEqual("12", p.model);
    -
    397 Assert::AreEqual(stdex::interval<size_t>(4, 17), p.part1.interval);
    +
    397 Assert::AreEqual(stdex::interval<size_t>(4, 17), p.part1.interval);
    398 Assert::IsTrue(p.match("SI12 1234567890120", 0, SIZE_MAX));
    399 Assert::IsTrue(p.is_valid);
    400 Assert::AreEqual("12", p.model);
    -
    401 Assert::AreEqual(stdex::interval<size_t>(5, 18), p.part1.interval);
    +
    401 Assert::AreEqual(stdex::interval<size_t>(5, 18), p.part1.interval);
    402 Assert::IsFalse(p.match("si12 1234567890120", 0, SIZE_MAX));
    403 Assert::IsTrue(p.match("si12 1234567890120", 0, SIZE_MAX, match_case_insensitive));
    404 Assert::IsTrue(p.match("...SI12 1234567890120...", 3, SIZE_MAX));
    @@ -515,14 +515,14 @@ $(document).ready(function() { init_codefold(0); });
    431 {
    432 http_request p(locale);
    433 Assert::IsTrue(p.match(request));
    -
    434 Assert::AreEqual((size_t)0, p.interval.start);
    -
    435 Assert::AreEqual((size_t)14, p.interval.end);
    +
    434 Assert::AreEqual((size_t)0, p.interval.start);
    +
    435 Assert::AreEqual((size_t)14, p.interval.end);
    436 Assert::AreEqual((size_t)0, p.verb.start);
    437 Assert::AreEqual((size_t)3, p.verb.end);
    -
    438 Assert::AreEqual((size_t)4, p.url.interval.start);
    -
    439 Assert::AreEqual((size_t)5, p.url.interval.end);
    -
    440 Assert::AreEqual((size_t)6, p.protocol.interval.start);
    -
    441 Assert::AreEqual((size_t)12, p.protocol.interval.end);
    +
    438 Assert::AreEqual((size_t)4, p.url.interval.start);
    +
    439 Assert::AreEqual((size_t)5, p.url.interval.end);
    +
    440 Assert::AreEqual((size_t)6, p.protocol.interval.start);
    +
    441 Assert::AreEqual((size_t)12, p.protocol.interval.end);
    442 Assert::AreEqual((uint16_t)0x200, p.protocol.version);
    443 }
    444
    @@ -532,7 +532,7 @@ $(document).ready(function() { init_codefold(0); });
    448 for (;;) {
    449 http_header h;
    450 if (h.match(request, offset)) {
    -
    451 offset = h.interval.end;
    +
    451 offset = h.interval.end;
    452 hdrs.push_back(std::move(h));
    453 }
    454 else
    @@ -551,7 +551,7 @@ $(document).ready(function() { init_codefold(0); });
    467 auto c = control.cbegin();
    468 auto l = langs.cbegin();
    469 for (; c != control.cend() && l != langs.cend(); ++c, ++l)
    -
    470 Assert::IsTrue(strnicmp(request + l->value.interval.start, l->value.interval.size(), c->c_str(), c->size(), locale) == 0);
    +
    470 Assert::IsTrue(strnicmp(request + l->value.interval.start, l->value.interval.size(), c->c_str(), c->size(), locale) == 0);
    471 Assert::IsTrue(c == control.cend());
    472 Assert::IsTrue(l == langs.cend());
    473 }
    @@ -584,12 +584,12 @@ $(document).ready(function() { init_codefold(0); });
    500 };
    501}
    stdex::parser::basic_parser< char >
    -
    stdex::parser::basic_parser::interval
    interval< size_t > interval
    Region of the last match.
    Definition parser.hpp:176
    -
    stdex::parser::basic_string
    Test for given string.
    Definition parser.hpp:822
    -
    stdex::parser::http_header
    Test for HTTP header.
    Definition parser.hpp:7154
    -
    stdex::parser::http_request
    Test for HTTP request.
    Definition parser.hpp:7016
    -
    stdex::parser::sgml_cp
    Test for specific SGML code point.
    Definition parser.hpp:347
    -
    stdex::parser::sgml_space_cp
    Test for any SGML space code point.
    Definition parser.hpp:434
    +
    stdex::parser::basic_parser::interval
    stdex::interval< size_t > interval
    Region of the last match.
    Definition parser.hpp:173
    +
    stdex::parser::basic_string
    Test for given string.
    Definition parser.hpp:819
    +
    stdex::parser::http_header
    Test for HTTP header.
    Definition parser.hpp:7151
    +
    stdex::parser::http_request
    Test for HTTP request.
    Definition parser.hpp:7013
    +
    stdex::parser::sgml_cp
    Test for specific SGML code point.
    Definition parser.hpp:344
    +
    stdex::parser::sgml_space_cp
    Test for any SGML space code point.
    Definition parser.hpp:431
    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
    @@ -597,7 +597,7 @@ $(document).ready(function() { init_codefold(0); }); diff --git a/parser_8hpp_source.html b/parser_8hpp_source.html index efbe80384..62ae1f1ab 100644 --- a/parser_8hpp_source.html +++ b/parser_8hpp_source.html @@ -103,7511 +103,7508 @@ $(document).ready(function() { init_codefold(0); });
    19#include <ws2ipdef.h>
    20#endif
    21#include <ws2tcpip.h>
    -
    22#elif defined(__APPLE__)
    +
    22#else
    23#include <netinet/in.h>
    -
    24#else
    -
    25#include <inaddr.h>
    -
    26#include <in6addr.h>
    -
    27#endif
    -
    28#include <limits>
    -
    29#include <list>
    -
    30#include <locale>
    -
    31#include <memory>
    -
    32#include <set>
    -
    33#include <string>
    -
    34
    -
    35#ifdef _MSC_VER
    -
    36#pragma warning(push)
    -
    37#pragma warning(disable: 4100)
    -
    38#endif
    -
    39
    -
    40#define ENUM_FLAG_OPERATOR(T,X) \
    -
    41inline 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)); } \
    -
    42inline 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); } \
    -
    43inline 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)); } \
    -
    44inline T& operator X= (T& lhs, const T rhs) { return lhs = lhs X rhs; } \
    -
    45inline T& operator X= (T& lhs, const std::underlying_type_t<T> rhs) { return lhs = lhs X rhs; }
    -
    46#define ENUM_FLAGS(T, type) \
    -
    47enum class T : type; \
    -
    48inline T operator ~ (T t) { return (T) (~static_cast<std::underlying_type_t <T>>(t)); } \
    -
    49ENUM_FLAG_OPERATOR(T,|) \
    -
    50ENUM_FLAG_OPERATOR(T,^) \
    -
    51ENUM_FLAG_OPERATOR(T,&) \
    -
    52enum class T : type
    -
    53
    -
    54#if defined(_WIN32)
    -
    55#elif defined(__APPLE__)
    -
    56#define s6_words __u6_addr.__u6_addr16
    -
    57#else
    -
    58#error Unsupported platform
    -
    59#endif
    -
    60
    -
    61namespace stdex
    -
    62{
    -
    63 namespace parser
    -
    64 {
    -
    68 constexpr int match_default = 0;
    -
    69 constexpr int match_case_insensitive = 0x1;
    -
    70 constexpr int match_multiline = 0x2;
    -
    71
    -
    75 template <class T>
    -
    -
    76 class basic_parser
    -
    77 {
    -
    78 public:
    -
    79 basic_parser(_In_ const std::locale& locale = std::locale()) : m_locale(locale) {}
    -
    80 virtual ~basic_parser() {}
    -
    81
    -
    82 bool search(
    -
    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)
    -
    87 {
    -
    88 for (size_t i = start; i < end && text[i]; i++)
    -
    89 if (match(text, i, end, flags))
    -
    90 return true;
    -
    91 return false;
    -
    92 }
    -
    93
    -
    94 virtual bool match(
    -
    95 _In_reads_or_z_(end) const T* text,
    -
    96 _In_ size_t start = 0,
    -
    97 _In_ size_t end = (size_t)-1,
    -
    98 _In_ int flags = match_default) = 0;
    -
    99
    -
    100 template<class _Traits, class _Ax>
    -
    101 inline bool match(
    -
    102 const std::basic_string<T, _Traits, _Ax>& text,
    -
    103 _In_ size_t start = 0,
    -
    104 _In_ size_t end = (size_t)-1,
    -
    105 _In_ int flags = match_default)
    -
    106 {
    -
    107 return match(text.c_str(), start, std::min<size_t>(end, text.size()), flags);
    -
    108 }
    -
    109
    -
    110 virtual void invalidate()
    -
    111 {
    -
    112 this->interval.start = 1;
    -
    113 this->interval.end = 0;
    -
    114 }
    -
    115
    -
    116 protected:
    -
    118 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])
    -
    119 {
    -
    120 if (text[start] == '&') {
    -
    121 // Potential entity start
    -
    122 const auto& ctype = std::use_facet<std::ctype<T>>(m_locale);
    -
    123 for (chr_end = start + 1;; chr_end++) {
    -
    124 if (chr_end >= end || text[chr_end] == 0) {
    -
    125 // Unterminated entity
    -
    126 break;
    -
    127 }
    -
    128 if (text[chr_end] == ';') {
    -
    129 // Entity end
    -
    130 size_t n = chr_end - start - 1;
    -
    131 if (n >= 2 && text[start + 1] == '#') {
    -
    132 // Numerical entity
    -
    133 char32_t unicode;
    -
    134 if (text[start + 2] == 'x' || text[start + 2] == 'X')
    -
    135 unicode = strtou32(text + start + 3, n - 2, nullptr, 16);
    -
    136 else
    -
    137 unicode = strtou32(text + start + 2, n - 1, nullptr, 10);
    -
    138#ifdef _WIN32
    -
    139 if (unicode < 0x10000) {
    -
    140 buf[0] = (wchar_t)unicode;
    -
    141 buf[1] = 0;
    -
    142 }
    -
    143 else {
    -
    144 ucs4_to_surrogate_pair(buf, unicode);
    -
    145 buf[2] = 0;
    -
    146 }
    -
    147#else
    -
    148 buf[0] = (wchar_t)unicode;
    -
    149 buf[1] = 0;
    -
    150#endif
    -
    151 chr_end++;
    -
    152 return buf;
    -
    153 }
    -
    154 const wchar_t* entity_w = sgml2uni(text + start + 1, n);
    -
    155 if (entity_w) {
    -
    156 chr_end++;
    -
    157 return entity_w;
    -
    158 }
    -
    159 // Unknown entity.
    -
    160 break;
    -
    161 }
    -
    162 else if (text[chr_end] == '&' || ctype.is(ctype.space, text[chr_end])) {
    -
    163 // This char cannot possibly be a part of entity.
    -
    164 break;
    -
    165 }
    -
    166 }
    -
    167 }
    -
    168 buf[0] = text[start];
    -
    169 buf[1] = 0;
    -
    170 chr_end = start + 1;
    -
    171 return buf;
    -
    172 }
    +
    24#endif
    +
    25#include <limits>
    +
    26#include <list>
    +
    27#include <locale>
    +
    28#include <memory>
    +
    29#include <set>
    +
    30#include <string>
    +
    31
    +
    32#ifdef _MSC_VER
    +
    33#pragma warning(push)
    +
    34#pragma warning(disable: 4100)
    +
    35#endif
    +
    36
    +
    37#define ENUM_FLAG_OPERATOR(T,X) \
    +
    38inline 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)); } \
    +
    39inline 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); } \
    +
    40inline 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)); } \
    +
    41inline T& operator X= (T& lhs, const T rhs) { return lhs = lhs X rhs; } \
    +
    42inline T& operator X= (T& lhs, const std::underlying_type_t<T> rhs) { return lhs = lhs X rhs; }
    +
    43#define ENUM_FLAGS(T, type) \
    +
    44enum class T : type; \
    +
    45inline T operator ~ (T t) { return (T) (~static_cast<std::underlying_type_t <T>>(t)); } \
    +
    46ENUM_FLAG_OPERATOR(T,|) \
    +
    47ENUM_FLAG_OPERATOR(T,^) \
    +
    48ENUM_FLAG_OPERATOR(T,&) \
    +
    49enum class T : type
    +
    50
    +
    51#if defined(_WIN32)
    +
    52#elif defined(__APPLE__)
    +
    53#define s6_words __u6_addr.__u6_addr16
    +
    54#else
    +
    55#define s6_words s6_addr16
    +
    56#endif
    +
    57
    +
    58namespace stdex
    +
    59{
    +
    60 namespace parser
    +
    61 {
    +
    65 constexpr int match_default = 0;
    +
    66 constexpr int match_case_insensitive = 0x1;
    +
    67 constexpr int match_multiline = 0x2;
    +
    68
    +
    72 template <class T>
    +
    + +
    74 {
    +
    75 public:
    +
    76 basic_parser(_In_ const std::locale& locale = std::locale()) : m_locale(locale) {}
    +
    77 virtual ~basic_parser() {}
    +
    78
    +
    79 bool search(
    +
    80 _In_reads_or_z_(end) const T* text,
    +
    81 _In_ size_t start = 0,
    +
    82 _In_ size_t end = (size_t)-1,
    +
    83 _In_ int flags = match_default)
    +
    84 {
    +
    85 for (size_t i = start; i < end && text[i]; i++)
    +
    86 if (match(text, i, end, flags))
    +
    87 return true;
    +
    88 return false;
    +
    89 }
    +
    90
    +
    91 virtual bool match(
    +
    92 _In_reads_or_z_(end) const T* text,
    +
    93 _In_ size_t start = 0,
    +
    94 _In_ size_t end = (size_t)-1,
    +
    95 _In_ int flags = match_default) = 0;
    +
    96
    +
    97 template<class _Traits, class _Ax>
    +
    98 inline bool match(
    +
    99 const std::basic_string<T, _Traits, _Ax>& text,
    +
    100 _In_ size_t start = 0,
    +
    101 _In_ size_t end = (size_t)-1,
    +
    102 _In_ int flags = match_default)
    +
    103 {
    +
    104 return match(text.c_str(), start, std::min<size_t>(end, text.size()), flags);
    +
    105 }
    +
    106
    +
    107 virtual void invalidate()
    +
    108 {
    +
    109 this->interval.start = 1;
    +
    110 this->interval.end = 0;
    +
    111 }
    +
    112
    +
    113 protected:
    +
    115 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])
    +
    116 {
    +
    117 if (text[start] == '&') {
    +
    118 // Potential entity start
    +
    119 const auto& ctype = std::use_facet<std::ctype<T>>(m_locale);
    +
    120 for (chr_end = start + 1;; chr_end++) {
    +
    121 if (chr_end >= end || text[chr_end] == 0) {
    +
    122 // Unterminated entity
    +
    123 break;
    +
    124 }
    +
    125 if (text[chr_end] == ';') {
    +
    126 // Entity end
    +
    127 size_t n = chr_end - start - 1;
    +
    128 if (n >= 2 && text[start + 1] == '#') {
    +
    129 // Numerical entity
    +
    130 char32_t unicode;
    +
    131 if (text[start + 2] == 'x' || text[start + 2] == 'X')
    +
    132 unicode = strtou32(text + start + 3, n - 2, nullptr, 16);
    +
    133 else
    +
    134 unicode = strtou32(text + start + 2, n - 1, nullptr, 10);
    +
    135#ifdef _WIN32
    +
    136 if (unicode < 0x10000) {
    +
    137 buf[0] = (wchar_t)unicode;
    +
    138 buf[1] = 0;
    +
    139 }
    +
    140 else {
    +
    141 ucs4_to_surrogate_pair(buf, unicode);
    +
    142 buf[2] = 0;
    +
    143 }
    +
    144#else
    +
    145 buf[0] = (wchar_t)unicode;
    +
    146 buf[1] = 0;
    +
    147#endif
    +
    148 chr_end++;
    +
    149 return buf;
    +
    150 }
    +
    151 const wchar_t* entity_w = sgml2uni(text + start + 1, n);
    +
    152 if (entity_w) {
    +
    153 chr_end++;
    +
    154 return entity_w;
    +
    155 }
    +
    156 // Unknown entity.
    +
    157 break;
    +
    158 }
    +
    159 else if (text[chr_end] == '&' || ctype.is(ctype.space, text[chr_end])) {
    +
    160 // This char cannot possibly be a part of entity.
    +
    161 break;
    +
    162 }
    +
    163 }
    +
    164 }
    +
    165 buf[0] = text[start];
    +
    166 buf[1] = 0;
    +
    167 chr_end = start + 1;
    +
    168 return buf;
    +
    169 }
    +
    171
    +
    172 public:
    +
    174
    -
    175 public:
    - -
    177
    -
    178 protected:
    -
    179 std::locale m_locale;
    -
    180 };
    +
    175 protected:
    +
    176 std::locale m_locale;
    +
    177 };
    -
    181
    -
    182 using parser = basic_parser<char>;
    -
    183 using wparser = basic_parser<wchar_t>;
    -
    184#ifdef _UNICODE
    -
    185 using tparser = wparser;
    -
    186#else
    -
    187 using tparser = parser;
    -
    188#endif
    -
    189 using sgml_parser = basic_parser<char>;
    -
    190
    -
    194 template <class T>
    -
    -
    195 class basic_noop : public basic_parser<T>
    -
    196 {
    -
    197 public:
    -
    198 virtual bool match(
    -
    199 _In_reads_or_z_(end) const T* text,
    -
    200 _In_ size_t start = 0,
    -
    201 _In_ size_t end = (size_t)-1,
    -
    202 _In_ int flags = match_default)
    -
    203 {
    -
    204 _Assume_(text || start >= end);
    -
    205 if (start < end && text[start]) {
    -
    206 this->interval.start = this->interval.end = start;
    -
    207 return true;
    -
    208 }
    -
    209 this->interval.start = (this->interval.end = start) + 1;
    -
    210 return false;
    -
    211 }
    -
    212 };
    +
    178
    + + +
    181#ifdef _UNICODE
    +
    182 using tparser = wparser;
    +
    183#else
    +
    184 using tparser = parser;
    +
    185#endif
    + +
    187
    +
    191 template <class T>
    +
    +
    192 class basic_noop : public basic_parser<T>
    +
    193 {
    +
    194 public:
    +
    195 virtual bool match(
    +
    196 _In_reads_or_z_(end) const T* text,
    +
    197 _In_ size_t start = 0,
    +
    198 _In_ size_t end = (size_t)-1,
    +
    199 _In_ int flags = match_default)
    +
    200 {
    +
    201 _Assume_(text || start >= end);
    +
    202 if (start < end && text[start]) {
    +
    203 this->interval.start = this->interval.end = start;
    +
    204 return true;
    +
    205 }
    +
    206 this->interval.start = (this->interval.end = start) + 1;
    +
    207 return false;
    +
    208 }
    +
    209 };
    -
    213
    -
    214 using noop = basic_noop<char>;
    - -
    216#ifdef _UNICODE
    -
    217 using tnoop = wnoop;
    -
    218#else
    -
    219 using tnoop = noop;
    -
    220#endif
    - -
    222
    -
    226 template <class T>
    -
    -
    227 class basic_any_cu : public basic_parser<T>
    -
    228 {
    -
    229 public:
    -
    230 basic_any_cu(_In_ const std::locale& locale = std::locale()) : basic_parser<T>(locale) {}
    -
    231
    -
    232 virtual bool match(
    -
    233 _In_reads_or_z_(end) const T* text,
    -
    234 _In_ size_t start = 0,
    -
    235 _In_ size_t end = (size_t)-1,
    -
    236 _In_ int flags = match_default)
    -
    237 {
    -
    238 _Assume_(text || start >= end);
    -
    239 if (start < end && text[start]) {
    -
    240 this->interval.end = (this->interval.start = start) + 1;
    -
    241 return true;
    -
    242 }
    -
    243 this->interval.start = (this->interval.end = start) + 1;
    -
    244 return false;
    -
    245 }
    -
    246 };
    +
    210
    +
    211 using noop = basic_noop<char>;
    + +
    213#ifdef _UNICODE
    +
    214 using tnoop = wnoop;
    +
    215#else
    +
    216 using tnoop = noop;
    +
    217#endif
    + +
    219
    +
    223 template <class T>
    +
    +
    224 class basic_any_cu : public basic_parser<T>
    +
    225 {
    +
    226 public:
    +
    227 basic_any_cu(_In_ const std::locale& locale = std::locale()) : basic_parser<T>(locale) {}
    +
    228
    +
    229 virtual bool match(
    +
    230 _In_reads_or_z_(end) const T* text,
    +
    231 _In_ size_t start = 0,
    +
    232 _In_ size_t end = (size_t)-1,
    +
    233 _In_ int flags = match_default)
    +
    234 {
    +
    235 _Assume_(text || start >= end);
    +
    236 if (start < end && text[start]) {
    +
    237 this->interval.end = (this->interval.start = start) + 1;
    +
    238 return true;
    +
    239 }
    +
    240 this->interval.start = (this->interval.end = start) + 1;
    +
    241 return false;
    +
    242 }
    +
    243 };
    -
    247
    - - -
    250#ifdef _UNICODE
    -
    251 using tany_cu = wany_cu;
    -
    252#else
    -
    253 using tany_cu = any_cu;
    -
    254#endif
    -
    255
    -
    -
    259 class sgml_any_cp : public basic_any_cu<char>
    -
    260 {
    -
    261 public:
    -
    262 sgml_any_cp(_In_ const std::locale& locale = std::locale()) : basic_any_cu<char>(locale) {}
    -
    263
    -
    264 virtual bool match(
    -
    265 _In_reads_or_z_(end) const char* text,
    -
    266 _In_ size_t start = 0,
    -
    267 _In_ size_t end = (size_t)-1,
    -
    268 _In_ int flags = match_default)
    -
    269 {
    -
    270 _Assume_(text || start >= end);
    -
    271 if (start < end && text[start]) {
    -
    272 if (text[start] == '&') {
    -
    273 // SGML entity
    -
    274 const auto& ctype = std::use_facet<std::ctype<char>>(m_locale);
    -
    275 for (this->interval.end = start + 1; this->interval.end < end && text[this->interval.end]; this->interval.end++)
    -
    276 if (text[this->interval.end] == ';') {
    -
    277 this->interval.end++;
    -
    278 this->interval.start = start;
    -
    279 return true;
    -
    280 }
    -
    281 else if (text[this->interval.end] == '&' || ctype.is(ctype.space, text[this->interval.end]))
    -
    282 break;
    -
    283 // Unterminated entity
    -
    284 }
    -
    285 this->interval.end = (this->interval.start = start) + 1;
    -
    286 return true;
    -
    287 }
    -
    288 this->interval.start = (this->interval.end = start) + 1;
    -
    289 return false;
    -
    290 }
    -
    291 };
    +
    244
    + + +
    247#ifdef _UNICODE
    +
    248 using tany_cu = wany_cu;
    +
    249#else
    +
    250 using tany_cu = any_cu;
    +
    251#endif
    +
    252
    +
    +
    256 class sgml_any_cp : public basic_any_cu<char>
    +
    257 {
    +
    258 public:
    +
    259 sgml_any_cp(_In_ const std::locale& locale = std::locale()) : basic_any_cu<char>(locale) {}
    +
    260
    +
    261 virtual bool match(
    +
    262 _In_reads_or_z_(end) const char* text,
    +
    263 _In_ size_t start = 0,
    +
    264 _In_ size_t end = (size_t)-1,
    +
    265 _In_ int flags = match_default)
    +
    266 {
    +
    267 _Assume_(text || start >= end);
    +
    268 if (start < end && text[start]) {
    +
    269 if (text[start] == '&') {
    +
    270 // SGML entity
    +
    271 const auto& ctype = std::use_facet<std::ctype<char>>(m_locale);
    +
    272 for (this->interval.end = start + 1; this->interval.end < end && text[this->interval.end]; this->interval.end++)
    +
    273 if (text[this->interval.end] == ';') {
    +
    274 this->interval.end++;
    +
    275 this->interval.start = start;
    +
    276 return true;
    +
    277 }
    +
    278 else if (text[this->interval.end] == '&' || ctype.is(ctype.space, text[this->interval.end]))
    +
    279 break;
    +
    280 // Unterminated entity
    +
    281 }
    +
    282 this->interval.end = (this->interval.start = start) + 1;
    +
    283 return true;
    +
    284 }
    +
    285 this->interval.start = (this->interval.end = start) + 1;
    +
    286 return false;
    +
    287 }
    +
    288 };
    -
    292
    -
    296 template <class T>
    -
    -
    297 class basic_cu : public basic_parser<T>
    -
    298 {
    -
    299 public:
    -
    300 basic_cu(T chr, bool invert = false, _In_ const std::locale& locale = std::locale()) :
    -
    301 basic_parser<T>(locale),
    -
    302 m_chr(chr),
    -
    303 m_invert(invert)
    -
    304 {}
    -
    305
    -
    306 virtual bool match(
    -
    307 _In_reads_or_z_(end) const T* text,
    -
    308 _In_ size_t start = 0,
    -
    309 _In_ size_t end = (size_t)-1,
    -
    310 _In_ int flags = match_default)
    -
    311 {
    -
    312 _Assume_(text || start >= end);
    -
    313 if (start < end && text[start]) {
    -
    314 bool r;
    -
    315 if (flags & match_case_insensitive) {
    -
    316 const auto& ctype = std::use_facet<std::ctype<T>>(this->m_locale);
    -
    317 r = ctype.tolower(text[start]) == ctype.tolower(m_chr);
    -
    318 }
    -
    319 else
    -
    320 r = text[start] == m_chr;
    -
    321 if ((r && !m_invert) || (!r && m_invert)) {
    -
    322 this->interval.end = (this->interval.start = start) + 1;
    -
    323 return true;
    -
    324 }
    -
    325 }
    -
    326 this->interval.start = (this->interval.end = start) + 1;
    -
    327 return false;
    -
    328 }
    -
    329
    -
    330 protected:
    -
    331 T m_chr;
    -
    332 bool m_invert;
    -
    333 };
    +
    289
    +
    293 template <class T>
    +
    +
    294 class basic_cu : public basic_parser<T>
    +
    295 {
    +
    296 public:
    +
    297 basic_cu(T chr, bool invert = false, _In_ const std::locale& locale = std::locale()) :
    +
    298 basic_parser<T>(locale),
    +
    299 m_chr(chr),
    +
    300 m_invert(invert)
    +
    301 {}
    +
    302
    +
    303 virtual bool match(
    +
    304 _In_reads_or_z_(end) const T* text,
    +
    305 _In_ size_t start = 0,
    +
    306 _In_ size_t end = (size_t)-1,
    +
    307 _In_ int flags = match_default)
    +
    308 {
    +
    309 _Assume_(text || start >= end);
    +
    310 if (start < end && text[start]) {
    +
    311 bool r;
    +
    312 if (flags & match_case_insensitive) {
    +
    313 const auto& ctype = std::use_facet<std::ctype<T>>(this->m_locale);
    +
    314 r = ctype.tolower(text[start]) == ctype.tolower(m_chr);
    +
    315 }
    +
    316 else
    +
    317 r = text[start] == m_chr;
    +
    318 if ((r && !m_invert) || (!r && m_invert)) {
    +
    319 this->interval.end = (this->interval.start = start) + 1;
    +
    320 return true;
    +
    321 }
    +
    322 }
    +
    323 this->interval.start = (this->interval.end = start) + 1;
    +
    324 return false;
    +
    325 }
    +
    326
    +
    327 protected:
    +
    328 T m_chr;
    +
    329 bool m_invert;
    +
    330 };
    -
    334
    -
    335 using cu = basic_cu<char>;
    -
    336 using wcu = basic_cu<wchar_t>;
    -
    337#ifdef _UNICODE
    -
    338 using tcu = wcu;
    -
    339#else
    -
    340 using tcu = cu;
    -
    341#endif
    -
    342
    -
    -
    346 class sgml_cp : public sgml_parser
    -
    347 {
    -
    348 public:
    -
    349 sgml_cp(const char* chr, size_t count = (size_t)-1, bool invert = false, _In_ const std::locale& locale = std::locale()) :
    -
    350 sgml_parser(locale),
    -
    351 m_invert(invert)
    -
    352 {
    -
    353 _Assume_(chr || !count);
    -
    354 wchar_t buf[3];
    -
    355 size_t chr_end;
    -
    356 m_chr.assign(count ? next_sgml_cp(chr, 0, count, chr_end, buf) : L"");
    -
    357 }
    -
    358
    -
    359 virtual bool match(
    -
    360 _In_reads_or_z_(end) const char* text,
    -
    361 _In_ size_t start = 0,
    -
    362 _In_ size_t end = (size_t)-1,
    -
    363 _In_ int flags = match_default)
    -
    364 {
    -
    365 _Assume_(text || start >= end);
    -
    366 if (start < end && text[start]) {
    -
    367 wchar_t buf[3];
    -
    368 const wchar_t* chr = next_sgml_cp(text, start, end, this->interval.end, buf);
    -
    369 bool r = ((flags & match_case_insensitive) ?
    -
    370 stdex::strnicmp(chr, (size_t)-1, m_chr.c_str(), m_chr.size(), m_locale) :
    -
    371 stdex::strncmp(chr, (size_t)-1, m_chr.c_str(), m_chr.size())) == 0;
    -
    372 if ((r && !m_invert) || (!r && m_invert)) {
    -
    373 this->interval.start = start;
    -
    374 return true;
    -
    375 }
    -
    376 }
    -
    377 this->interval.start = (this->interval.end = start) + 1;
    -
    378 return false;
    -
    379 }
    -
    380
    -
    381 protected:
    -
    382 std::wstring m_chr;
    -
    383 bool m_invert;
    -
    384 };
    +
    331
    +
    332 using cu = basic_cu<char>;
    +
    333 using wcu = basic_cu<wchar_t>;
    +
    334#ifdef _UNICODE
    +
    335 using tcu = wcu;
    +
    336#else
    +
    337 using tcu = cu;
    +
    338#endif
    +
    339
    +
    +
    343 class sgml_cp : public sgml_parser
    +
    344 {
    +
    345 public:
    +
    346 sgml_cp(const char* chr, size_t count = (size_t)-1, bool invert = false, _In_ const std::locale& locale = std::locale()) :
    +
    347 sgml_parser(locale),
    +
    348 m_invert(invert)
    +
    349 {
    +
    350 _Assume_(chr || !count);
    +
    351 wchar_t buf[3];
    +
    352 size_t chr_end;
    +
    353 m_chr.assign(count ? next_sgml_cp(chr, 0, count, chr_end, buf) : L"");
    +
    354 }
    +
    355
    +
    356 virtual bool match(
    +
    357 _In_reads_or_z_(end) const char* text,
    +
    358 _In_ size_t start = 0,
    +
    359 _In_ size_t end = (size_t)-1,
    +
    360 _In_ int flags = match_default)
    +
    361 {
    +
    362 _Assume_(text || start >= end);
    +
    363 if (start < end && text[start]) {
    +
    364 wchar_t buf[3];
    +
    365 const wchar_t* chr = next_sgml_cp(text, start, end, this->interval.end, buf);
    +
    366 bool r = ((flags & match_case_insensitive) ?
    +
    367 stdex::strnicmp(chr, (size_t)-1, m_chr.c_str(), m_chr.size(), m_locale) :
    +
    368 stdex::strncmp(chr, (size_t)-1, m_chr.c_str(), m_chr.size())) == 0;
    +
    369 if ((r && !m_invert) || (!r && m_invert)) {
    +
    370 this->interval.start = start;
    +
    371 return true;
    +
    372 }
    +
    373 }
    +
    374 this->interval.start = (this->interval.end = start) + 1;
    +
    375 return false;
    +
    376 }
    +
    377
    +
    378 protected:
    +
    379 std::wstring m_chr;
    +
    380 bool m_invert;
    +
    381 };
    -
    385
    -
    389 template <class T>
    -
    -
    390 class basic_space_cu : public basic_parser<T>
    -
    391 {
    -
    392 public:
    -
    393 basic_space_cu(bool invert = false, _In_ const std::locale& locale = std::locale()) :
    -
    394 basic_parser<T>(locale),
    -
    395 m_invert(invert)
    -
    396 {}
    -
    397
    -
    398 virtual bool match(
    -
    399 _In_reads_or_z_(end) const T* text,
    -
    400 _In_ size_t start = 0,
    -
    401 _In_ size_t end = (size_t)-1,
    -
    402 _In_ int flags = match_default)
    -
    403 {
    -
    404 _Assume_(text || start >= end);
    -
    405 if (start < end && text[start]) {
    -
    406 bool r =
    -
    407 ((flags & match_multiline) || !islbreak(text[start])) &&
    -
    408 std::use_facet<std::ctype<T>>(this->m_locale).is(std::ctype_base::space, text[start]);
    -
    409 if ((r && !m_invert) || (!r && m_invert)) {
    -
    410 this->interval.end = (this->interval.start = start) + 1;
    -
    411 return true;
    -
    412 }
    -
    413 }
    -
    414 this->interval.start = (this->interval.end = start) + 1;
    -
    415 return false;
    -
    416 }
    -
    417
    -
    418 protected:
    -
    419 bool m_invert;
    -
    420 };
    +
    382
    +
    386 template <class T>
    +
    +
    387 class basic_space_cu : public basic_parser<T>
    +
    388 {
    +
    389 public:
    +
    390 basic_space_cu(bool invert = false, _In_ const std::locale& locale = std::locale()) :
    +
    391 basic_parser<T>(locale),
    +
    392 m_invert(invert)
    +
    393 {}
    +
    394
    +
    395 virtual bool match(
    +
    396 _In_reads_or_z_(end) const T* text,
    +
    397 _In_ size_t start = 0,
    +
    398 _In_ size_t end = (size_t)-1,
    +
    399 _In_ int flags = match_default)
    +
    400 {
    +
    401 _Assume_(text || start >= end);
    +
    402 if (start < end && text[start]) {
    +
    403 bool r =
    +
    404 ((flags & match_multiline) || !islbreak(text[start])) &&
    +
    405 std::use_facet<std::ctype<T>>(this->m_locale).is(std::ctype_base::space, text[start]);
    +
    406 if ((r && !m_invert) || (!r && m_invert)) {
    +
    407 this->interval.end = (this->interval.start = start) + 1;
    +
    408 return true;
    +
    409 }
    +
    410 }
    +
    411 this->interval.start = (this->interval.end = start) + 1;
    +
    412 return false;
    +
    413 }
    +
    414
    +
    415 protected:
    +
    416 bool m_invert;
    +
    417 };
    -
    421
    - - -
    424#ifdef _UNICODE
    -
    425 using tspace_cu = wspace_cu;
    -
    426#else
    -
    427 using tspace_cu = space_cu;
    -
    428#endif
    -
    429
    -
    -
    433 class sgml_space_cp : public basic_space_cu<char>
    -
    434 {
    -
    435 public:
    -
    436 sgml_space_cp(_In_ bool invert = false, _In_ const std::locale& locale = std::locale()) :
    - -
    438 {}
    -
    439
    -
    440 virtual bool match(
    -
    441 _In_reads_or_z_(end) const char* text,
    -
    442 _In_ size_t start = 0,
    -
    443 _In_ size_t end = (size_t)-1,
    -
    444 _In_ int flags = match_default)
    -
    445 {
    -
    446 _Assume_(text || start >= end);
    -
    447 if (start < end && text[start]) {
    -
    448 wchar_t buf[3];
    -
    449 const wchar_t* chr = next_sgml_cp(text, start, end, this->interval.end, buf);
    -
    450 const wchar_t* chr_end = chr + stdex::strlen(chr);
    -
    451 bool r =
    -
    452 ((flags & match_multiline) || !islbreak(chr, (size_t)-1)) &&
    -
    453 std::use_facet<std::ctype<wchar_t>>(m_locale).scan_not(std::ctype_base::space, chr, chr_end) == chr_end;
    -
    454 if ((r && !m_invert) || (!r && m_invert)) {
    -
    455 this->interval.start = start;
    -
    456 return true;
    -
    457 }
    -
    458 }
    -
    459
    -
    460 this->interval.start = (this->interval.end = start) + 1;
    -
    461 return false;
    -
    462 }
    -
    463 };
    +
    418
    + + +
    421#ifdef _UNICODE
    +
    422 using tspace_cu = wspace_cu;
    +
    423#else
    +
    424 using tspace_cu = space_cu;
    +
    425#endif
    +
    426
    +
    +
    430 class sgml_space_cp : public basic_space_cu<char>
    +
    431 {
    +
    432 public:
    +
    433 sgml_space_cp(_In_ bool invert = false, _In_ const std::locale& locale = std::locale()) :
    + +
    435 {}
    +
    436
    +
    437 virtual bool match(
    +
    438 _In_reads_or_z_(end) const char* text,
    +
    439 _In_ size_t start = 0,
    +
    440 _In_ size_t end = (size_t)-1,
    +
    441 _In_ int flags = match_default)
    +
    442 {
    +
    443 _Assume_(text || start >= end);
    +
    444 if (start < end && text[start]) {
    +
    445 wchar_t buf[3];
    +
    446 const wchar_t* chr = next_sgml_cp(text, start, end, this->interval.end, buf);
    +
    447 const wchar_t* chr_end = chr + stdex::strlen(chr);
    +
    448 bool r =
    +
    449 ((flags & match_multiline) || !islbreak(chr, (size_t)-1)) &&
    +
    450 std::use_facet<std::ctype<wchar_t>>(m_locale).scan_not(std::ctype_base::space, chr, chr_end) == chr_end;
    +
    451 if ((r && !m_invert) || (!r && m_invert)) {
    +
    452 this->interval.start = start;
    +
    453 return true;
    +
    454 }
    +
    455 }
    +
    456
    +
    457 this->interval.start = (this->interval.end = start) + 1;
    +
    458 return false;
    +
    459 }
    +
    460 };
    -
    464
    -
    468 template <class T>
    -
    -
    469 class basic_punct_cu : public basic_parser<T>
    -
    470 {
    -
    471 public:
    -
    472 basic_punct_cu(bool invert = false, _In_ const std::locale& locale = std::locale()) :
    -
    473 basic_parser<T>(locale),
    -
    474 m_invert(invert)
    -
    475 {}
    -
    476
    -
    477 virtual bool match(
    -
    478 _In_reads_or_z_(end) const T* text,
    -
    479 _In_ size_t start = 0,
    -
    480 _In_ size_t end = (size_t)-1,
    -
    481 _In_ int flags = match_default)
    -
    482 {
    -
    483 _Assume_(text || start >= end);
    -
    484 if (start < end && text[start]) {
    -
    485 bool r = std::use_facet<std::ctype<T>>(this->m_locale).is(std::ctype_base::punct, text[start]);
    -
    486 if ((r && !m_invert) || (!r && m_invert)) {
    -
    487 this->interval.end = (this->interval.start = start) + 1;
    -
    488 return true;
    -
    489 }
    -
    490 }
    -
    491 this->interval.start = (this->interval.end = start) + 1;
    -
    492 return false;
    -
    493 }
    -
    494
    -
    495 protected:
    -
    496 bool m_invert;
    -
    497 };
    +
    461
    +
    465 template <class T>
    +
    +
    466 class basic_punct_cu : public basic_parser<T>
    +
    467 {
    +
    468 public:
    +
    469 basic_punct_cu(bool invert = false, _In_ const std::locale& locale = std::locale()) :
    +
    470 basic_parser<T>(locale),
    +
    471 m_invert(invert)
    +
    472 {}
    +
    473
    +
    474 virtual bool match(
    +
    475 _In_reads_or_z_(end) const T* text,
    +
    476 _In_ size_t start = 0,
    +
    477 _In_ size_t end = (size_t)-1,
    +
    478 _In_ int flags = match_default)
    +
    479 {
    +
    480 _Assume_(text || start >= end);
    +
    481 if (start < end && text[start]) {
    +
    482 bool r = std::use_facet<std::ctype<T>>(this->m_locale).is(std::ctype_base::punct, text[start]);
    +
    483 if ((r && !m_invert) || (!r && m_invert)) {
    +
    484 this->interval.end = (this->interval.start = start) + 1;
    +
    485 return true;
    +
    486 }
    +
    487 }
    +
    488 this->interval.start = (this->interval.end = start) + 1;
    +
    489 return false;
    +
    490 }
    +
    491
    +
    492 protected:
    +
    493 bool m_invert;
    +
    494 };
    -
    498
    - - -
    501#ifdef _UNICODE
    -
    502 using tpunct_cu = wpunct_cu;
    -
    503#else
    -
    504 using tpunct_cu = punct_cu;
    -
    505#endif
    -
    506
    -
    -
    510 class sgml_punct_cp : public basic_punct_cu<char>
    -
    511 {
    -
    512 public:
    -
    513 sgml_punct_cp(bool invert = false, _In_ const std::locale& locale = std::locale()) :
    - -
    515 {}
    -
    516
    -
    517 virtual bool match(
    -
    518 _In_reads_or_z_(end) const char* text,
    -
    519 _In_ size_t start = 0,
    -
    520 _In_ size_t end = (size_t)-1,
    -
    521 _In_ int flags = match_default)
    -
    522 {
    -
    523 _Assume_(text || start >= end);
    -
    524 if (start < end && text[start]) {
    -
    525 wchar_t buf[3];
    -
    526 const wchar_t* chr = next_sgml_cp(text, start, end, this->interval.end, buf);
    -
    527 const wchar_t* chr_end = chr + stdex::strlen(chr);
    -
    528 bool r = std::use_facet<std::ctype<wchar_t>>(m_locale).scan_not(std::ctype_base::punct, chr, chr_end) == chr_end;
    -
    529 if ((r && !m_invert) || (!r && m_invert)) {
    -
    530 this->interval.start = start;
    -
    531 return true;
    -
    532 }
    -
    533 }
    -
    534 this->interval.start = (this->interval.end = start) + 1;
    -
    535 return false;
    -
    536 }
    -
    537 };
    +
    495
    + + +
    498#ifdef _UNICODE
    +
    499 using tpunct_cu = wpunct_cu;
    +
    500#else
    +
    501 using tpunct_cu = punct_cu;
    +
    502#endif
    +
    503
    +
    +
    507 class sgml_punct_cp : public basic_punct_cu<char>
    +
    508 {
    +
    509 public:
    +
    510 sgml_punct_cp(bool invert = false, _In_ const std::locale& locale = std::locale()) :
    + +
    512 {}
    +
    513
    +
    514 virtual bool match(
    +
    515 _In_reads_or_z_(end) const char* text,
    +
    516 _In_ size_t start = 0,
    +
    517 _In_ size_t end = (size_t)-1,
    +
    518 _In_ int flags = match_default)
    +
    519 {
    +
    520 _Assume_(text || start >= end);
    +
    521 if (start < end && text[start]) {
    +
    522 wchar_t buf[3];
    +
    523 const wchar_t* chr = next_sgml_cp(text, start, end, this->interval.end, buf);
    +
    524 const wchar_t* chr_end = chr + stdex::strlen(chr);
    +
    525 bool r = std::use_facet<std::ctype<wchar_t>>(m_locale).scan_not(std::ctype_base::punct, chr, chr_end) == chr_end;
    +
    526 if ((r && !m_invert) || (!r && m_invert)) {
    +
    527 this->interval.start = start;
    +
    528 return true;
    +
    529 }
    +
    530 }
    +
    531 this->interval.start = (this->interval.end = start) + 1;
    +
    532 return false;
    +
    533 }
    +
    534 };
    -
    538
    -
    542 template <class T>
    -
    - -
    544 {
    -
    545 public:
    -
    546 basic_space_or_punct_cu(bool invert = false, _In_ const std::locale& locale = std::locale()) :
    -
    547 basic_parser<T>(locale),
    -
    548 m_invert(invert)
    -
    549 {}
    -
    550
    -
    551 virtual bool match(
    -
    552 _In_reads_or_z_(end) const T* text,
    -
    553 _In_ size_t start = 0,
    -
    554 _In_ size_t end = (size_t)-1,
    -
    555 _In_ int flags = match_default)
    -
    556 {
    -
    557 _Assume_(text || start >= end);
    -
    558 if (start < end && text[start]) {
    -
    559 bool r =
    -
    560 ((flags & match_multiline) || !islbreak(text[start])) &&
    -
    561 std::use_facet<std::ctype<T>>(this->m_locale).is(std::ctype_base::space | std::ctype_base::punct, text[start]);
    -
    562 if ((r && !m_invert) || (!r && m_invert)) {
    -
    563 this->interval.end = (this->interval.start = start) + 1;
    -
    564 return true;
    -
    565 }
    -
    566 }
    -
    567 this->interval.start = (this->interval.end = start) + 1;
    -
    568 return false;
    -
    569 }
    -
    570
    -
    571 protected:
    -
    572 bool m_invert;
    -
    573 };
    +
    535
    +
    539 template <class T>
    +
    + +
    541 {
    +
    542 public:
    +
    543 basic_space_or_punct_cu(bool invert = false, _In_ const std::locale& locale = std::locale()) :
    +
    544 basic_parser<T>(locale),
    +
    545 m_invert(invert)
    +
    546 {}
    +
    547
    +
    548 virtual bool match(
    +
    549 _In_reads_or_z_(end) const T* text,
    +
    550 _In_ size_t start = 0,
    +
    551 _In_ size_t end = (size_t)-1,
    +
    552 _In_ int flags = match_default)
    +
    553 {
    +
    554 _Assume_(text || start >= end);
    +
    555 if (start < end && text[start]) {
    +
    556 bool r =
    +
    557 ((flags & match_multiline) || !islbreak(text[start])) &&
    +
    558 std::use_facet<std::ctype<T>>(this->m_locale).is(std::ctype_base::space | std::ctype_base::punct, text[start]);
    +
    559 if ((r && !m_invert) || (!r && m_invert)) {
    +
    560 this->interval.end = (this->interval.start = start) + 1;
    +
    561 return true;
    +
    562 }
    +
    563 }
    +
    564 this->interval.start = (this->interval.end = start) + 1;
    +
    565 return false;
    +
    566 }
    +
    567
    +
    568 protected:
    +
    569 bool m_invert;
    +
    570 };
    -
    574
    - - -
    577#ifdef _UNICODE
    - -
    579#else
    - -
    581#endif
    -
    582
    -
    - -
    587 {
    -
    588 public:
    -
    589 sgml_space_or_punct_cp(bool invert = false, _In_ const std::locale& locale = std::locale()) :
    - -
    591 {}
    -
    592
    -
    593 virtual bool match(
    -
    594 _In_reads_or_z_(end) const char* text,
    -
    595 _In_ size_t start = 0,
    -
    596 _In_ size_t end = (size_t)-1,
    -
    597 _In_ int flags = match_default)
    -
    598 {
    -
    599 _Assume_(text || start >= end);
    -
    600 if (start < end && text[start]) {
    -
    601 wchar_t buf[3];
    -
    602 const wchar_t* chr = next_sgml_cp(text, start, end, this->interval.end, buf);
    -
    603 const wchar_t* chr_end = chr + stdex::strlen(chr);
    -
    604 bool r =
    -
    605 ((flags & match_multiline) || !islbreak(chr, (size_t)-1)) &&
    -
    606 std::use_facet<std::ctype<wchar_t>>(m_locale).scan_not(std::ctype_base::space | std::ctype_base::punct, chr, chr_end) == chr_end;
    -
    607 if ((r && !m_invert) || (!r && m_invert)) {
    -
    608 this->interval.start = start;
    -
    609 return true;
    -
    610 }
    -
    611 }
    -
    612 this->interval.start = (this->interval.end = start) + 1;
    -
    613 return false;
    -
    614 }
    -
    615 };
    +
    571
    + + +
    574#ifdef _UNICODE
    + +
    576#else
    + +
    578#endif
    +
    579
    +
    + +
    584 {
    +
    585 public:
    +
    586 sgml_space_or_punct_cp(bool invert = false, _In_ const std::locale& locale = std::locale()) :
    + +
    588 {}
    +
    589
    +
    590 virtual bool match(
    +
    591 _In_reads_or_z_(end) const char* text,
    +
    592 _In_ size_t start = 0,
    +
    593 _In_ size_t end = (size_t)-1,
    +
    594 _In_ int flags = match_default)
    +
    595 {
    +
    596 _Assume_(text || start >= end);
    +
    597 if (start < end && text[start]) {
    +
    598 wchar_t buf[3];
    +
    599 const wchar_t* chr = next_sgml_cp(text, start, end, this->interval.end, buf);
    +
    600 const wchar_t* chr_end = chr + stdex::strlen(chr);
    +
    601 bool r =
    +
    602 ((flags & match_multiline) || !islbreak(chr, (size_t)-1)) &&
    +
    603 std::use_facet<std::ctype<wchar_t>>(m_locale).scan_not(std::ctype_base::space | std::ctype_base::punct, chr, chr_end) == chr_end;
    +
    604 if ((r && !m_invert) || (!r && m_invert)) {
    +
    605 this->interval.start = start;
    +
    606 return true;
    +
    607 }
    +
    608 }
    +
    609 this->interval.start = (this->interval.end = start) + 1;
    +
    610 return false;
    +
    611 }
    +
    612 };
    -
    616
    -
    620 template <class T>
    -
    -
    621 class basic_bol : public basic_parser<T>
    -
    622 {
    -
    623 public:
    -
    624 basic_bol(bool invert = false) : m_invert(invert) {}
    -
    625
    -
    626 virtual bool match(
    -
    627 _In_reads_or_z_(end) const T* text,
    -
    628 _In_ size_t start = 0,
    -
    629 _In_ size_t end = (size_t)-1,
    -
    630 _In_ int flags = match_default)
    -
    631 {
    -
    632 _Assume_(text || start >= end);
    -
    633 bool r = start == 0 || (start <= end && islbreak(text[start - 1]));
    -
    634 if ((r && !m_invert) || (!r && m_invert)) {
    -
    635 this->interval.end = this->interval.start = start;
    -
    636 return true;
    -
    637 }
    -
    638 this->interval.start = (this->interval.end = start) + 1;
    -
    639 return false;
    -
    640 }
    -
    641
    -
    642 protected:
    -
    643 bool m_invert;
    -
    644 };
    +
    613
    +
    617 template <class T>
    +
    +
    618 class basic_bol : public basic_parser<T>
    +
    619 {
    +
    620 public:
    +
    621 basic_bol(bool invert = false) : m_invert(invert) {}
    +
    622
    +
    623 virtual bool match(
    +
    624 _In_reads_or_z_(end) const T* text,
    +
    625 _In_ size_t start = 0,
    +
    626 _In_ size_t end = (size_t)-1,
    +
    627 _In_ int flags = match_default)
    +
    628 {
    +
    629 _Assume_(text || start >= end);
    +
    630 bool r = start == 0 || (start <= end && islbreak(text[start - 1]));
    +
    631 if ((r && !m_invert) || (!r && m_invert)) {
    +
    632 this->interval.end = this->interval.start = start;
    +
    633 return true;
    +
    634 }
    +
    635 this->interval.start = (this->interval.end = start) + 1;
    +
    636 return false;
    +
    637 }
    +
    638
    +
    639 protected:
    +
    640 bool m_invert;
    +
    641 };
    -
    645
    -
    646 using bol = basic_bol<char>;
    -
    647 using wbol = basic_bol<wchar_t>;
    -
    648#ifdef _UNICODE
    -
    649 using tbol = wbol;
    -
    650#else
    -
    651 using tbol = bol;
    -
    652#endif
    - -
    654
    -
    658 template <class T>
    -
    -
    659 class basic_eol : public basic_parser<T>
    -
    660 {
    -
    661 public:
    -
    662 basic_eol(bool invert = false) : m_invert(invert) {}
    -
    663
    -
    664 virtual bool match(
    -
    665 _In_reads_or_z_(end) const T* text,
    -
    666 _In_ size_t start = 0,
    -
    667 _In_ size_t end = (size_t)-1,
    -
    668 _In_ int flags = match_default)
    -
    669 {
    -
    670 _Assume_(text || start >= end);
    -
    671 bool r = islbreak(text[start]);
    -
    672 if ((r && !m_invert) || (!r && m_invert)) {
    -
    673 this->interval.end = this->interval.start = start;
    -
    674 return true;
    -
    675 }
    -
    676 this->interval.start = (this->interval.end = start) + 1;
    -
    677 return false;
    -
    678 }
    -
    679
    -
    680 protected:
    -
    681 bool m_invert;
    -
    682 };
    +
    642
    +
    643 using bol = basic_bol<char>;
    +
    644 using wbol = basic_bol<wchar_t>;
    +
    645#ifdef _UNICODE
    +
    646 using tbol = wbol;
    +
    647#else
    +
    648 using tbol = bol;
    +
    649#endif
    + +
    651
    +
    655 template <class T>
    +
    +
    656 class basic_eol : public basic_parser<T>
    +
    657 {
    +
    658 public:
    +
    659 basic_eol(bool invert = false) : m_invert(invert) {}
    +
    660
    +
    661 virtual bool match(
    +
    662 _In_reads_or_z_(end) const T* text,
    +
    663 _In_ size_t start = 0,
    +
    664 _In_ size_t end = (size_t)-1,
    +
    665 _In_ int flags = match_default)
    +
    666 {
    +
    667 _Assume_(text || start >= end);
    +
    668 bool r = islbreak(text[start]);
    +
    669 if ((r && !m_invert) || (!r && m_invert)) {
    +
    670 this->interval.end = this->interval.start = start;
    +
    671 return true;
    +
    672 }
    +
    673 this->interval.start = (this->interval.end = start) + 1;
    +
    674 return false;
    +
    675 }
    +
    676
    +
    677 protected:
    +
    678 bool m_invert;
    +
    679 };
    -
    683
    -
    684 using eol = basic_eol<char>;
    -
    685 using weol = basic_eol<wchar_t>;
    -
    686#ifdef _UNICODE
    -
    687 using teol = weol;
    -
    688#else
    -
    689 using teol = eol;
    -
    690#endif
    - -
    692
    -
    693 template <class T>
    -
    -
    694 class basic_set : public basic_parser<T>
    -
    695 {
    -
    696 public:
    -
    697 basic_set(bool invert = false, _In_ const std::locale& locale = std::locale()) :
    -
    698 basic_parser<T>(locale),
    -
    699 hit_offset((size_t)-1),
    -
    700 m_invert(invert)
    -
    701 {}
    -
    702
    -
    703 virtual bool match(
    -
    704 _In_reads_or_z_(end) const T* text,
    -
    705 _In_ size_t start = 0,
    -
    706 _In_ size_t end = (size_t)-1,
    -
    707 _In_ int flags = match_default) = 0;
    -
    708
    -
    709 virtual void invalidate()
    -
    710 {
    -
    711 hit_offset = (size_t)-1;
    - -
    713 }
    +
    680
    +
    681 using eol = basic_eol<char>;
    +
    682 using weol = basic_eol<wchar_t>;
    +
    683#ifdef _UNICODE
    +
    684 using teol = weol;
    +
    685#else
    +
    686 using teol = eol;
    +
    687#endif
    + +
    689
    +
    690 template <class T>
    +
    +
    691 class basic_set : public basic_parser<T>
    +
    692 {
    +
    693 public:
    +
    694 basic_set(bool invert = false, _In_ const std::locale& locale = std::locale()) :
    +
    695 basic_parser<T>(locale),
    +
    696 hit_offset((size_t)-1),
    +
    697 m_invert(invert)
    +
    698 {}
    +
    699
    +
    700 virtual bool match(
    +
    701 _In_reads_or_z_(end) const T* text,
    +
    702 _In_ size_t start = 0,
    +
    703 _In_ size_t end = (size_t)-1,
    +
    704 _In_ int flags = match_default) = 0;
    +
    705
    +
    706 virtual void invalidate()
    +
    707 {
    +
    708 hit_offset = (size_t)-1;
    + +
    710 }
    +
    711
    +
    712 public:
    +
    713 size_t hit_offset;
    714
    -
    715 public:
    -
    716 size_t hit_offset;
    -
    717
    -
    718 protected:
    -
    719 bool m_invert;
    -
    720 };
    +
    715 protected:
    +
    716 bool m_invert;
    +
    717 };
    -
    721
    -
    725 template <class T>
    -
    -
    726 class basic_cu_set : public basic_set<T>
    -
    727 {
    -
    728 public:
    - -
    730 _In_reads_or_z_(count) const T* set,
    -
    731 _In_ size_t count = (size_t)-1,
    -
    732 _In_ bool invert = false,
    -
    733 _In_ const std::locale& locale = std::locale()) :
    -
    734 basic_set<T>(invert, locale)
    -
    735 {
    -
    736 if (set)
    -
    737 m_set.assign(set, set + stdex::strnlen(set, count));
    -
    738 }
    -
    739
    -
    740 virtual bool match(
    -
    741 _In_reads_or_z_(end) const T* text,
    -
    742 _In_ size_t start = 0,
    -
    743 _In_ size_t end = (size_t)-1,
    -
    744 _In_ int flags = match_default)
    -
    745 {
    -
    746 _Assume_(text || start >= end);
    -
    747 if (start < end && text[start]) {
    -
    748 const T* set = m_set.c_str();
    -
    749 size_t r = (flags & match_case_insensitive) ?
    -
    750 stdex::strnichr(set, m_set.size(), text[start], this->m_locale) :
    -
    751 stdex::strnchr(set, m_set.size(), text[start]);
    -
    752 if ((r != stdex::npos && !this->m_invert) || (r == stdex::npos && this->m_invert)) {
    -
    753 this->hit_offset = r;
    -
    754 this->interval.end = (this->interval.start = start) + 1;
    -
    755 return true;
    -
    756 }
    -
    757 }
    -
    758 this->hit_offset = (size_t)-1;
    -
    759 this->interval.start = (this->interval.end = start) + 1;
    -
    760 return false;
    -
    761 }
    -
    762
    -
    763 protected:
    -
    764 std::basic_string<T> m_set;
    -
    765 };
    +
    718
    +
    722 template <class T>
    +
    +
    723 class basic_cu_set : public basic_set<T>
    +
    724 {
    +
    725 public:
    + +
    727 _In_reads_or_z_(count) const T* set,
    +
    728 _In_ size_t count = (size_t)-1,
    +
    729 _In_ bool invert = false,
    +
    730 _In_ const std::locale& locale = std::locale()) :
    +
    731 basic_set<T>(invert, locale)
    +
    732 {
    +
    733 if (set)
    +
    734 m_set.assign(set, set + stdex::strnlen(set, count));
    +
    735 }
    +
    736
    +
    737 virtual bool match(
    +
    738 _In_reads_or_z_(end) const T* text,
    +
    739 _In_ size_t start = 0,
    +
    740 _In_ size_t end = (size_t)-1,
    +
    741 _In_ int flags = match_default)
    +
    742 {
    +
    743 _Assume_(text || start >= end);
    +
    744 if (start < end && text[start]) {
    +
    745 const T* set = m_set.c_str();
    +
    746 size_t r = (flags & match_case_insensitive) ?
    +
    747 stdex::strnichr(set, m_set.size(), text[start], this->m_locale) :
    +
    748 stdex::strnchr(set, m_set.size(), text[start]);
    +
    749 if ((r != stdex::npos && !this->m_invert) || (r == stdex::npos && this->m_invert)) {
    +
    750 this->hit_offset = r;
    +
    751 this->interval.end = (this->interval.start = start) + 1;
    +
    752 return true;
    +
    753 }
    +
    754 }
    +
    755 this->hit_offset = (size_t)-1;
    +
    756 this->interval.start = (this->interval.end = start) + 1;
    +
    757 return false;
    +
    758 }
    +
    759
    +
    760 protected:
    +
    761 std::basic_string<T> m_set;
    +
    762 };
    -
    766
    - - -
    769#ifdef _UNICODE
    -
    770 using tcu_set = wcu_set;
    -
    771#else
    -
    772 using tcu_set = cu_set;
    -
    773#endif
    -
    774
    -
    -
    778 class sgml_cp_set : public basic_set<char>
    -
    779 {
    -
    780 public:
    -
    781 sgml_cp_set(const char* set, size_t count = (size_t)-1, bool invert = false, _In_ const std::locale& locale = std::locale()) :
    -
    782 basic_set<char>(invert, locale)
    -
    783 {
    -
    784 if (set)
    -
    785 m_set = sgml2wstr(set, count);
    -
    786 }
    -
    787
    -
    788 virtual bool match(
    -
    789 _In_reads_or_z_(end) const char* text,
    -
    790 _In_ size_t start = 0,
    -
    791 _In_ size_t end = (size_t)-1,
    -
    792 _In_ int flags = match_default)
    -
    793 {
    -
    794 _Assume_(text || start >= end);
    -
    795 if (start < end && text[start]) {
    -
    796 wchar_t buf[3];
    -
    797 const wchar_t* chr = next_sgml_cp(text, start, end, this->interval.end, buf);
    -
    798 const wchar_t* set = m_set.c_str();
    -
    799 size_t r = (flags & match_case_insensitive) ?
    -
    800 stdex::strnistr(set, m_set.size(), chr, m_locale) :
    -
    801 stdex::strnstr(set, m_set.size(), chr);
    -
    802 if ((r != stdex::npos && !m_invert) || (r == stdex::npos && m_invert)) {
    -
    803 hit_offset = r;
    -
    804 this->interval.start = start;
    -
    805 return true;
    -
    806 }
    -
    807 }
    -
    808 hit_offset = (size_t)-1;
    -
    809 this->interval.start = (this->interval.end = start) + 1;
    -
    810 return false;
    -
    811 }
    -
    812
    -
    813 protected:
    -
    814 std::wstring m_set;
    -
    815 };
    +
    763
    + + +
    766#ifdef _UNICODE
    +
    767 using tcu_set = wcu_set;
    +
    768#else
    +
    769 using tcu_set = cu_set;
    +
    770#endif
    +
    771
    +
    +
    775 class sgml_cp_set : public basic_set<char>
    +
    776 {
    +
    777 public:
    +
    778 sgml_cp_set(const char* set, size_t count = (size_t)-1, bool invert = false, _In_ const std::locale& locale = std::locale()) :
    +
    779 basic_set<char>(invert, locale)
    +
    780 {
    +
    781 if (set)
    +
    782 m_set = sgml2wstr(set, count);
    +
    783 }
    +
    784
    +
    785 virtual bool match(
    +
    786 _In_reads_or_z_(end) const char* text,
    +
    787 _In_ size_t start = 0,
    +
    788 _In_ size_t end = (size_t)-1,
    +
    789 _In_ int flags = match_default)
    +
    790 {
    +
    791 _Assume_(text || start >= end);
    +
    792 if (start < end && text[start]) {
    +
    793 wchar_t buf[3];
    +
    794 const wchar_t* chr = next_sgml_cp(text, start, end, this->interval.end, buf);
    +
    795 const wchar_t* set = m_set.c_str();
    +
    796 size_t r = (flags & match_case_insensitive) ?
    +
    797 stdex::strnistr(set, m_set.size(), chr, m_locale) :
    +
    798 stdex::strnstr(set, m_set.size(), chr);
    +
    799 if ((r != stdex::npos && !m_invert) || (r == stdex::npos && m_invert)) {
    +
    800 hit_offset = r;
    +
    801 this->interval.start = start;
    +
    802 return true;
    +
    803 }
    +
    804 }
    +
    805 hit_offset = (size_t)-1;
    +
    806 this->interval.start = (this->interval.end = start) + 1;
    +
    807 return false;
    +
    808 }
    +
    809
    +
    810 protected:
    +
    811 std::wstring m_set;
    +
    812 };
    -
    816
    -
    820 template <class T>
    -
    -
    821 class basic_string : public basic_parser<T>
    -
    822 {
    -
    823 public:
    - -
    825 _In_reads_or_z_(count) const T* str,
    -
    826 _In_ size_t count = (size_t)-1,
    -
    827 _In_ const std::locale& locale = std::locale()) :
    -
    828 basic_parser<T>(locale),
    -
    829 m_str(str, str + stdex::strnlen(str, count))
    -
    830 {}
    -
    831
    -
    832 virtual bool match(
    -
    833 _In_reads_or_z_(end) const T* text,
    -
    834 _In_ size_t start = 0,
    -
    835 _In_ size_t end = (size_t)-1,
    -
    836 _In_ int flags = match_default)
    -
    837 {
    -
    838 _Assume_(text || start >= end);
    -
    839 size_t
    -
    840 m = m_str.size(),
    -
    841 n = std::min<size_t>(end - start, m);
    -
    842 bool r = ((flags & match_case_insensitive) ?
    -
    843 stdex::strnicmp(text + start, n, m_str.c_str(), m, this->m_locale) :
    -
    844 stdex::strncmp(text + start, n, m_str.c_str(), m)) == 0;
    -
    845 if (r) {
    -
    846 this->interval.end = (this->interval.start = start) + n;
    -
    847 return true;
    -
    848 }
    -
    849 this->interval.start = (this->interval.end = start) + 1;
    -
    850 return false;
    -
    851 }
    -
    852
    -
    853 protected:
    -
    854 std::basic_string<T> m_str;
    -
    855 };
    +
    813
    +
    817 template <class T>
    +
    +
    818 class basic_string : public basic_parser<T>
    +
    819 {
    +
    820 public:
    + +
    822 _In_reads_or_z_(count) const T* str,
    +
    823 _In_ size_t count = (size_t)-1,
    +
    824 _In_ const std::locale& locale = std::locale()) :
    +
    825 basic_parser<T>(locale),
    +
    826 m_str(str, str + stdex::strnlen(str, count))
    +
    827 {}
    +
    828
    +
    829 virtual bool match(
    +
    830 _In_reads_or_z_(end) const T* text,
    +
    831 _In_ size_t start = 0,
    +
    832 _In_ size_t end = (size_t)-1,
    +
    833 _In_ int flags = match_default)
    +
    834 {
    +
    835 _Assume_(text || start >= end);
    +
    836 size_t
    +
    837 m = m_str.size(),
    +
    838 n = std::min<size_t>(end - start, m);
    +
    839 bool r = ((flags & match_case_insensitive) ?
    +
    840 stdex::strnicmp(text + start, n, m_str.c_str(), m, this->m_locale) :
    +
    841 stdex::strncmp(text + start, n, m_str.c_str(), m)) == 0;
    +
    842 if (r) {
    +
    843 this->interval.end = (this->interval.start = start) + n;
    +
    844 return true;
    +
    845 }
    +
    846 this->interval.start = (this->interval.end = start) + 1;
    +
    847 return false;
    +
    848 }
    +
    849
    +
    850 protected:
    +
    851 std::basic_string<T> m_str;
    +
    852 };
    -
    856
    - - -
    859#ifdef _UNICODE
    -
    860 using tstring = wstring;
    -
    861#else
    -
    862 using tstring = string;
    -
    863#endif
    -
    864
    -
    - -
    869 {
    -
    870 public:
    -
    871 sgml_string(const char* str, size_t count = (size_t)-1, _In_ const std::locale& locale = std::locale()) :
    -
    872 sgml_parser(locale),
    -
    873 m_str(sgml2wstr(str, count))
    -
    874 {}
    -
    875
    -
    876 virtual bool match(
    -
    877 _In_reads_or_z_(end) const char* text,
    -
    878 _In_ size_t start = 0,
    -
    879 _In_ size_t end = (size_t)-1,
    -
    880 _In_ int flags = match_default)
    -
    881 {
    -
    882 _Assume_(text || start >= end);
    -
    883 const wchar_t* str = m_str.c_str();
    -
    884 const bool case_insensitive = flags & match_case_insensitive ? true : false;
    -
    885 const auto& ctype = std::use_facet<std::ctype<wchar_t>>(m_locale);
    -
    886 for (this->interval.end = start;;) {
    -
    887 if (!*str) {
    -
    888 this->interval.start = start;
    -
    889 return true;
    -
    890 }
    -
    891 if (this->interval.end >= end || !text[this->interval.end]) {
    -
    892 this->interval.start = (this->interval.end = start) + 1;
    -
    893 return false;
    -
    894 }
    -
    895 wchar_t buf[3];
    -
    896 const wchar_t* chr = next_sgml_cp(text, this->interval.end, end, this->interval.end, buf);
    -
    897 for (; *chr; ++str, ++chr) {
    -
    898 if (!*str ||
    -
    899 (case_insensitive ? ctype.tolower(*str) != ctype.tolower(*chr) : *str != *chr))
    -
    900 {
    -
    901 this->interval.start = (this->interval.end = start) + 1;
    -
    902 return false;
    -
    903 }
    -
    904 }
    -
    905 }
    -
    906 }
    -
    907
    -
    908 protected:
    -
    909 std::wstring m_str;
    -
    910 };
    +
    853
    + + +
    856#ifdef _UNICODE
    +
    857 using tstring = wstring;
    +
    858#else
    +
    859 using tstring = string;
    +
    860#endif
    +
    861
    +
    + +
    866 {
    +
    867 public:
    +
    868 sgml_string(const char* str, size_t count = (size_t)-1, _In_ const std::locale& locale = std::locale()) :
    +
    869 sgml_parser(locale),
    +
    870 m_str(sgml2wstr(str, count))
    +
    871 {}
    +
    872
    +
    873 virtual bool match(
    +
    874 _In_reads_or_z_(end) const char* text,
    +
    875 _In_ size_t start = 0,
    +
    876 _In_ size_t end = (size_t)-1,
    +
    877 _In_ int flags = match_default)
    +
    878 {
    +
    879 _Assume_(text || start >= end);
    +
    880 const wchar_t* str = m_str.c_str();
    +
    881 const bool case_insensitive = flags & match_case_insensitive ? true : false;
    +
    882 const auto& ctype = std::use_facet<std::ctype<wchar_t>>(m_locale);
    +
    883 for (this->interval.end = start;;) {
    +
    884 if (!*str) {
    +
    885 this->interval.start = start;
    +
    886 return true;
    +
    887 }
    +
    888 if (this->interval.end >= end || !text[this->interval.end]) {
    +
    889 this->interval.start = (this->interval.end = start) + 1;
    +
    890 return false;
    +
    891 }
    +
    892 wchar_t buf[3];
    +
    893 const wchar_t* chr = next_sgml_cp(text, this->interval.end, end, this->interval.end, buf);
    +
    894 for (; *chr; ++str, ++chr) {
    +
    895 if (!*str ||
    +
    896 (case_insensitive ? ctype.tolower(*str) != ctype.tolower(*chr) : *str != *chr))
    +
    897 {
    +
    898 this->interval.start = (this->interval.end = start) + 1;
    +
    899 return false;
    +
    900 }
    +
    901 }
    +
    902 }
    +
    903 }
    +
    904
    +
    905 protected:
    +
    906 std::wstring m_str;
    +
    907 };
    -
    911
    -
    915 template <class T>
    -
    - -
    917 {
    -
    918 public:
    -
    919 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) :
    -
    920 m_el(el),
    - - - -
    924 {}
    -
    925
    -
    926 virtual bool match(
    -
    927 _In_reads_or_z_(end) const T* text,
    -
    928 _In_ size_t start = 0,
    -
    929 _In_ size_t end = (size_t)-1,
    -
    930 _In_ int flags = match_default)
    -
    931 {
    -
    932 _Assume_(text || start >= end);
    -
    933 this->interval.start = this->interval.end = start;
    -
    934 for (size_t i = 0; ; i++) {
    -
    935 if ((!m_greedy && i >= m_min_iterations) || i >= m_max_iterations)
    -
    936 return true;
    -
    937 if (!m_el->match(text, this->interval.end, end, flags)) {
    -
    938 if (i >= m_min_iterations)
    -
    939 return true;
    -
    940 break;
    -
    941 }
    -
    942 if (m_el->interval.end == this->interval.end) {
    -
    943 // Element did match, but the matching interval was empty. Quit instead of spinning.
    -
    944 return true;
    -
    945 }
    -
    946 this->interval.end = m_el->interval.end;
    -
    947 }
    -
    948 this->interval.start = (this->interval.end = start) + 1;
    -
    949 return false;
    -
    950 }
    -
    951
    -
    952 protected:
    -
    953 std::shared_ptr<basic_parser<T>> m_el;
    - - -
    956 bool m_greedy;
    -
    957 };
    +
    908
    +
    912 template <class T>
    +
    + +
    914 {
    +
    915 public:
    +
    916 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) :
    +
    917 m_el(el),
    + + + +
    921 {}
    +
    922
    +
    923 virtual bool match(
    +
    924 _In_reads_or_z_(end) const T* text,
    +
    925 _In_ size_t start = 0,
    +
    926 _In_ size_t end = (size_t)-1,
    +
    927 _In_ int flags = match_default)
    +
    928 {
    +
    929 _Assume_(text || start >= end);
    +
    930 this->interval.start = this->interval.end = start;
    +
    931 for (size_t i = 0; ; i++) {
    +
    932 if ((!m_greedy && i >= m_min_iterations) || i >= m_max_iterations)
    +
    933 return true;
    +
    934 if (!m_el->match(text, this->interval.end, end, flags)) {
    +
    935 if (i >= m_min_iterations)
    +
    936 return true;
    +
    937 break;
    +
    938 }
    +
    939 if (m_el->interval.end == this->interval.end) {
    +
    940 // Element did match, but the matching interval was empty. Quit instead of spinning.
    +
    941 return true;
    +
    942 }
    +
    943 this->interval.end = m_el->interval.end;
    +
    944 }
    +
    945 this->interval.start = (this->interval.end = start) + 1;
    +
    946 return false;
    +
    947 }
    +
    948
    +
    949 protected:
    +
    950 std::shared_ptr<basic_parser<T>> m_el;
    + + +
    953 bool m_greedy;
    +
    954 };
    -
    958
    - - -
    961#ifdef _UNICODE
    -
    962 using titerations = witerations;
    -
    963#else
    -
    964 using titerations = iterations;
    -
    965#endif
    - -
    967
    -
    971 template <class T>
    -
    - -
    973 {
    -
    974 protected:
    -
    975 parser_collection(_In_ const std::locale& locale) : basic_parser<T>(locale) {}
    -
    976
    -
    977 public:
    - -
    979 _In_count_(count) const std::shared_ptr<basic_parser<T>>* el,
    -
    980 _In_ size_t count,
    -
    981 _In_ const std::locale& locale = std::locale()) :
    -
    982 basic_parser<T>(locale)
    -
    983 {
    -
    984 _Assume_(el || !count);
    -
    985 m_collection.reserve(count);
    -
    986 for (size_t i = 0; i < count; i++)
    -
    987 m_collection.push_back(el[i]);
    -
    988 }
    -
    989
    - -
    991 _Inout_ std::vector<std::shared_ptr<basic_parser<T>>>&& collection,
    -
    992 _In_ const std::locale& locale = std::locale()) :
    -
    993 basic_parser<T>(locale),
    -
    994 m_collection(std::move(collection))
    -
    995 {}
    -
    996
    -
    997 virtual void invalidate()
    -
    998 {
    -
    999 for (auto& el: m_collection)
    -
    1000 el->invalidate();
    - -
    1002 }
    -
    1003
    -
    1004 protected:
    -
    1005 std::vector<std::shared_ptr<basic_parser<T>>> m_collection;
    -
    1006 };
    +
    955
    + + +
    958#ifdef _UNICODE
    +
    959 using titerations = witerations;
    +
    960#else
    +
    961 using titerations = iterations;
    +
    962#endif
    + +
    964
    +
    968 template <class T>
    +
    + +
    970 {
    +
    971 protected:
    +
    972 parser_collection(_In_ const std::locale& locale) : basic_parser<T>(locale) {}
    +
    973
    +
    974 public:
    + +
    976 _In_count_(count) const std::shared_ptr<basic_parser<T>>* el,
    +
    977 _In_ size_t count,
    +
    978 _In_ const std::locale& locale = std::locale()) :
    +
    979 basic_parser<T>(locale)
    +
    980 {
    +
    981 _Assume_(el || !count);
    +
    982 m_collection.reserve(count);
    +
    983 for (size_t i = 0; i < count; i++)
    +
    984 m_collection.push_back(el[i]);
    +
    985 }
    +
    986
    + +
    988 _Inout_ std::vector<std::shared_ptr<basic_parser<T>>>&& collection,
    +
    989 _In_ const std::locale& locale = std::locale()) :
    +
    990 basic_parser<T>(locale),
    +
    991 m_collection(std::move(collection))
    +
    992 {}
    +
    993
    +
    994 virtual void invalidate()
    +
    995 {
    +
    996 for (auto& el: m_collection)
    +
    997 el->invalidate();
    + +
    999 }
    +
    1000
    +
    1001 protected:
    +
    1002 std::vector<std::shared_ptr<basic_parser<T>>> m_collection;
    +
    1003 };
    -
    1007
    -
    1011 template <class T>
    -
    - -
    1013 {
    -
    1014 public:
    - -
    1016 _In_count_(count) const std::shared_ptr<basic_parser<T>>* el = nullptr,
    -
    1017 _In_ size_t count = 0,
    -
    1018 _In_ const std::locale& locale = std::locale()) :
    -
    1019 parser_collection<T>(el, count, locale)
    -
    1020 {}
    -
    1021
    - -
    1023 _Inout_ std::vector<std::shared_ptr<basic_parser<T>>>&& collection,
    -
    1024 _In_ const std::locale& locale = std::locale()) :
    -
    1025 parser_collection<T>(std::move(collection), locale)
    -
    1026 {}
    -
    1027
    -
    1028 virtual bool match(
    -
    1029 _In_reads_or_z_(end) const T* text,
    -
    1030 _In_ size_t start = 0,
    -
    1031 _In_ size_t end = (size_t)-1,
    -
    1032 _In_ int flags = match_default)
    -
    1033 {
    -
    1034 _Assume_(text || start >= end);
    -
    1035 this->interval.end = start;
    -
    1036 for (auto i = this->m_collection.begin(); i != this->m_collection.end(); ++i) {
    -
    1037 if (!(*i)->match(text, this->interval.end, end, flags)) {
    -
    1038 for (++i; i != this->m_collection.end(); ++i)
    -
    1039 (*i)->invalidate();
    -
    1040 this->interval.start = (this->interval.end = start) + 1;
    -
    1041 return false;
    -
    1042 }
    -
    1043 this->interval.end = (*i)->interval.end;
    -
    1044 }
    -
    1045 this->interval.start = start;
    -
    1046 return true;
    -
    1047 }
    -
    1048 };
    +
    1004
    +
    1008 template <class T>
    +
    + +
    1010 {
    +
    1011 public:
    + +
    1013 _In_count_(count) const std::shared_ptr<basic_parser<T>>* el = nullptr,
    +
    1014 _In_ size_t count = 0,
    +
    1015 _In_ const std::locale& locale = std::locale()) :
    +
    1016 parser_collection<T>(el, count, locale)
    +
    1017 {}
    +
    1018
    + +
    1020 _Inout_ std::vector<std::shared_ptr<basic_parser<T>>>&& collection,
    +
    1021 _In_ const std::locale& locale = std::locale()) :
    +
    1022 parser_collection<T>(std::move(collection), locale)
    +
    1023 {}
    +
    1024
    +
    1025 virtual bool match(
    +
    1026 _In_reads_or_z_(end) const T* text,
    +
    1027 _In_ size_t start = 0,
    +
    1028 _In_ size_t end = (size_t)-1,
    +
    1029 _In_ int flags = match_default)
    +
    1030 {
    +
    1031 _Assume_(text || start >= end);
    +
    1032 this->interval.end = start;
    +
    1033 for (auto i = this->m_collection.begin(); i != this->m_collection.end(); ++i) {
    +
    1034 if (!(*i)->match(text, this->interval.end, end, flags)) {
    +
    1035 for (++i; i != this->m_collection.end(); ++i)
    +
    1036 (*i)->invalidate();
    +
    1037 this->interval.start = (this->interval.end = start) + 1;
    +
    1038 return false;
    +
    1039 }
    +
    1040 this->interval.end = (*i)->interval.end;
    +
    1041 }
    +
    1042 this->interval.start = start;
    +
    1043 return true;
    +
    1044 }
    +
    1045 };
    -
    1049
    - - -
    1052#ifdef _UNICODE
    -
    1053 using tsequence = wsequence;
    -
    1054#else
    -
    1055 using tsequence = sequence;
    -
    1056#endif
    - -
    1058
    -
    1062 template <class T>
    -
    - -
    1064 {
    -
    1065 protected:
    -
    1066 basic_branch(_In_ const std::locale& locale) :
    -
    1067 parser_collection<T>(locale),
    -
    1068 hit_offset((size_t)-1)
    -
    1069 {}
    -
    1070
    -
    1071 public:
    - -
    1073 _In_count_(count) const std::shared_ptr<basic_parser<T>>* el = nullptr,
    -
    1074 _In_ size_t count = 0,
    -
    1075 _In_ const std::locale& locale = std::locale()) :
    -
    1076 parser_collection<T>(el, count, locale),
    -
    1077 hit_offset((size_t)-1)
    -
    1078 {}
    -
    1079
    - -
    1081 _Inout_ std::vector<std::shared_ptr<basic_parser<T>>>&& collection,
    -
    1082 _In_ const std::locale& locale = std::locale()) :
    -
    1083 parser_collection<T>(std::move(collection), locale),
    -
    1084 hit_offset((size_t)-1)
    -
    1085 {}
    -
    1086
    -
    1087 virtual bool match(
    -
    1088 _In_reads_or_z_(end) const T* text,
    -
    1089 _In_ size_t start = 0,
    -
    1090 _In_ size_t end = (size_t)-1,
    -
    1091 _In_ int flags = match_default)
    -
    1092 {
    -
    1093 _Assume_(text || start >= end);
    -
    1094 hit_offset = 0;
    -
    1095 for (auto i = this->m_collection.begin(); i != this->m_collection.end(); ++i, ++hit_offset) {
    -
    1096 if ((*i)->match(text, start, end, flags)) {
    -
    1097 this->interval = (*i)->interval;
    -
    1098 for (++i; i != this->m_collection.end(); ++i)
    -
    1099 (*i)->invalidate();
    -
    1100 return true;
    -
    1101 }
    -
    1102 }
    -
    1103 hit_offset = (size_t)-1;
    -
    1104 this->interval.start = (this->interval.end = start) + 1;
    -
    1105 return false;
    -
    1106 }
    -
    1107
    -
    1108 virtual void invalidate()
    -
    1109 {
    -
    1110 hit_offset = (size_t)-1;
    - -
    1112 }
    -
    1113
    -
    1114 public:
    -
    1115 size_t hit_offset;
    -
    1116 };
    +
    1046
    + + +
    1049#ifdef _UNICODE
    +
    1050 using tsequence = wsequence;
    +
    1051#else
    +
    1052 using tsequence = sequence;
    +
    1053#endif
    + +
    1055
    +
    1059 template <class T>
    +
    + +
    1061 {
    +
    1062 protected:
    +
    1063 basic_branch(_In_ const std::locale& locale) :
    +
    1064 parser_collection<T>(locale),
    +
    1065 hit_offset((size_t)-1)
    +
    1066 {}
    +
    1067
    +
    1068 public:
    + +
    1070 _In_count_(count) const std::shared_ptr<basic_parser<T>>* el = nullptr,
    +
    1071 _In_ size_t count = 0,
    +
    1072 _In_ const std::locale& locale = std::locale()) :
    +
    1073 parser_collection<T>(el, count, locale),
    +
    1074 hit_offset((size_t)-1)
    +
    1075 {}
    +
    1076
    + +
    1078 _Inout_ std::vector<std::shared_ptr<basic_parser<T>>>&& collection,
    +
    1079 _In_ const std::locale& locale = std::locale()) :
    +
    1080 parser_collection<T>(std::move(collection), locale),
    +
    1081 hit_offset((size_t)-1)
    +
    1082 {}
    +
    1083
    +
    1084 virtual bool match(
    +
    1085 _In_reads_or_z_(end) const T* text,
    +
    1086 _In_ size_t start = 0,
    +
    1087 _In_ size_t end = (size_t)-1,
    +
    1088 _In_ int flags = match_default)
    +
    1089 {
    +
    1090 _Assume_(text || start >= end);
    +
    1091 hit_offset = 0;
    +
    1092 for (auto i = this->m_collection.begin(); i != this->m_collection.end(); ++i, ++hit_offset) {
    +
    1093 if ((*i)->match(text, start, end, flags)) {
    +
    1094 this->interval = (*i)->interval;
    +
    1095 for (++i; i != this->m_collection.end(); ++i)
    +
    1096 (*i)->invalidate();
    +
    1097 return true;
    +
    1098 }
    +
    1099 }
    +
    1100 hit_offset = (size_t)-1;
    +
    1101 this->interval.start = (this->interval.end = start) + 1;
    +
    1102 return false;
    +
    1103 }
    +
    1104
    +
    1105 virtual void invalidate()
    +
    1106 {
    +
    1107 hit_offset = (size_t)-1;
    + +
    1109 }
    +
    1110
    +
    1111 public:
    +
    1112 size_t hit_offset;
    +
    1113 };
    -
    1117
    -
    1118 using branch = basic_branch<char>;
    - -
    1120#ifdef _UNICODE
    -
    1121 using tbranch = wbranch;
    -
    1122#else
    -
    1123 using tbranch = branch;
    -
    1124#endif
    - -
    1126
    -
    1130 template <class T, class T_parser = basic_string<T>>
    -
    - -
    1132 {
    -
    1133 public:
    -
    1134 inline basic_string_branch(
    -
    1135 _In_reads_(count) const T* str_z = nullptr,
    -
    1136 _In_ size_t count = 0,
    -
    1137 _In_ const std::locale& locale = std::locale()) :
    -
    1138 basic_branch<T>(locale)
    -
    1139 {
    -
    1140 build(str_z, count);
    -
    1141 }
    -
    1142
    -
    1143 inline basic_string_branch(_In_z_ const T* str, ...) :
    -
    1144 basic_branch<T>(std::locale())
    -
    1145 {
    -
    1146 va_list params;
    -
    1147 va_start(params, str);
    -
    1148 build(str, params);
    -
    1149 va_end(params);
    -
    1150 }
    -
    1151
    -
    1152 inline basic_string_branch(_In_ const std::locale& locale, _In_z_ const T* str, ...) :
    -
    1153 basic_branch<T>(locale)
    -
    1154 {
    -
    1155 va_list params;
    -
    1156 va_start(params, str);
    -
    1157 build(str, params);
    -
    1158 va_end(params);
    -
    1159 }
    -
    1160
    -
    1161 protected:
    -
    1162 void build(_In_reads_(count) const T* str_z, _In_ size_t count)
    -
    1163 {
    -
    1164 _Assume_(str_z || !count);
    -
    1165 if (count) {
    -
    1166 size_t offset, n;
    -
    1167 for (
    -
    1168 offset = n = 0;
    -
    1169 offset < count && str_z[offset];
    -
    1170 offset += stdex::strnlen(str_z + offset, count - offset) + 1, ++n);
    -
    1171 this->m_collection.reserve(n);
    -
    1172 for (
    -
    1173 offset = 0;
    -
    1174 offset < count && str_z[offset];
    -
    1175 offset += stdex::strnlen(str_z + offset, count - offset) + 1)
    -
    1176 this->m_collection.push_back(std::move(std::make_shared<T_parser>(str_z + offset, count - offset, this->m_locale)));
    -
    1177 }
    -
    1178 }
    -
    1179
    -
    1180 void build(_In_z_ const T* str, _In_ va_list params)
    -
    1181 {
    -
    1182 const T* p;
    -
    1183 for (
    -
    1184 this->m_collection.push_back(std::move(std::make_shared<T_parser>(str, (size_t)-1, this->m_locale)));
    -
    1185 (p = va_arg(params, const T*)) != nullptr;
    -
    1186 this->m_collection.push_back(std::move(std::make_shared<T_parser>(p, (size_t)-1, this->m_locale))));
    -
    1187 }
    -
    1188 };
    +
    1114
    +
    1115 using branch = basic_branch<char>;
    + +
    1117#ifdef _UNICODE
    +
    1118 using tbranch = wbranch;
    +
    1119#else
    +
    1120 using tbranch = branch;
    +
    1121#endif
    + +
    1123
    +
    1127 template <class T, class T_parser = basic_string<T>>
    +
    + +
    1129 {
    +
    1130 public:
    +
    1131 inline basic_string_branch(
    +
    1132 _In_reads_(count) const T* str_z = nullptr,
    +
    1133 _In_ size_t count = 0,
    +
    1134 _In_ const std::locale& locale = std::locale()) :
    +
    1135 basic_branch<T>(locale)
    +
    1136 {
    +
    1137 build(str_z, count);
    +
    1138 }
    +
    1139
    +
    1140 inline basic_string_branch(_In_z_ const T* str, ...) :
    +
    1141 basic_branch<T>(std::locale())
    +
    1142 {
    +
    1143 va_list params;
    +
    1144 va_start(params, str);
    +
    1145 build(str, params);
    +
    1146 va_end(params);
    +
    1147 }
    +
    1148
    +
    1149 inline basic_string_branch(_In_ const std::locale& locale, _In_z_ const T* str, ...) :
    +
    1150 basic_branch<T>(locale)
    +
    1151 {
    +
    1152 va_list params;
    +
    1153 va_start(params, str);
    +
    1154 build(str, params);
    +
    1155 va_end(params);
    +
    1156 }
    +
    1157
    +
    1158 protected:
    +
    1159 void build(_In_reads_(count) const T* str_z, _In_ size_t count)
    +
    1160 {
    +
    1161 _Assume_(str_z || !count);
    +
    1162 if (count) {
    +
    1163 size_t offset, n;
    +
    1164 for (
    +
    1165 offset = n = 0;
    +
    1166 offset < count && str_z[offset];
    +
    1167 offset += stdex::strnlen(str_z + offset, count - offset) + 1, ++n);
    +
    1168 this->m_collection.reserve(n);
    +
    1169 for (
    +
    1170 offset = 0;
    +
    1171 offset < count && str_z[offset];
    +
    1172 offset += stdex::strnlen(str_z + offset, count - offset) + 1)
    +
    1173 this->m_collection.push_back(std::move(std::make_shared<T_parser>(str_z + offset, count - offset, this->m_locale)));
    +
    1174 }
    +
    1175 }
    +
    1176
    +
    1177 void build(_In_z_ const T* str, _In_ va_list params)
    +
    1178 {
    +
    1179 const T* p;
    +
    1180 for (
    +
    1181 this->m_collection.push_back(std::move(std::make_shared<T_parser>(str, (size_t)-1, this->m_locale)));
    +
    1182 (p = va_arg(params, const T*)) != nullptr;
    +
    1183 this->m_collection.push_back(std::move(std::make_shared<T_parser>(p, (size_t)-1, this->m_locale))));
    +
    1184 }
    +
    1185 };
    -
    1189
    - - -
    1192#ifdef _UNICODE
    - -
    1194#else
    - -
    1196#endif
    - -
    1198
    -
    1202 template <class T>
    -
    - -
    1204 {
    -
    1205 public:
    - -
    1207 _In_count_(count) const std::shared_ptr<basic_parser<T>>* el = nullptr,
    -
    1208 _In_ size_t count = 0,
    -
    1209 _In_ const std::locale& locale = std::locale()) :
    -
    1210 parser_collection<T>(el, count, locale)
    -
    1211 {}
    -
    1212
    - -
    1214 _Inout_ std::vector<std::shared_ptr<basic_parser<T>>>&& collection,
    -
    1215 _In_ const std::locale& locale = std::locale()) :
    -
    1216 parser_collection<T>(std::move(collection), locale)
    -
    1217 {}
    -
    1218
    -
    1219 virtual bool match(
    -
    1220 _In_reads_or_z_(end) const T* text,
    -
    1221 _In_ size_t start = 0,
    -
    1222 _In_ size_t end = (size_t)-1,
    -
    1223 _In_ int flags = match_default)
    -
    1224 {
    -
    1225 _Assume_(text || start >= end);
    -
    1226 for (auto& el: this->m_collection)
    -
    1227 el->invalidate();
    -
    1228 if (match_recursively(text, start, end, flags)) {
    -
    1229 this->interval.start = start;
    -
    1230 return true;
    -
    1231 }
    -
    1232 this->interval.start = (this->interval.end = start) + 1;
    -
    1233 return false;
    -
    1234 }
    -
    1235
    -
    1236 protected:
    -
    1237 bool match_recursively(
    -
    1238 _In_reads_or_z_(end) const T* text,
    -
    1239 _In_ size_t start = 0,
    -
    1240 _In_ size_t end = (size_t)-1,
    -
    1241 _In_ int flags = match_default)
    -
    1242 {
    -
    1243 bool all_matched = true;
    -
    1244 for (auto& el: this->m_collection) {
    -
    1245 if (!el->interval) {
    -
    1246 // Element was not matched in permutatuion yet.
    -
    1247 all_matched = false;
    -
    1248 if (el->match(text, start, end, flags)) {
    -
    1249 // Element matched for the first time.
    -
    1250 if (match_recursively(text, el->interval.end, end, flags)) {
    -
    1251 // Rest of the elements matched too.
    -
    1252 return true;
    -
    1253 }
    -
    1254 el->invalidate();
    -
    1255 }
    -
    1256 }
    -
    1257 }
    -
    1258 if (all_matched) {
    -
    1259 this->interval.end = start;
    -
    1260 return true;
    -
    1261 }
    -
    1262 return false;
    -
    1263 }
    -
    1264 };
    +
    1186
    + + +
    1189#ifdef _UNICODE
    + +
    1191#else
    + +
    1193#endif
    + +
    1195
    +
    1199 template <class T>
    +
    + +
    1201 {
    +
    1202 public:
    + +
    1204 _In_count_(count) const std::shared_ptr<basic_parser<T>>* el = nullptr,
    +
    1205 _In_ size_t count = 0,
    +
    1206 _In_ const std::locale& locale = std::locale()) :
    +
    1207 parser_collection<T>(el, count, locale)
    +
    1208 {}
    +
    1209
    + +
    1211 _Inout_ std::vector<std::shared_ptr<basic_parser<T>>>&& collection,
    +
    1212 _In_ const std::locale& locale = std::locale()) :
    +
    1213 parser_collection<T>(std::move(collection), locale)
    +
    1214 {}
    +
    1215
    +
    1216 virtual bool match(
    +
    1217 _In_reads_or_z_(end) const T* text,
    +
    1218 _In_ size_t start = 0,
    +
    1219 _In_ size_t end = (size_t)-1,
    +
    1220 _In_ int flags = match_default)
    +
    1221 {
    +
    1222 _Assume_(text || start >= end);
    +
    1223 for (auto& el: this->m_collection)
    +
    1224 el->invalidate();
    +
    1225 if (match_recursively(text, start, end, flags)) {
    +
    1226 this->interval.start = start;
    +
    1227 return true;
    +
    1228 }
    +
    1229 this->interval.start = (this->interval.end = start) + 1;
    +
    1230 return false;
    +
    1231 }
    +
    1232
    +
    1233 protected:
    +
    1234 bool match_recursively(
    +
    1235 _In_reads_or_z_(end) const T* text,
    +
    1236 _In_ size_t start = 0,
    +
    1237 _In_ size_t end = (size_t)-1,
    +
    1238 _In_ int flags = match_default)
    +
    1239 {
    +
    1240 bool all_matched = true;
    +
    1241 for (auto& el: this->m_collection) {
    +
    1242 if (!el->interval) {
    +
    1243 // Element was not matched in permutatuion yet.
    +
    1244 all_matched = false;
    +
    1245 if (el->match(text, start, end, flags)) {
    +
    1246 // Element matched for the first time.
    +
    1247 if (match_recursively(text, el->interval.end, end, flags)) {
    +
    1248 // Rest of the elements matched too.
    +
    1249 return true;
    +
    1250 }
    +
    1251 el->invalidate();
    +
    1252 }
    +
    1253 }
    +
    1254 }
    +
    1255 if (all_matched) {
    +
    1256 this->interval.end = start;
    +
    1257 return true;
    +
    1258 }
    +
    1259 return false;
    +
    1260 }
    +
    1261 };
    -
    1265
    - - -
    1268#ifdef _UNICODE
    -
    1269 using tpermutation = wpermutation;
    -
    1270#else
    -
    1271 using tpermutation = permutation;
    -
    1272#endif
    - -
    1274
    -
    1278 template <class T>
    -
    -
    1279 class basic_integer : public basic_parser<T>
    -
    1280 {
    -
    1281 public:
    -
    1282 basic_integer(_In_ const std::locale& locale = std::locale()) :
    -
    1283 basic_parser<T>(locale),
    -
    1284 value(0)
    -
    1285 {}
    -
    1286
    -
    1287 virtual void invalidate()
    -
    1288 {
    -
    1289 value = 0;
    - -
    1291 }
    -
    1292
    -
    1293 public:
    -
    1294 size_t value;
    -
    1295 };
    +
    1262
    + + +
    1265#ifdef _UNICODE
    +
    1266 using tpermutation = wpermutation;
    +
    1267#else
    +
    1268 using tpermutation = permutation;
    +
    1269#endif
    + +
    1271
    +
    1275 template <class T>
    +
    +
    1276 class basic_integer : public basic_parser<T>
    +
    1277 {
    +
    1278 public:
    +
    1279 basic_integer(_In_ const std::locale& locale = std::locale()) :
    +
    1280 basic_parser<T>(locale),
    +
    1281 value(0)
    +
    1282 {}
    +
    1283
    +
    1284 virtual void invalidate()
    +
    1285 {
    +
    1286 value = 0;
    + +
    1288 }
    +
    1289
    +
    1290 public:
    +
    1291 size_t value;
    +
    1292 };
    -
    1296
    -
    1300 template <class T>
    -
    - -
    1302 {
    -
    1303 public:
    - -
    1305 _In_ const std::shared_ptr<basic_parser<T>>& digit_0,
    -
    1306 _In_ const std::shared_ptr<basic_parser<T>>& digit_1,
    -
    1307 _In_ const std::shared_ptr<basic_parser<T>>& digit_2,
    -
    1308 _In_ const std::shared_ptr<basic_parser<T>>& digit_3,
    -
    1309 _In_ const std::shared_ptr<basic_parser<T>>& digit_4,
    -
    1310 _In_ const std::shared_ptr<basic_parser<T>>& digit_5,
    -
    1311 _In_ const std::shared_ptr<basic_parser<T>>& digit_6,
    -
    1312 _In_ const std::shared_ptr<basic_parser<T>>& digit_7,
    -
    1313 _In_ const std::shared_ptr<basic_parser<T>>& digit_8,
    -
    1314 _In_ const std::shared_ptr<basic_parser<T>>& digit_9,
    -
    1315 _In_ const std::locale& locale = std::locale()) :
    -
    1316 basic_integer<T>(locale),
    -
    1317 m_digit_0(digit_0),
    -
    1318 m_digit_1(digit_1),
    -
    1319 m_digit_2(digit_2),
    -
    1320 m_digit_3(digit_3),
    -
    1321 m_digit_4(digit_4),
    -
    1322 m_digit_5(digit_5),
    -
    1323 m_digit_6(digit_6),
    -
    1324 m_digit_7(digit_7),
    -
    1325 m_digit_8(digit_8),
    -
    1326 m_digit_9(digit_9)
    -
    1327 {}
    -
    1328
    -
    1329 virtual bool match(
    -
    1330 _In_reads_or_z_(end) const T* text,
    -
    1331 _In_ size_t start = 0,
    -
    1332 _In_ size_t end = (size_t)-1,
    -
    1333 _In_ int flags = match_default)
    -
    1334 {
    -
    1335 _Assume_(text || start >= end);
    -
    1336 for (this->interval.end = start, this->value = 0; this->interval.end < end && text[this->interval.end];) {
    -
    1337 size_t dig;
    -
    1338 if (m_digit_0->match(text, this->interval.end, end, flags)) { dig = 0; this->interval.end = m_digit_0->interval.end; }
    -
    1339 else if (m_digit_1->match(text, this->interval.end, end, flags)) { dig = 1; this->interval.end = m_digit_1->interval.end; }
    -
    1340 else if (m_digit_2->match(text, this->interval.end, end, flags)) { dig = 2; this->interval.end = m_digit_2->interval.end; }
    -
    1341 else if (m_digit_3->match(text, this->interval.end, end, flags)) { dig = 3; this->interval.end = m_digit_3->interval.end; }
    -
    1342 else if (m_digit_4->match(text, this->interval.end, end, flags)) { dig = 4; this->interval.end = m_digit_4->interval.end; }
    -
    1343 else if (m_digit_5->match(text, this->interval.end, end, flags)) { dig = 5; this->interval.end = m_digit_5->interval.end; }
    -
    1344 else if (m_digit_6->match(text, this->interval.end, end, flags)) { dig = 6; this->interval.end = m_digit_6->interval.end; }
    -
    1345 else if (m_digit_7->match(text, this->interval.end, end, flags)) { dig = 7; this->interval.end = m_digit_7->interval.end; }
    -
    1346 else if (m_digit_8->match(text, this->interval.end, end, flags)) { dig = 8; this->interval.end = m_digit_8->interval.end; }
    -
    1347 else if (m_digit_9->match(text, this->interval.end, end, flags)) { dig = 9; this->interval.end = m_digit_9->interval.end; }
    -
    1348 else break;
    -
    1349 this->value = this->value * 10 + dig;
    -
    1350 }
    - -
    1352 this->interval.start = start;
    -
    1353 return true;
    -
    1354 }
    -
    1355 this->interval.start = (this->interval.end = start) + 1;
    -
    1356 return false;
    -
    1357 }
    -
    1358
    -
    1359 protected:
    -
    1360 std::shared_ptr<basic_parser<T>>
    -
    1361 m_digit_0,
    -
    1362 m_digit_1,
    -
    1363 m_digit_2,
    -
    1364 m_digit_3,
    -
    1365 m_digit_4,
    -
    1366 m_digit_5,
    -
    1367 m_digit_6,
    -
    1368 m_digit_7,
    -
    1369 m_digit_8,
    -
    1370 m_digit_9;
    -
    1371 };
    +
    1293
    +
    1297 template <class T>
    +
    + +
    1299 {
    +
    1300 public:
    + +
    1302 _In_ const std::shared_ptr<basic_parser<T>>& digit_0,
    +
    1303 _In_ const std::shared_ptr<basic_parser<T>>& digit_1,
    +
    1304 _In_ const std::shared_ptr<basic_parser<T>>& digit_2,
    +
    1305 _In_ const std::shared_ptr<basic_parser<T>>& digit_3,
    +
    1306 _In_ const std::shared_ptr<basic_parser<T>>& digit_4,
    +
    1307 _In_ const std::shared_ptr<basic_parser<T>>& digit_5,
    +
    1308 _In_ const std::shared_ptr<basic_parser<T>>& digit_6,
    +
    1309 _In_ const std::shared_ptr<basic_parser<T>>& digit_7,
    +
    1310 _In_ const std::shared_ptr<basic_parser<T>>& digit_8,
    +
    1311 _In_ const std::shared_ptr<basic_parser<T>>& digit_9,
    +
    1312 _In_ const std::locale& locale = std::locale()) :
    +
    1313 basic_integer<T>(locale),
    +
    1314 m_digit_0(digit_0),
    +
    1315 m_digit_1(digit_1),
    +
    1316 m_digit_2(digit_2),
    +
    1317 m_digit_3(digit_3),
    +
    1318 m_digit_4(digit_4),
    +
    1319 m_digit_5(digit_5),
    +
    1320 m_digit_6(digit_6),
    +
    1321 m_digit_7(digit_7),
    +
    1322 m_digit_8(digit_8),
    +
    1323 m_digit_9(digit_9)
    +
    1324 {}
    +
    1325
    +
    1326 virtual bool match(
    +
    1327 _In_reads_or_z_(end) const T* text,
    +
    1328 _In_ size_t start = 0,
    +
    1329 _In_ size_t end = (size_t)-1,
    +
    1330 _In_ int flags = match_default)
    +
    1331 {
    +
    1332 _Assume_(text || start >= end);
    +
    1333 for (this->interval.end = start, this->value = 0; this->interval.end < end && text[this->interval.end];) {
    +
    1334 size_t dig;
    +
    1335 if (m_digit_0->match(text, this->interval.end, end, flags)) { dig = 0; this->interval.end = m_digit_0->interval.end; }
    +
    1336 else if (m_digit_1->match(text, this->interval.end, end, flags)) { dig = 1; this->interval.end = m_digit_1->interval.end; }
    +
    1337 else if (m_digit_2->match(text, this->interval.end, end, flags)) { dig = 2; this->interval.end = m_digit_2->interval.end; }
    +
    1338 else if (m_digit_3->match(text, this->interval.end, end, flags)) { dig = 3; this->interval.end = m_digit_3->interval.end; }
    +
    1339 else if (m_digit_4->match(text, this->interval.end, end, flags)) { dig = 4; this->interval.end = m_digit_4->interval.end; }
    +
    1340 else if (m_digit_5->match(text, this->interval.end, end, flags)) { dig = 5; this->interval.end = m_digit_5->interval.end; }
    +
    1341 else if (m_digit_6->match(text, this->interval.end, end, flags)) { dig = 6; this->interval.end = m_digit_6->interval.end; }
    +
    1342 else if (m_digit_7->match(text, this->interval.end, end, flags)) { dig = 7; this->interval.end = m_digit_7->interval.end; }
    +
    1343 else if (m_digit_8->match(text, this->interval.end, end, flags)) { dig = 8; this->interval.end = m_digit_8->interval.end; }
    +
    1344 else if (m_digit_9->match(text, this->interval.end, end, flags)) { dig = 9; this->interval.end = m_digit_9->interval.end; }
    +
    1345 else break;
    +
    1346 this->value = this->value * 10 + dig;
    +
    1347 }
    + +
    1349 this->interval.start = start;
    +
    1350 return true;
    +
    1351 }
    +
    1352 this->interval.start = (this->interval.end = start) + 1;
    +
    1353 return false;
    +
    1354 }
    +
    1355
    +
    1356 protected:
    +
    1357 std::shared_ptr<basic_parser<T>>
    +
    1358 m_digit_0,
    +
    1359 m_digit_1,
    +
    1360 m_digit_2,
    +
    1361 m_digit_3,
    +
    1362 m_digit_4,
    +
    1363 m_digit_5,
    +
    1364 m_digit_6,
    +
    1365 m_digit_7,
    +
    1366 m_digit_8,
    +
    1367 m_digit_9;
    +
    1368 };
    -
    1372
    - - -
    1375#ifdef _UNICODE
    -
    1376 using tinteger10 = winteger10;
    -
    1377#else
    -
    1378 using tinteger10 = integer10;
    -
    1379#endif
    - -
    1381
    -
    1385 template <class T>
    -
    - -
    1387 {
    -
    1388 public:
    - -
    1390 _In_ const std::shared_ptr<basic_integer10<T>>& digits,
    -
    1391 _In_ const std::shared_ptr<basic_set<T>>& separator,
    -
    1392 _In_ const std::locale& locale = std::locale()) :
    -
    1393 basic_integer<T>(locale),
    -
    1394 digit_count(0),
    -
    1395 has_separators(false),
    -
    1396 m_digits(digits),
    -
    1397 m_separator(separator)
    -
    1398 {}
    -
    1399
    -
    1400 virtual bool match(
    -
    1401 _In_reads_or_z_(end) const T* text,
    -
    1402 _In_ size_t start = 0,
    -
    1403 _In_ size_t end = (size_t)-1,
    -
    1404 _In_ int flags = match_default)
    -
    1405 {
    -
    1406 _Assume_(text || start >= end);
    -
    1407 if (m_digits->match(text, start, end, flags)) {
    -
    1408 // Leading part match.
    -
    1409 this->value = m_digits->value;
    -
    1410 digit_count = m_digits->interval.size();
    -
    1411 has_separators = false;
    -
    1412 this->interval.start = start;
    -
    1413 this->interval.end = m_digits->interval.end;
    -
    1414 if (m_digits->interval.size() <= 3) {
    -
    1415 // Maybe separated with thousand separators?
    -
    1416 size_t hit_offset = (size_t)-1;
    -
    1417 while (m_separator->match(text, this->interval.end, end, flags) &&
    -
    1418 (hit_offset == (size_t)-1 || hit_offset == m_separator->hit_offset) && // All separators must be the same, no mixing.
    -
    1419 m_digits->match(text, m_separator->interval.end, end, flags) &&
    -
    1420 m_digits->interval.size() == 3)
    -
    1421 {
    -
    1422 // Thousand separator and three-digit integer followed.
    -
    1423 this->value = this->value * 1000 + m_digits->value;
    -
    1424 digit_count += 3;
    -
    1425 has_separators = true;
    -
    1426 this->interval.end = m_digits->interval.end;
    -
    1427 hit_offset = m_separator->hit_offset;
    -
    1428 }
    -
    1429 }
    -
    1430
    -
    1431 return true;
    -
    1432 }
    -
    1433 this->value = 0;
    -
    1434 this->interval.start = (this->interval.end = start) + 1;
    -
    1435 return false;
    -
    1436 }
    -
    1437
    -
    1438 virtual void invalidate()
    -
    1439 {
    -
    1440 digit_count = 0;
    -
    1441 has_separators = false;
    - -
    1443 }
    -
    1444
    -
    1445 public:
    - - -
    1448
    -
    1449 protected:
    -
    1450 std::shared_ptr<basic_integer10<T>> m_digits;
    -
    1451 std::shared_ptr<basic_set<T>> m_separator;
    -
    1452 };
    +
    1369
    + + +
    1372#ifdef _UNICODE
    +
    1373 using tinteger10 = winteger10;
    +
    1374#else
    +
    1375 using tinteger10 = integer10;
    +
    1376#endif
    + +
    1378
    +
    1382 template <class T>
    +
    + +
    1384 {
    +
    1385 public:
    + +
    1387 _In_ const std::shared_ptr<basic_integer10<T>>& digits,
    +
    1388 _In_ const std::shared_ptr<basic_set<T>>& separator,
    +
    1389 _In_ const std::locale& locale = std::locale()) :
    +
    1390 basic_integer<T>(locale),
    +
    1391 digit_count(0),
    +
    1392 has_separators(false),
    +
    1393 m_digits(digits),
    +
    1394 m_separator(separator)
    +
    1395 {}
    +
    1396
    +
    1397 virtual bool match(
    +
    1398 _In_reads_or_z_(end) const T* text,
    +
    1399 _In_ size_t start = 0,
    +
    1400 _In_ size_t end = (size_t)-1,
    +
    1401 _In_ int flags = match_default)
    +
    1402 {
    +
    1403 _Assume_(text || start >= end);
    +
    1404 if (m_digits->match(text, start, end, flags)) {
    +
    1405 // Leading part match.
    +
    1406 this->value = m_digits->value;
    +
    1407 digit_count = m_digits->interval.size();
    +
    1408 has_separators = false;
    +
    1409 this->interval.start = start;
    +
    1410 this->interval.end = m_digits->interval.end;
    +
    1411 if (m_digits->interval.size() <= 3) {
    +
    1412 // Maybe separated with thousand separators?
    +
    1413 size_t hit_offset = (size_t)-1;
    +
    1414 while (m_separator->match(text, this->interval.end, end, flags) &&
    +
    1415 (hit_offset == (size_t)-1 || hit_offset == m_separator->hit_offset) && // All separators must be the same, no mixing.
    +
    1416 m_digits->match(text, m_separator->interval.end, end, flags) &&
    +
    1417 m_digits->interval.size() == 3)
    +
    1418 {
    +
    1419 // Thousand separator and three-digit integer followed.
    +
    1420 this->value = this->value * 1000 + m_digits->value;
    +
    1421 digit_count += 3;
    +
    1422 has_separators = true;
    +
    1423 this->interval.end = m_digits->interval.end;
    +
    1424 hit_offset = m_separator->hit_offset;
    +
    1425 }
    +
    1426 }
    +
    1427
    +
    1428 return true;
    +
    1429 }
    +
    1430 this->value = 0;
    +
    1431 this->interval.start = (this->interval.end = start) + 1;
    +
    1432 return false;
    +
    1433 }
    +
    1434
    +
    1435 virtual void invalidate()
    +
    1436 {
    +
    1437 digit_count = 0;
    +
    1438 has_separators = false;
    + +
    1440 }
    +
    1441
    +
    1442 public:
    + + +
    1445
    +
    1446 protected:
    +
    1447 std::shared_ptr<basic_integer10<T>> m_digits;
    +
    1448 std::shared_ptr<basic_set<T>> m_separator;
    +
    1449 };
    -
    1453
    - - -
    1456#ifdef _UNICODE
    -
    1457 using tinteger10ts = winteger10ts;
    -
    1458#else
    -
    1459 using tinteger10ts = integer10ts;
    -
    1460#endif
    - -
    1462
    -
    1466 template <class T>
    -
    - -
    1468 {
    -
    1469 public:
    - -
    1471 _In_ const std::shared_ptr<basic_parser<T>>& digit_0,
    -
    1472 _In_ const std::shared_ptr<basic_parser<T>>& digit_1,
    -
    1473 _In_ const std::shared_ptr<basic_parser<T>>& digit_2,
    -
    1474 _In_ const std::shared_ptr<basic_parser<T>>& digit_3,
    -
    1475 _In_ const std::shared_ptr<basic_parser<T>>& digit_4,
    -
    1476 _In_ const std::shared_ptr<basic_parser<T>>& digit_5,
    -
    1477 _In_ const std::shared_ptr<basic_parser<T>>& digit_6,
    -
    1478 _In_ const std::shared_ptr<basic_parser<T>>& digit_7,
    -
    1479 _In_ const std::shared_ptr<basic_parser<T>>& digit_8,
    -
    1480 _In_ const std::shared_ptr<basic_parser<T>>& digit_9,
    -
    1481 _In_ const std::shared_ptr<basic_parser<T>>& digit_10,
    -
    1482 _In_ const std::shared_ptr<basic_parser<T>>& digit_11,
    -
    1483 _In_ const std::shared_ptr<basic_parser<T>>& digit_12,
    -
    1484 _In_ const std::shared_ptr<basic_parser<T>>& digit_13,
    -
    1485 _In_ const std::shared_ptr<basic_parser<T>>& digit_14,
    -
    1486 _In_ const std::shared_ptr<basic_parser<T>>& digit_15,
    -
    1487 _In_ const std::locale& locale = std::locale()) :
    -
    1488 basic_integer<T>(locale),
    -
    1489 m_digit_0(digit_0),
    -
    1490 m_digit_1(digit_1),
    -
    1491 m_digit_2(digit_2),
    -
    1492 m_digit_3(digit_3),
    -
    1493 m_digit_4(digit_4),
    -
    1494 m_digit_5(digit_5),
    -
    1495 m_digit_6(digit_6),
    -
    1496 m_digit_7(digit_7),
    -
    1497 m_digit_8(digit_8),
    -
    1498 m_digit_9(digit_9),
    -
    1499 m_digit_10(digit_10),
    -
    1500 m_digit_11(digit_11),
    -
    1501 m_digit_12(digit_12),
    -
    1502 m_digit_13(digit_13),
    -
    1503 m_digit_14(digit_14),
    -
    1504 m_digit_15(digit_15)
    -
    1505 {}
    -
    1506
    -
    1507 virtual bool match(
    -
    1508 _In_reads_or_z_(end) const T* text,
    -
    1509 _In_ size_t start = 0,
    -
    1510 _In_ size_t end = (size_t)-1,
    -
    1511 _In_ int flags = match_default)
    -
    1512 {
    -
    1513 _Assume_(text || start >= end);
    -
    1514 for (this->interval.end = start, this->value = 0; this->interval.end < end && text[this->interval.end];) {
    -
    1515 size_t dig;
    -
    1516 if (m_digit_0->match(text, this->interval.end, end, flags)) { dig = 0; this->interval.end = m_digit_0->interval.end; }
    -
    1517 else if (m_digit_1->match(text, this->interval.end, end, flags)) { dig = 1; this->interval.end = m_digit_1->interval.end; }
    -
    1518 else if (m_digit_2->match(text, this->interval.end, end, flags)) { dig = 2; this->interval.end = m_digit_2->interval.end; }
    -
    1519 else if (m_digit_3->match(text, this->interval.end, end, flags)) { dig = 3; this->interval.end = m_digit_3->interval.end; }
    -
    1520 else if (m_digit_4->match(text, this->interval.end, end, flags)) { dig = 4; this->interval.end = m_digit_4->interval.end; }
    -
    1521 else if (m_digit_5->match(text, this->interval.end, end, flags)) { dig = 5; this->interval.end = m_digit_5->interval.end; }
    -
    1522 else if (m_digit_6->match(text, this->interval.end, end, flags)) { dig = 6; this->interval.end = m_digit_6->interval.end; }
    -
    1523 else if (m_digit_7->match(text, this->interval.end, end, flags)) { dig = 7; this->interval.end = m_digit_7->interval.end; }
    -
    1524 else if (m_digit_8->match(text, this->interval.end, end, flags)) { dig = 8; this->interval.end = m_digit_8->interval.end; }
    -
    1525 else if (m_digit_9->match(text, this->interval.end, end, flags)) { dig = 9; this->interval.end = m_digit_9->interval.end; }
    -
    1526 else if (m_digit_10->match(text, this->interval.end, end, flags)) { dig = 10; this->interval.end = m_digit_10->interval.end; }
    -
    1527 else if (m_digit_11->match(text, this->interval.end, end, flags)) { dig = 11; this->interval.end = m_digit_11->interval.end; }
    -
    1528 else if (m_digit_12->match(text, this->interval.end, end, flags)) { dig = 12; this->interval.end = m_digit_12->interval.end; }
    -
    1529 else if (m_digit_13->match(text, this->interval.end, end, flags)) { dig = 13; this->interval.end = m_digit_13->interval.end; }
    -
    1530 else if (m_digit_14->match(text, this->interval.end, end, flags)) { dig = 14; this->interval.end = m_digit_14->interval.end; }
    -
    1531 else if (m_digit_15->match(text, this->interval.end, end, flags)) { dig = 15; this->interval.end = m_digit_15->interval.end; }
    -
    1532 else break;
    -
    1533 this->value = this->value * 16 + dig;
    -
    1534 }
    - -
    1536 this->interval.start = start;
    -
    1537 return true;
    -
    1538 }
    -
    1539 this->interval.start = (this->interval.end = start) + 1;
    -
    1540 return false;
    -
    1541 }
    -
    1542
    -
    1543 protected:
    -
    1544 std::shared_ptr<basic_parser<T>>
    -
    1545 m_digit_0,
    -
    1546 m_digit_1,
    -
    1547 m_digit_2,
    -
    1548 m_digit_3,
    -
    1549 m_digit_4,
    -
    1550 m_digit_5,
    -
    1551 m_digit_6,
    -
    1552 m_digit_7,
    -
    1553 m_digit_8,
    -
    1554 m_digit_9,
    -
    1555 m_digit_10,
    -
    1556 m_digit_11,
    -
    1557 m_digit_12,
    -
    1558 m_digit_13,
    -
    1559 m_digit_14,
    -
    1560 m_digit_15;
    -
    1561 };
    +
    1450
    + + +
    1453#ifdef _UNICODE
    +
    1454 using tinteger10ts = winteger10ts;
    +
    1455#else
    +
    1456 using tinteger10ts = integer10ts;
    +
    1457#endif
    + +
    1459
    +
    1463 template <class T>
    +
    + +
    1465 {
    +
    1466 public:
    + +
    1468 _In_ const std::shared_ptr<basic_parser<T>>& digit_0,
    +
    1469 _In_ const std::shared_ptr<basic_parser<T>>& digit_1,
    +
    1470 _In_ const std::shared_ptr<basic_parser<T>>& digit_2,
    +
    1471 _In_ const std::shared_ptr<basic_parser<T>>& digit_3,
    +
    1472 _In_ const std::shared_ptr<basic_parser<T>>& digit_4,
    +
    1473 _In_ const std::shared_ptr<basic_parser<T>>& digit_5,
    +
    1474 _In_ const std::shared_ptr<basic_parser<T>>& digit_6,
    +
    1475 _In_ const std::shared_ptr<basic_parser<T>>& digit_7,
    +
    1476 _In_ const std::shared_ptr<basic_parser<T>>& digit_8,
    +
    1477 _In_ const std::shared_ptr<basic_parser<T>>& digit_9,
    +
    1478 _In_ const std::shared_ptr<basic_parser<T>>& digit_10,
    +
    1479 _In_ const std::shared_ptr<basic_parser<T>>& digit_11,
    +
    1480 _In_ const std::shared_ptr<basic_parser<T>>& digit_12,
    +
    1481 _In_ const std::shared_ptr<basic_parser<T>>& digit_13,
    +
    1482 _In_ const std::shared_ptr<basic_parser<T>>& digit_14,
    +
    1483 _In_ const std::shared_ptr<basic_parser<T>>& digit_15,
    +
    1484 _In_ const std::locale& locale = std::locale()) :
    +
    1485 basic_integer<T>(locale),
    +
    1486 m_digit_0(digit_0),
    +
    1487 m_digit_1(digit_1),
    +
    1488 m_digit_2(digit_2),
    +
    1489 m_digit_3(digit_3),
    +
    1490 m_digit_4(digit_4),
    +
    1491 m_digit_5(digit_5),
    +
    1492 m_digit_6(digit_6),
    +
    1493 m_digit_7(digit_7),
    +
    1494 m_digit_8(digit_8),
    +
    1495 m_digit_9(digit_9),
    +
    1496 m_digit_10(digit_10),
    +
    1497 m_digit_11(digit_11),
    +
    1498 m_digit_12(digit_12),
    +
    1499 m_digit_13(digit_13),
    +
    1500 m_digit_14(digit_14),
    +
    1501 m_digit_15(digit_15)
    +
    1502 {}
    +
    1503
    +
    1504 virtual bool match(
    +
    1505 _In_reads_or_z_(end) const T* text,
    +
    1506 _In_ size_t start = 0,
    +
    1507 _In_ size_t end = (size_t)-1,
    +
    1508 _In_ int flags = match_default)
    +
    1509 {
    +
    1510 _Assume_(text || start >= end);
    +
    1511 for (this->interval.end = start, this->value = 0; this->interval.end < end && text[this->interval.end];) {
    +
    1512 size_t dig;
    +
    1513 if (m_digit_0->match(text, this->interval.end, end, flags)) { dig = 0; this->interval.end = m_digit_0->interval.end; }
    +
    1514 else if (m_digit_1->match(text, this->interval.end, end, flags)) { dig = 1; this->interval.end = m_digit_1->interval.end; }
    +
    1515 else if (m_digit_2->match(text, this->interval.end, end, flags)) { dig = 2; this->interval.end = m_digit_2->interval.end; }
    +
    1516 else if (m_digit_3->match(text, this->interval.end, end, flags)) { dig = 3; this->interval.end = m_digit_3->interval.end; }
    +
    1517 else if (m_digit_4->match(text, this->interval.end, end, flags)) { dig = 4; this->interval.end = m_digit_4->interval.end; }
    +
    1518 else if (m_digit_5->match(text, this->interval.end, end, flags)) { dig = 5; this->interval.end = m_digit_5->interval.end; }
    +
    1519 else if (m_digit_6->match(text, this->interval.end, end, flags)) { dig = 6; this->interval.end = m_digit_6->interval.end; }
    +
    1520 else if (m_digit_7->match(text, this->interval.end, end, flags)) { dig = 7; this->interval.end = m_digit_7->interval.end; }
    +
    1521 else if (m_digit_8->match(text, this->interval.end, end, flags)) { dig = 8; this->interval.end = m_digit_8->interval.end; }
    +
    1522 else if (m_digit_9->match(text, this->interval.end, end, flags)) { dig = 9; this->interval.end = m_digit_9->interval.end; }
    +
    1523 else if (m_digit_10->match(text, this->interval.end, end, flags)) { dig = 10; this->interval.end = m_digit_10->interval.end; }
    +
    1524 else if (m_digit_11->match(text, this->interval.end, end, flags)) { dig = 11; this->interval.end = m_digit_11->interval.end; }
    +
    1525 else if (m_digit_12->match(text, this->interval.end, end, flags)) { dig = 12; this->interval.end = m_digit_12->interval.end; }
    +
    1526 else if (m_digit_13->match(text, this->interval.end, end, flags)) { dig = 13; this->interval.end = m_digit_13->interval.end; }
    +
    1527 else if (m_digit_14->match(text, this->interval.end, end, flags)) { dig = 14; this->interval.end = m_digit_14->interval.end; }
    +
    1528 else if (m_digit_15->match(text, this->interval.end, end, flags)) { dig = 15; this->interval.end = m_digit_15->interval.end; }
    +
    1529 else break;
    +
    1530 this->value = this->value * 16 + dig;
    +
    1531 }
    + +
    1533 this->interval.start = start;
    +
    1534 return true;
    +
    1535 }
    +
    1536 this->interval.start = (this->interval.end = start) + 1;
    +
    1537 return false;
    +
    1538 }
    +
    1539
    +
    1540 protected:
    +
    1541 std::shared_ptr<basic_parser<T>>
    +
    1542 m_digit_0,
    +
    1543 m_digit_1,
    +
    1544 m_digit_2,
    +
    1545 m_digit_3,
    +
    1546 m_digit_4,
    +
    1547 m_digit_5,
    +
    1548 m_digit_6,
    +
    1549 m_digit_7,
    +
    1550 m_digit_8,
    +
    1551 m_digit_9,
    +
    1552 m_digit_10,
    +
    1553 m_digit_11,
    +
    1554 m_digit_12,
    +
    1555 m_digit_13,
    +
    1556 m_digit_14,
    +
    1557 m_digit_15;
    +
    1558 };
    -
    1562
    - - -
    1565#ifdef _UNICODE
    -
    1566 using tinteger16 = winteger16;
    -
    1567#else
    -
    1568 using tinteger16 = integer16;
    -
    1569#endif
    - -
    1571
    -
    1575 template <class T>
    -
    - -
    1577 {
    -
    1578 public:
    - -
    1580 _In_ const std::shared_ptr<basic_parser<T>>& digit_1,
    -
    1581 _In_ const std::shared_ptr<basic_parser<T>>& digit_5,
    -
    1582 _In_ const std::shared_ptr<basic_parser<T>>& digit_10,
    -
    1583 _In_ const std::shared_ptr<basic_parser<T>>& digit_50,
    -
    1584 _In_ const std::shared_ptr<basic_parser<T>>& digit_100,
    -
    1585 _In_ const std::shared_ptr<basic_parser<T>>& digit_500,
    -
    1586 _In_ const std::shared_ptr<basic_parser<T>>& digit_1000,
    -
    1587 _In_ const std::shared_ptr<basic_parser<T>>& digit_5000,
    -
    1588 _In_ const std::shared_ptr<basic_parser<T>>& digit_10000,
    -
    1589 _In_ const std::locale& locale = std::locale()) :
    -
    1590 basic_integer<T>(locale),
    -
    1591 m_digit_1(digit_1),
    -
    1592 m_digit_5(digit_5),
    -
    1593 m_digit_10(digit_10),
    -
    1594 m_digit_50(digit_50),
    -
    1595 m_digit_100(digit_100),
    -
    1596 m_digit_500(digit_500),
    -
    1597 m_digit_1000(digit_1000),
    -
    1598 m_digit_5000(digit_5000),
    -
    1599 m_digit_10000(digit_10000)
    -
    1600 {}
    -
    1601
    -
    1602 virtual bool match(
    -
    1603 _In_reads_or_z_(end) const T* text,
    -
    1604 _In_ size_t start = 0,
    -
    1605 _In_ size_t end = (size_t)-1,
    -
    1606 _In_ int flags = match_default)
    -
    1607 {
    -
    1608 _Assume_(text || start >= end);
    -
    1609 size_t
    -
    1610 dig[5] = { (size_t)-1, (size_t)-1, (size_t)-1, (size_t)-1, (size_t)-1 },
    -
    1611 end2;
    -
    1612
    -
    1613 for (this->interval.end = start, this->value = 0; this->interval.end < end && text[this->interval.end]; dig[3] = dig[2], dig[2] = dig[1], dig[1] = dig[0], this->interval.end = end2) {
    -
    1614 if (m_digit_1 && m_digit_1->match(text, this->interval.end, end, flags)) { dig[0] = 1; end2 = m_digit_1->interval.end; }
    -
    1615 else if (m_digit_5 && m_digit_5->match(text, this->interval.end, end, flags)) { dig[0] = 5; end2 = m_digit_5->interval.end; }
    -
    1616 else if (m_digit_10 && m_digit_10->match(text, this->interval.end, end, flags)) { dig[0] = 10; end2 = m_digit_10->interval.end; }
    -
    1617 else if (m_digit_50 && m_digit_50->match(text, this->interval.end, end, flags)) { dig[0] = 50; end2 = m_digit_50->interval.end; }
    -
    1618 else if (m_digit_100 && m_digit_100->match(text, this->interval.end, end, flags)) { dig[0] = 100; end2 = m_digit_100->interval.end; }
    -
    1619 else if (m_digit_500 && m_digit_500->match(text, this->interval.end, end, flags)) { dig[0] = 500; end2 = m_digit_500->interval.end; }
    -
    1620 else if (m_digit_1000 && m_digit_1000->match(text, this->interval.end, end, flags)) { dig[0] = 1000; end2 = m_digit_1000->interval.end; }
    -
    1621 else if (m_digit_5000 && m_digit_5000->match(text, this->interval.end, end, flags)) { dig[0] = 5000; end2 = m_digit_5000->interval.end; }
    -
    1622 else if (m_digit_10000 && m_digit_10000->match(text, this->interval.end, end, flags)) { dig[0] = 10000; end2 = m_digit_10000->interval.end; }
    -
    1623 else break;
    +
    1559
    + + +
    1562#ifdef _UNICODE
    +
    1563 using tinteger16 = winteger16;
    +
    1564#else
    +
    1565 using tinteger16 = integer16;
    +
    1566#endif
    + +
    1568
    +
    1572 template <class T>
    +
    + +
    1574 {
    +
    1575 public:
    + +
    1577 _In_ const std::shared_ptr<basic_parser<T>>& digit_1,
    +
    1578 _In_ const std::shared_ptr<basic_parser<T>>& digit_5,
    +
    1579 _In_ const std::shared_ptr<basic_parser<T>>& digit_10,
    +
    1580 _In_ const std::shared_ptr<basic_parser<T>>& digit_50,
    +
    1581 _In_ const std::shared_ptr<basic_parser<T>>& digit_100,
    +
    1582 _In_ const std::shared_ptr<basic_parser<T>>& digit_500,
    +
    1583 _In_ const std::shared_ptr<basic_parser<T>>& digit_1000,
    +
    1584 _In_ const std::shared_ptr<basic_parser<T>>& digit_5000,
    +
    1585 _In_ const std::shared_ptr<basic_parser<T>>& digit_10000,
    +
    1586 _In_ const std::locale& locale = std::locale()) :
    +
    1587 basic_integer<T>(locale),
    +
    1588 m_digit_1(digit_1),
    +
    1589 m_digit_5(digit_5),
    +
    1590 m_digit_10(digit_10),
    +
    1591 m_digit_50(digit_50),
    +
    1592 m_digit_100(digit_100),
    +
    1593 m_digit_500(digit_500),
    +
    1594 m_digit_1000(digit_1000),
    +
    1595 m_digit_5000(digit_5000),
    +
    1596 m_digit_10000(digit_10000)
    +
    1597 {}
    +
    1598
    +
    1599 virtual bool match(
    +
    1600 _In_reads_or_z_(end) const T* text,
    +
    1601 _In_ size_t start = 0,
    +
    1602 _In_ size_t end = (size_t)-1,
    +
    1603 _In_ int flags = match_default)
    +
    1604 {
    +
    1605 _Assume_(text || start >= end);
    +
    1606 size_t
    +
    1607 dig[5] = { (size_t)-1, (size_t)-1, (size_t)-1, (size_t)-1, (size_t)-1 },
    +
    1608 end2;
    +
    1609
    +
    1610 for (this->interval.end = start, this->value = 0; this->interval.end < end && text[this->interval.end]; dig[3] = dig[2], dig[2] = dig[1], dig[1] = dig[0], this->interval.end = end2) {
    +
    1611 if (m_digit_1 && m_digit_1->match(text, this->interval.end, end, flags)) { dig[0] = 1; end2 = m_digit_1->interval.end; }
    +
    1612 else if (m_digit_5 && m_digit_5->match(text, this->interval.end, end, flags)) { dig[0] = 5; end2 = m_digit_5->interval.end; }
    +
    1613 else if (m_digit_10 && m_digit_10->match(text, this->interval.end, end, flags)) { dig[0] = 10; end2 = m_digit_10->interval.end; }
    +
    1614 else if (m_digit_50 && m_digit_50->match(text, this->interval.end, end, flags)) { dig[0] = 50; end2 = m_digit_50->interval.end; }
    +
    1615 else if (m_digit_100 && m_digit_100->match(text, this->interval.end, end, flags)) { dig[0] = 100; end2 = m_digit_100->interval.end; }
    +
    1616 else if (m_digit_500 && m_digit_500->match(text, this->interval.end, end, flags)) { dig[0] = 500; end2 = m_digit_500->interval.end; }
    +
    1617 else if (m_digit_1000 && m_digit_1000->match(text, this->interval.end, end, flags)) { dig[0] = 1000; end2 = m_digit_1000->interval.end; }
    +
    1618 else if (m_digit_5000 && m_digit_5000->match(text, this->interval.end, end, flags)) { dig[0] = 5000; end2 = m_digit_5000->interval.end; }
    +
    1619 else if (m_digit_10000 && m_digit_10000->match(text, this->interval.end, end, flags)) { dig[0] = 10000; end2 = m_digit_10000->interval.end; }
    +
    1620 else break;
    +
    1621
    +
    1622 // Store first digit.
    +
    1623 if (dig[4] == (size_t)-1) dig[4] = dig[0];
    1624
    -
    1625 // Store first digit.
    -
    1626 if (dig[4] == (size_t)-1) dig[4] = dig[0];
    -
    1627
    -
    1628 if (dig[3] == dig[2] && dig[2] == dig[1] && dig[1] == dig[0] && dig[0] != dig[4]) {
    -
    1629 // Same digit repeated four times. No-go, unless first digit. E.g. XIIII vs. XIV. MMMMMCD allowed, IIII also...
    -
    1630 break;
    -
    1631 }
    -
    1632 if (dig[0] <= dig[1]) {
    -
    1633 // Digit is less or equal previous one: add.
    -
    1634 this->value += dig[0];
    -
    1635 }
    -
    1636 else if (
    -
    1637 (dig[1] == 1 && (dig[0] == 5 || dig[0] == 10)) ||
    -
    1638 (dig[1] == 10 && (dig[0] == 50 || dig[0] == 100)) ||
    -
    1639 (dig[1] == 100 && (dig[0] == 500 || dig[0] == 1000)) ||
    -
    1640 (dig[1] == 1000 && (dig[0] == 5000 || dig[0] == 10000)))
    -
    1641 {
    -
    1642 // Digit is up to two orders bigger than previous one: subtract. But...
    -
    1643 if (dig[2] < dig[0]) {
    -
    1644 // Digit is also bigger than pre-previous one. E.g. VIX (V < X => invalid)
    -
    1645 break;
    -
    1646 }
    -
    1647 this->value -= dig[1]; // Cancel addition in the previous step.
    -
    1648 dig[0] -= dig[1]; // Combine last two digits.
    -
    1649 dig[1] = dig[2]; // The true previous digit is now pre-previous one. :)
    -
    1650 dig[2] = dig[3]; // The true pre-previous digit is now pre-pre-previous one. :)
    -
    1651 this->value += dig[0]; // Add combined value.
    -
    1652 }
    -
    1653 else {
    -
    1654 // New digit is too big than the previous one. E.g. VX (V < X => invalid)
    -
    1655 break;
    -
    1656 }
    -
    1657 }
    -
    1658 if (this->value) {
    -
    1659 this->interval.start = start;
    -
    1660 return true;
    -
    1661 }
    -
    1662 this->interval.start = (this->interval.end = start) + 1;
    -
    1663 return false;
    -
    1664 }
    -
    1665
    -
    1666 protected:
    -
    1667 std::shared_ptr<basic_parser<T>>
    -
    1668 m_digit_1,
    -
    1669 m_digit_5,
    -
    1670 m_digit_10,
    -
    1671 m_digit_50,
    -
    1672 m_digit_100,
    -
    1673 m_digit_500,
    -
    1674 m_digit_1000,
    -
    1675 m_digit_5000,
    -
    1676 m_digit_10000;
    -
    1677 };
    +
    1625 if (dig[3] == dig[2] && dig[2] == dig[1] && dig[1] == dig[0] && dig[0] != dig[4]) {
    +
    1626 // Same digit repeated four times. No-go, unless first digit. E.g. XIIII vs. XIV. MMMMMCD allowed, IIII also...
    +
    1627 break;
    +
    1628 }
    +
    1629 if (dig[0] <= dig[1]) {
    +
    1630 // Digit is less or equal previous one: add.
    +
    1631 this->value += dig[0];
    +
    1632 }
    +
    1633 else if (
    +
    1634 (dig[1] == 1 && (dig[0] == 5 || dig[0] == 10)) ||
    +
    1635 (dig[1] == 10 && (dig[0] == 50 || dig[0] == 100)) ||
    +
    1636 (dig[1] == 100 && (dig[0] == 500 || dig[0] == 1000)) ||
    +
    1637 (dig[1] == 1000 && (dig[0] == 5000 || dig[0] == 10000)))
    +
    1638 {
    +
    1639 // Digit is up to two orders bigger than previous one: subtract. But...
    +
    1640 if (dig[2] < dig[0]) {
    +
    1641 // Digit is also bigger than pre-previous one. E.g. VIX (V < X => invalid)
    +
    1642 break;
    +
    1643 }
    +
    1644 this->value -= dig[1]; // Cancel addition in the previous step.
    +
    1645 dig[0] -= dig[1]; // Combine last two digits.
    +
    1646 dig[1] = dig[2]; // The true previous digit is now pre-previous one. :)
    +
    1647 dig[2] = dig[3]; // The true pre-previous digit is now pre-pre-previous one. :)
    +
    1648 this->value += dig[0]; // Add combined value.
    +
    1649 }
    +
    1650 else {
    +
    1651 // New digit is too big than the previous one. E.g. VX (V < X => invalid)
    +
    1652 break;
    +
    1653 }
    +
    1654 }
    +
    1655 if (this->value) {
    +
    1656 this->interval.start = start;
    +
    1657 return true;
    +
    1658 }
    +
    1659 this->interval.start = (this->interval.end = start) + 1;
    +
    1660 return false;
    +
    1661 }
    +
    1662
    +
    1663 protected:
    +
    1664 std::shared_ptr<basic_parser<T>>
    +
    1665 m_digit_1,
    +
    1666 m_digit_5,
    +
    1667 m_digit_10,
    +
    1668 m_digit_50,
    +
    1669 m_digit_100,
    +
    1670 m_digit_500,
    +
    1671 m_digit_1000,
    +
    1672 m_digit_5000,
    +
    1673 m_digit_10000;
    +
    1674 };
    -
    1678
    - - -
    1681#ifdef _UNICODE
    - -
    1683#else
    - -
    1685#endif
    - -
    1687
    -
    1691 template <class T>
    -
    - -
    1693 {
    -
    1694 public:
    - -
    1696 _In_ const std::shared_ptr<basic_parser<T>>& _numerator,
    -
    1697 _In_ const std::shared_ptr<basic_parser<T>>& _fraction_line,
    -
    1698 _In_ const std::shared_ptr<basic_parser<T>>& _denominator,
    -
    1699 _In_ const std::locale& locale = std::locale()) :
    -
    1700 basic_parser<T>(locale),
    -
    1701 numerator(_numerator),
    -
    1702 fraction_line(_fraction_line),
    -
    1703 denominator(_denominator)
    -
    1704 {}
    -
    1705
    -
    1706 virtual bool match(
    -
    1707 _In_reads_or_z_(end) const T* text,
    -
    1708 _In_ size_t start = 0,
    -
    1709 _In_ size_t end = (size_t)-1,
    -
    1710 _In_ int flags = match_default)
    -
    1711 {
    -
    1712 _Assume_(text || start >= end);
    -
    1713 if (numerator->match(text, start, end, flags) &&
    -
    1714 fraction_line->match(text, numerator->interval.end, end, flags) &&
    -
    1715 denominator->match(text, fraction_line->interval.end, end, flags))
    -
    1716 {
    -
    1717 this->interval.start = start;
    -
    1718 this->interval.end = denominator->interval.end;
    -
    1719 return true;
    -
    1720 }
    -
    1721 numerator->invalidate();
    -
    1722 fraction_line->invalidate();
    -
    1723 denominator->invalidate();
    -
    1724 this->interval.start = (this->interval.end = start) + 1;
    -
    1725 return false;
    -
    1726 }
    -
    1727
    -
    1728 virtual void invalidate()
    -
    1729 {
    -
    1730 numerator->invalidate();
    -
    1731 fraction_line->invalidate();
    -
    1732 denominator->invalidate();
    - -
    1734 }
    -
    1735
    -
    1736 public:
    -
    1737 std::shared_ptr<basic_parser<T>> numerator;
    -
    1738 std::shared_ptr<basic_parser<T>> fraction_line;
    -
    1739 std::shared_ptr<basic_parser<T>> denominator;
    -
    1740 };
    +
    1675
    + + +
    1678#ifdef _UNICODE
    + +
    1680#else
    + +
    1682#endif
    + +
    1684
    +
    1688 template <class T>
    +
    + +
    1690 {
    +
    1691 public:
    + +
    1693 _In_ const std::shared_ptr<basic_parser<T>>& _numerator,
    +
    1694 _In_ const std::shared_ptr<basic_parser<T>>& _fraction_line,
    +
    1695 _In_ const std::shared_ptr<basic_parser<T>>& _denominator,
    +
    1696 _In_ const std::locale& locale = std::locale()) :
    +
    1697 basic_parser<T>(locale),
    +
    1698 numerator(_numerator),
    +
    1699 fraction_line(_fraction_line),
    +
    1700 denominator(_denominator)
    +
    1701 {}
    +
    1702
    +
    1703 virtual bool match(
    +
    1704 _In_reads_or_z_(end) const T* text,
    +
    1705 _In_ size_t start = 0,
    +
    1706 _In_ size_t end = (size_t)-1,
    +
    1707 _In_ int flags = match_default)
    +
    1708 {
    +
    1709 _Assume_(text || start >= end);
    +
    1710 if (numerator->match(text, start, end, flags) &&
    +
    1711 fraction_line->match(text, numerator->interval.end, end, flags) &&
    +
    1712 denominator->match(text, fraction_line->interval.end, end, flags))
    +
    1713 {
    +
    1714 this->interval.start = start;
    +
    1715 this->interval.end = denominator->interval.end;
    +
    1716 return true;
    +
    1717 }
    +
    1718 numerator->invalidate();
    +
    1719 fraction_line->invalidate();
    +
    1720 denominator->invalidate();
    +
    1721 this->interval.start = (this->interval.end = start) + 1;
    +
    1722 return false;
    +
    1723 }
    +
    1724
    +
    1725 virtual void invalidate()
    +
    1726 {
    +
    1727 numerator->invalidate();
    +
    1728 fraction_line->invalidate();
    +
    1729 denominator->invalidate();
    + +
    1731 }
    +
    1732
    +
    1733 public:
    +
    1734 std::shared_ptr<basic_parser<T>> numerator;
    +
    1735 std::shared_ptr<basic_parser<T>> fraction_line;
    +
    1736 std::shared_ptr<basic_parser<T>> denominator;
    +
    1737 };
    -
    1741
    - - -
    1744#ifdef _UNICODE
    -
    1745 using tfraction = wfraction;
    -
    1746#else
    -
    1747 using tfraction = fraction;
    -
    1748#endif
    - -
    1750
    -
    1754 template <class T>
    -
    -
    1755 class basic_score : public basic_parser<T>
    -
    1756 {
    -
    1757 public:
    - -
    1759 _In_ const std::shared_ptr<basic_parser<T>>& _home,
    -
    1760 _In_ const std::shared_ptr<basic_parser<T>>& _separator,
    -
    1761 _In_ const std::shared_ptr<basic_parser<T>>& _guest,
    -
    1762 _In_ const std::shared_ptr<basic_parser<T>>& space,
    -
    1763 _In_ const std::locale& locale = std::locale()) :
    -
    1764 basic_parser<T>(locale),
    -
    1765 home(_home),
    -
    1766 separator(_separator),
    -
    1767 guest(_guest),
    -
    1768 m_space(space)
    -
    1769 {}
    -
    1770
    -
    1771 virtual bool match(
    -
    1772 _In_reads_or_z_(end) const T* text,
    -
    1773 _In_ size_t start = 0,
    -
    1774 _In_ size_t end = (size_t)-1,
    -
    1775 _In_ int flags = match_default)
    -
    1776 {
    -
    1777 _Assume_(text || start >= end);
    -
    1778 this->interval.end = start;
    -
    1779
    -
    1780 const int space_match_flags = flags & ~match_multiline; // Spaces in score must never be broken in new line.
    -
    1781
    -
    1782 if (home->match(text, this->interval.end, end, flags))
    -
    1783 this->interval.end = home->interval.end;
    -
    1784 else
    -
    1785 goto end;
    -
    1786
    -
    1787 for (; m_space->match(text, this->interval.end, end, space_match_flags); this->interval.end = m_space->interval.end);
    -
    1788
    -
    1789 if (separator->match(text, this->interval.end, end, flags))
    -
    1790 this->interval.end = separator->interval.end;
    -
    1791 else
    -
    1792 goto end;
    -
    1793
    -
    1794 for (; m_space->match(text, this->interval.end, end, space_match_flags); this->interval.end = m_space->interval.end);
    -
    1795
    -
    1796 if (guest->match(text, this->interval.end, end, flags))
    -
    1797 this->interval.end = guest->interval.end;
    -
    1798 else
    -
    1799 goto end;
    +
    1738
    + + +
    1741#ifdef _UNICODE
    +
    1742 using tfraction = wfraction;
    +
    1743#else
    +
    1744 using tfraction = fraction;
    +
    1745#endif
    + +
    1747
    +
    1751 template <class T>
    +
    +
    1752 class basic_score : public basic_parser<T>
    +
    1753 {
    +
    1754 public:
    + +
    1756 _In_ const std::shared_ptr<basic_parser<T>>& _home,
    +
    1757 _In_ const std::shared_ptr<basic_parser<T>>& _separator,
    +
    1758 _In_ const std::shared_ptr<basic_parser<T>>& _guest,
    +
    1759 _In_ const std::shared_ptr<basic_parser<T>>& space,
    +
    1760 _In_ const std::locale& locale = std::locale()) :
    +
    1761 basic_parser<T>(locale),
    +
    1762 home(_home),
    +
    1763 separator(_separator),
    +
    1764 guest(_guest),
    +
    1765 m_space(space)
    +
    1766 {}
    +
    1767
    +
    1768 virtual bool match(
    +
    1769 _In_reads_or_z_(end) const T* text,
    +
    1770 _In_ size_t start = 0,
    +
    1771 _In_ size_t end = (size_t)-1,
    +
    1772 _In_ int flags = match_default)
    +
    1773 {
    +
    1774 _Assume_(text || start >= end);
    +
    1775 this->interval.end = start;
    +
    1776
    +
    1777 const int space_match_flags = flags & ~match_multiline; // Spaces in score must never be broken in new line.
    +
    1778
    +
    1779 if (home->match(text, this->interval.end, end, flags))
    +
    1780 this->interval.end = home->interval.end;
    +
    1781 else
    +
    1782 goto end;
    +
    1783
    +
    1784 for (; m_space->match(text, this->interval.end, end, space_match_flags); this->interval.end = m_space->interval.end);
    +
    1785
    +
    1786 if (separator->match(text, this->interval.end, end, flags))
    +
    1787 this->interval.end = separator->interval.end;
    +
    1788 else
    +
    1789 goto end;
    +
    1790
    +
    1791 for (; m_space->match(text, this->interval.end, end, space_match_flags); this->interval.end = m_space->interval.end);
    +
    1792
    +
    1793 if (guest->match(text, this->interval.end, end, flags))
    +
    1794 this->interval.end = guest->interval.end;
    +
    1795 else
    +
    1796 goto end;
    +
    1797
    +
    1798 this->interval.start = start;
    +
    1799 return true;
    1800
    -
    1801 this->interval.start = start;
    -
    1802 return true;
    -
    1803
    -
    1804 end:
    -
    1805 home->invalidate();
    -
    1806 separator->invalidate();
    -
    1807 guest->invalidate();
    -
    1808 this->interval.start = (this->interval.end = start) + 1;
    -
    1809 return false;
    -
    1810 }
    -
    1811
    -
    1812 virtual void invalidate()
    -
    1813 {
    -
    1814 home->invalidate();
    -
    1815 separator->invalidate();
    -
    1816 guest->invalidate();
    - -
    1818 }
    -
    1819
    -
    1820 public:
    -
    1821 std::shared_ptr<basic_parser<T>> home;
    -
    1822 std::shared_ptr<basic_parser<T>> separator;
    -
    1823 std::shared_ptr<basic_parser<T>> guest;
    -
    1824
    -
    1825 protected:
    -
    1826 std::shared_ptr<basic_parser<T>> m_space;
    -
    1827 };
    +
    1801 end:
    +
    1802 home->invalidate();
    +
    1803 separator->invalidate();
    +
    1804 guest->invalidate();
    +
    1805 this->interval.start = (this->interval.end = start) + 1;
    +
    1806 return false;
    +
    1807 }
    +
    1808
    +
    1809 virtual void invalidate()
    +
    1810 {
    +
    1811 home->invalidate();
    +
    1812 separator->invalidate();
    +
    1813 guest->invalidate();
    + +
    1815 }
    +
    1816
    +
    1817 public:
    +
    1818 std::shared_ptr<basic_parser<T>> home;
    +
    1819 std::shared_ptr<basic_parser<T>> separator;
    +
    1820 std::shared_ptr<basic_parser<T>> guest;
    +
    1821
    +
    1822 protected:
    +
    1823 std::shared_ptr<basic_parser<T>> m_space;
    +
    1824 };
    -
    1828
    -
    1829 using score = basic_score<char>;
    - -
    1831#ifdef _UNICODE
    -
    1832 using tscore = wscore;
    -
    1833#else
    -
    1834 using tscore = score;
    -
    1835#endif
    - -
    1837
    -
    1841 template <class T>
    -
    - -
    1843 {
    -
    1844 public:
    - -
    1846 _In_ const std::shared_ptr<basic_parser<T>>& _positive_sign,
    -
    1847 _In_ const std::shared_ptr<basic_parser<T>>& _negative_sign,
    -
    1848 _In_ const std::shared_ptr<basic_parser<T>>& _special_sign,
    -
    1849 _In_ const std::shared_ptr<basic_parser<T>>& _number,
    -
    1850 _In_ const std::locale& locale = std::locale()) :
    -
    1851 basic_parser<T>(locale),
    - - - - -
    1856 {}
    -
    1857
    -
    1858 virtual bool match(
    -
    1859 _In_reads_or_z_(end) const T* text,
    -
    1860 _In_ size_t start = 0,
    -
    1861 _In_ size_t end = (size_t)-1,
    -
    1862 _In_ int flags = match_default)
    -
    1863 {
    -
    1864 _Assume_(text || start >= end);
    -
    1865 this->interval.end = start;
    -
    1866 if (positive_sign && positive_sign->match(text, this->interval.end, end, flags)) {
    -
    1867 this->interval.end = positive_sign->interval.end;
    -
    1868 if (negative_sign) negative_sign->invalidate();
    -
    1869 if (special_sign) special_sign->invalidate();
    -
    1870 }
    -
    1871 else if (negative_sign && negative_sign->match(text, this->interval.end, end, flags)) {
    -
    1872 this->interval.end = negative_sign->interval.end;
    -
    1873 if (positive_sign) positive_sign->invalidate();
    -
    1874 if (special_sign) special_sign->invalidate();
    -
    1875 }
    -
    1876 else if (special_sign && special_sign->match(text, this->interval.end, end, flags)) {
    -
    1877 this->interval.end = special_sign->interval.end;
    -
    1878 if (positive_sign) positive_sign->invalidate();
    -
    1879 if (negative_sign) negative_sign->invalidate();
    -
    1880 }
    -
    1881 else {
    -
    1882 if (positive_sign) positive_sign->invalidate();
    -
    1883 if (negative_sign) negative_sign->invalidate();
    -
    1884 if (special_sign) special_sign->invalidate();
    -
    1885 }
    -
    1886 if (number->match(text, this->interval.end, end, flags)) {
    -
    1887 this->interval.start = start;
    -
    1888 this->interval.end = number->interval.end;
    -
    1889 return true;
    -
    1890 }
    -
    1891 if (positive_sign) positive_sign->invalidate();
    -
    1892 if (negative_sign) negative_sign->invalidate();
    -
    1893 if (special_sign) special_sign->invalidate();
    -
    1894 number->invalidate();
    -
    1895 this->interval.start = (this->interval.end = start) + 1;
    -
    1896 return false;
    -
    1897 }
    -
    1898
    -
    1899 virtual void invalidate()
    -
    1900 {
    -
    1901 if (positive_sign) positive_sign->invalidate();
    -
    1902 if (negative_sign) negative_sign->invalidate();
    -
    1903 if (special_sign) special_sign->invalidate();
    -
    1904 number->invalidate();
    - -
    1906 }
    -
    1907
    -
    1908 public:
    -
    1909 std::shared_ptr<basic_parser<T>> positive_sign;
    -
    1910 std::shared_ptr<basic_parser<T>> negative_sign;
    -
    1911 std::shared_ptr<basic_parser<T>> special_sign;
    -
    1912 std::shared_ptr<basic_parser<T>> number;
    -
    1913 };
    +
    1825
    +
    1826 using score = basic_score<char>;
    + +
    1828#ifdef _UNICODE
    +
    1829 using tscore = wscore;
    +
    1830#else
    +
    1831 using tscore = score;
    +
    1832#endif
    + +
    1834
    +
    1838 template <class T>
    +
    + +
    1840 {
    +
    1841 public:
    + +
    1843 _In_ const std::shared_ptr<basic_parser<T>>& _positive_sign,
    +
    1844 _In_ const std::shared_ptr<basic_parser<T>>& _negative_sign,
    +
    1845 _In_ const std::shared_ptr<basic_parser<T>>& _special_sign,
    +
    1846 _In_ const std::shared_ptr<basic_parser<T>>& _number,
    +
    1847 _In_ const std::locale& locale = std::locale()) :
    +
    1848 basic_parser<T>(locale),
    + + + + +
    1853 {}
    +
    1854
    +
    1855 virtual bool match(
    +
    1856 _In_reads_or_z_(end) const T* text,
    +
    1857 _In_ size_t start = 0,
    +
    1858 _In_ size_t end = (size_t)-1,
    +
    1859 _In_ int flags = match_default)
    +
    1860 {
    +
    1861 _Assume_(text || start >= end);
    +
    1862 this->interval.end = start;
    +
    1863 if (positive_sign && positive_sign->match(text, this->interval.end, end, flags)) {
    +
    1864 this->interval.end = positive_sign->interval.end;
    +
    1865 if (negative_sign) negative_sign->invalidate();
    +
    1866 if (special_sign) special_sign->invalidate();
    +
    1867 }
    +
    1868 else if (negative_sign && negative_sign->match(text, this->interval.end, end, flags)) {
    +
    1869 this->interval.end = negative_sign->interval.end;
    +
    1870 if (positive_sign) positive_sign->invalidate();
    +
    1871 if (special_sign) special_sign->invalidate();
    +
    1872 }
    +
    1873 else if (special_sign && special_sign->match(text, this->interval.end, end, flags)) {
    +
    1874 this->interval.end = special_sign->interval.end;
    +
    1875 if (positive_sign) positive_sign->invalidate();
    +
    1876 if (negative_sign) negative_sign->invalidate();
    +
    1877 }
    +
    1878 else {
    +
    1879 if (positive_sign) positive_sign->invalidate();
    +
    1880 if (negative_sign) negative_sign->invalidate();
    +
    1881 if (special_sign) special_sign->invalidate();
    +
    1882 }
    +
    1883 if (number->match(text, this->interval.end, end, flags)) {
    +
    1884 this->interval.start = start;
    +
    1885 this->interval.end = number->interval.end;
    +
    1886 return true;
    +
    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 this->interval.start = (this->interval.end = start) + 1;
    +
    1893 return false;
    +
    1894 }
    +
    1895
    +
    1896 virtual void invalidate()
    +
    1897 {
    +
    1898 if (positive_sign) positive_sign->invalidate();
    +
    1899 if (negative_sign) negative_sign->invalidate();
    +
    1900 if (special_sign) special_sign->invalidate();
    +
    1901 number->invalidate();
    + +
    1903 }
    +
    1904
    +
    1905 public:
    +
    1906 std::shared_ptr<basic_parser<T>> positive_sign;
    +
    1907 std::shared_ptr<basic_parser<T>> negative_sign;
    +
    1908 std::shared_ptr<basic_parser<T>> special_sign;
    +
    1909 std::shared_ptr<basic_parser<T>> number;
    +
    1910 };
    -
    1914
    - - -
    1917#ifdef _UNICODE
    - -
    1919#else
    - -
    1921#endif
    - -
    1923
    -
    1927 template <class T>
    -
    - -
    1929 {
    -
    1930 public:
    - -
    1932 _In_ const std::shared_ptr<basic_parser<T>>& _positive_sign,
    -
    1933 _In_ const std::shared_ptr<basic_parser<T>>& _negative_sign,
    -
    1934 _In_ const std::shared_ptr<basic_parser<T>>& _special_sign,
    -
    1935 _In_ const std::shared_ptr<basic_parser<T>>& _integer,
    -
    1936 _In_ const std::shared_ptr<basic_parser<T>>& space,
    -
    1937 _In_ const std::shared_ptr<basic_parser<T>>& _fraction,
    -
    1938 _In_ const std::locale& locale = std::locale()) :
    -
    1939 basic_parser<T>(locale),
    - - - - - -
    1945 m_space(space)
    -
    1946 {}
    -
    1947
    -
    1948 virtual bool match(
    -
    1949 _In_reads_or_z_(end) const T* text,
    -
    1950 _In_ size_t start = 0,
    -
    1951 _In_ size_t end = (size_t)-1,
    -
    1952 _In_ int flags = match_default)
    -
    1953 {
    -
    1954 _Assume_(text || start >= end);
    -
    1955 this->interval.end = start;
    -
    1956
    -
    1957 if (positive_sign && positive_sign->match(text, this->interval.end, end, flags)) {
    -
    1958 this->interval.end = positive_sign->interval.end;
    -
    1959 if (negative_sign) negative_sign->invalidate();
    -
    1960 if (special_sign) special_sign->invalidate();
    -
    1961 }
    -
    1962 else if (negative_sign && negative_sign->match(text, this->interval.end, end, flags)) {
    -
    1963 this->interval.end = negative_sign->interval.end;
    -
    1964 if (positive_sign) positive_sign->invalidate();
    -
    1965 if (special_sign) special_sign->invalidate();
    -
    1966 }
    -
    1967 else if (special_sign && special_sign->match(text, this->interval.end, end, flags)) {
    -
    1968 this->interval.end = special_sign->interval.end;
    -
    1969 if (positive_sign) positive_sign->invalidate();
    -
    1970 if (negative_sign) negative_sign->invalidate();
    -
    1971 }
    -
    1972 else {
    -
    1973 if (positive_sign) positive_sign->invalidate();
    -
    1974 if (negative_sign) negative_sign->invalidate();
    -
    1975 if (special_sign) special_sign->invalidate();
    -
    1976 }
    -
    1977
    -
    1978 // Check for <integer> <fraction>
    -
    1979 const int space_match_flags = flags & ~match_multiline; // Spaces in fractions must never be broken in new line.
    -
    1980 if (integer->match(text, this->interval.end, end, flags) &&
    -
    1981 m_space->match(text, integer->interval.end, end, space_match_flags))
    -
    1982 {
    -
    1983 for (this->interval.end = m_space->interval.end; m_space->match(text, this->interval.end, end, space_match_flags); this->interval.end = m_space->interval.end);
    -
    1984 if (fraction->match(text, this->interval.end, end, flags)) {
    -
    1985 this->interval.start = start;
    -
    1986 this->interval.end = fraction->interval.end;
    -
    1987 return true;
    -
    1988 }
    -
    1989 fraction->invalidate();
    -
    1990 this->interval.start = start;
    -
    1991 this->interval.end = integer->interval.end;
    -
    1992 return true;
    -
    1993 }
    -
    1994
    -
    1995 // Check for <fraction>
    -
    1996 if (fraction->match(text, this->interval.end, end, flags)) {
    -
    1997 integer->invalidate();
    -
    1998 this->interval.start = start;
    -
    1999 this->interval.end = fraction->interval.end;
    -
    2000 return true;
    -
    2001 }
    -
    2002
    -
    2003 // Check for <integer>
    -
    2004 if (integer->match(text, this->interval.end, end, flags)) {
    -
    2005 fraction->invalidate();
    -
    2006 this->interval.start = start;
    -
    2007 this->interval.end = integer->interval.end;
    -
    2008 return true;
    -
    2009 }
    -
    2010
    -
    2011 if (positive_sign) positive_sign->invalidate();
    -
    2012 if (negative_sign) negative_sign->invalidate();
    -
    2013 if (special_sign) special_sign->invalidate();
    -
    2014 integer->invalidate();
    -
    2015 fraction->invalidate();
    -
    2016 this->interval.start = (this->interval.end = start) + 1;
    -
    2017 return false;
    -
    2018 }
    -
    2019
    -
    2020 virtual void invalidate()
    -
    2021 {
    -
    2022 if (positive_sign) positive_sign->invalidate();
    -
    2023 if (negative_sign) negative_sign->invalidate();
    -
    2024 if (special_sign) special_sign->invalidate();
    -
    2025 integer->invalidate();
    -
    2026 fraction->invalidate();
    - -
    2028 }
    -
    2029
    -
    2030 public:
    -
    2031 std::shared_ptr<basic_parser<T>> positive_sign;
    -
    2032 std::shared_ptr<basic_parser<T>> negative_sign;
    -
    2033 std::shared_ptr<basic_parser<T>> special_sign;
    -
    2034 std::shared_ptr<basic_parser<T>> integer;
    -
    2035 std::shared_ptr<basic_parser<T>> fraction;
    -
    2036
    -
    2037 protected:
    -
    2038 std::shared_ptr<basic_parser<T>> m_space;
    -
    2039 };
    +
    1911
    + + +
    1914#ifdef _UNICODE
    + +
    1916#else
    + +
    1918#endif
    + +
    1920
    +
    1924 template <class T>
    +
    + +
    1926 {
    +
    1927 public:
    + +
    1929 _In_ const std::shared_ptr<basic_parser<T>>& _positive_sign,
    +
    1930 _In_ const std::shared_ptr<basic_parser<T>>& _negative_sign,
    +
    1931 _In_ const std::shared_ptr<basic_parser<T>>& _special_sign,
    +
    1932 _In_ const std::shared_ptr<basic_parser<T>>& _integer,
    +
    1933 _In_ const std::shared_ptr<basic_parser<T>>& space,
    +
    1934 _In_ const std::shared_ptr<basic_parser<T>>& _fraction,
    +
    1935 _In_ const std::locale& locale = std::locale()) :
    +
    1936 basic_parser<T>(locale),
    + + + + + +
    1942 m_space(space)
    +
    1943 {}
    +
    1944
    +
    1945 virtual bool match(
    +
    1946 _In_reads_or_z_(end) const T* text,
    +
    1947 _In_ size_t start = 0,
    +
    1948 _In_ size_t end = (size_t)-1,
    +
    1949 _In_ int flags = match_default)
    +
    1950 {
    +
    1951 _Assume_(text || start >= end);
    +
    1952 this->interval.end = start;
    +
    1953
    +
    1954 if (positive_sign && positive_sign->match(text, this->interval.end, end, flags)) {
    +
    1955 this->interval.end = positive_sign->interval.end;
    +
    1956 if (negative_sign) negative_sign->invalidate();
    +
    1957 if (special_sign) special_sign->invalidate();
    +
    1958 }
    +
    1959 else if (negative_sign && negative_sign->match(text, this->interval.end, end, flags)) {
    +
    1960 this->interval.end = negative_sign->interval.end;
    +
    1961 if (positive_sign) positive_sign->invalidate();
    +
    1962 if (special_sign) special_sign->invalidate();
    +
    1963 }
    +
    1964 else if (special_sign && special_sign->match(text, this->interval.end, end, flags)) {
    +
    1965 this->interval.end = special_sign->interval.end;
    +
    1966 if (positive_sign) positive_sign->invalidate();
    +
    1967 if (negative_sign) negative_sign->invalidate();
    +
    1968 }
    +
    1969 else {
    +
    1970 if (positive_sign) positive_sign->invalidate();
    +
    1971 if (negative_sign) negative_sign->invalidate();
    +
    1972 if (special_sign) special_sign->invalidate();
    +
    1973 }
    +
    1974
    +
    1975 // Check for <integer> <fraction>
    +
    1976 const int space_match_flags = flags & ~match_multiline; // Spaces in fractions must never be broken in new line.
    +
    1977 if (integer->match(text, this->interval.end, end, flags) &&
    +
    1978 m_space->match(text, integer->interval.end, end, space_match_flags))
    +
    1979 {
    +
    1980 for (this->interval.end = m_space->interval.end; m_space->match(text, this->interval.end, end, space_match_flags); this->interval.end = m_space->interval.end);
    +
    1981 if (fraction->match(text, this->interval.end, end, flags)) {
    +
    1982 this->interval.start = start;
    +
    1983 this->interval.end = fraction->interval.end;
    +
    1984 return true;
    +
    1985 }
    +
    1986 fraction->invalidate();
    +
    1987 this->interval.start = start;
    +
    1988 this->interval.end = integer->interval.end;
    +
    1989 return true;
    +
    1990 }
    +
    1991
    +
    1992 // Check for <fraction>
    +
    1993 if (fraction->match(text, this->interval.end, end, flags)) {
    +
    1994 integer->invalidate();
    +
    1995 this->interval.start = start;
    +
    1996 this->interval.end = fraction->interval.end;
    +
    1997 return true;
    +
    1998 }
    +
    1999
    +
    2000 // Check for <integer>
    +
    2001 if (integer->match(text, this->interval.end, end, flags)) {
    +
    2002 fraction->invalidate();
    +
    2003 this->interval.start = start;
    +
    2004 this->interval.end = integer->interval.end;
    +
    2005 return true;
    +
    2006 }
    +
    2007
    +
    2008 if (positive_sign) positive_sign->invalidate();
    +
    2009 if (negative_sign) negative_sign->invalidate();
    +
    2010 if (special_sign) special_sign->invalidate();
    +
    2011 integer->invalidate();
    +
    2012 fraction->invalidate();
    +
    2013 this->interval.start = (this->interval.end = start) + 1;
    +
    2014 return false;
    +
    2015 }
    +
    2016
    +
    2017 virtual void invalidate()
    +
    2018 {
    +
    2019 if (positive_sign) positive_sign->invalidate();
    +
    2020 if (negative_sign) negative_sign->invalidate();
    +
    2021 if (special_sign) special_sign->invalidate();
    +
    2022 integer->invalidate();
    +
    2023 fraction->invalidate();
    + +
    2025 }
    +
    2026
    +
    2027 public:
    +
    2028 std::shared_ptr<basic_parser<T>> positive_sign;
    +
    2029 std::shared_ptr<basic_parser<T>> negative_sign;
    +
    2030 std::shared_ptr<basic_parser<T>> special_sign;
    +
    2031 std::shared_ptr<basic_parser<T>> integer;
    +
    2032 std::shared_ptr<basic_parser<T>> fraction;
    +
    2033
    +
    2034 protected:
    +
    2035 std::shared_ptr<basic_parser<T>> m_space;
    +
    2036 };
    -
    2040
    - - -
    2043#ifdef _UNICODE
    - -
    2045#else
    - -
    2047#endif
    - -
    2049
    -
    2053 template <class T>
    -
    - -
    2055 {
    -
    2056 public:
    - -
    2058 _In_ const std::shared_ptr<basic_parser<T>>& _positive_sign,
    -
    2059 _In_ const std::shared_ptr<basic_parser<T>>& _negative_sign,
    -
    2060 _In_ const std::shared_ptr<basic_parser<T>>& _special_sign,
    -
    2061 _In_ const std::shared_ptr<basic_integer<T>>& _integer,
    -
    2062 _In_ const std::shared_ptr<basic_parser<T>>& _decimal_separator,
    -
    2063 _In_ const std::shared_ptr<basic_integer<T>>& _decimal,
    -
    2064 _In_ const std::shared_ptr<basic_parser<T>>& _exponent_symbol,
    -
    2065 _In_ const std::shared_ptr<basic_parser<T>>& _positive_exp_sign,
    -
    2066 _In_ const std::shared_ptr<basic_parser<T>>& _negative_exp_sign,
    -
    2067 _In_ const std::shared_ptr<basic_integer<T>>& _exponent,
    -
    2068 _In_ const std::locale& locale = std::locale()) :
    -
    2069 basic_parser<T>(locale),
    - - - - - - - - - - -
    2080 value(std::numeric_limits<double>::quiet_NaN())
    -
    2081 {}
    -
    2082
    -
    2083 virtual bool match(
    -
    2084 _In_reads_or_z_(end) const T* text,
    -
    2085 _In_ size_t start = 0,
    -
    2086 _In_ size_t end = (size_t)-1,
    -
    2087 _In_ int flags = match_default)
    -
    2088 {
    -
    2089 _Assume_(text || start >= end);
    -
    2090 this->interval.end = start;
    -
    2091
    -
    2092 if (positive_sign && positive_sign->match(text, this->interval.end, end, flags)) {
    -
    2093 this->interval.end = positive_sign->interval.end;
    -
    2094 if (negative_sign) negative_sign->invalidate();
    -
    2095 if (special_sign) special_sign->invalidate();
    -
    2096 }
    -
    2097 else if (negative_sign && negative_sign->match(text, this->interval.end, end, flags)) {
    -
    2098 this->interval.end = negative_sign->interval.end;
    -
    2099 if (positive_sign) positive_sign->invalidate();
    -
    2100 if (special_sign) special_sign->invalidate();
    -
    2101 }
    -
    2102 else if (special_sign && special_sign->match(text, this->interval.end, end, flags)) {
    -
    2103 this->interval.end = special_sign->interval.end;
    -
    2104 if (positive_sign) positive_sign->invalidate();
    -
    2105 if (negative_sign) negative_sign->invalidate();
    -
    2106 }
    -
    2107 else {
    -
    2108 if (positive_sign) positive_sign->invalidate();
    -
    2109 if (negative_sign) negative_sign->invalidate();
    -
    2110 if (special_sign) special_sign->invalidate();
    -
    2111 }
    +
    2037
    + + +
    2040#ifdef _UNICODE
    + +
    2042#else
    + +
    2044#endif
    + +
    2046
    +
    2050 template <class T>
    +
    + +
    2052 {
    +
    2053 public:
    + +
    2055 _In_ const std::shared_ptr<basic_parser<T>>& _positive_sign,
    +
    2056 _In_ const std::shared_ptr<basic_parser<T>>& _negative_sign,
    +
    2057 _In_ const std::shared_ptr<basic_parser<T>>& _special_sign,
    +
    2058 _In_ const std::shared_ptr<basic_integer<T>>& _integer,
    +
    2059 _In_ const std::shared_ptr<basic_parser<T>>& _decimal_separator,
    +
    2060 _In_ const std::shared_ptr<basic_integer<T>>& _decimal,
    +
    2061 _In_ const std::shared_ptr<basic_parser<T>>& _exponent_symbol,
    +
    2062 _In_ const std::shared_ptr<basic_parser<T>>& _positive_exp_sign,
    +
    2063 _In_ const std::shared_ptr<basic_parser<T>>& _negative_exp_sign,
    +
    2064 _In_ const std::shared_ptr<basic_integer<T>>& _exponent,
    +
    2065 _In_ const std::locale& locale = std::locale()) :
    +
    2066 basic_parser<T>(locale),
    + + + + + + + + + + +
    2077 value(std::numeric_limits<double>::quiet_NaN())
    +
    2078 {}
    +
    2079
    +
    2080 virtual bool match(
    +
    2081 _In_reads_or_z_(end) const T* text,
    +
    2082 _In_ size_t start = 0,
    +
    2083 _In_ size_t end = (size_t)-1,
    +
    2084 _In_ int flags = match_default)
    +
    2085 {
    +
    2086 _Assume_(text || start >= end);
    +
    2087 this->interval.end = start;
    +
    2088
    +
    2089 if (positive_sign && positive_sign->match(text, this->interval.end, end, flags)) {
    +
    2090 this->interval.end = positive_sign->interval.end;
    +
    2091 if (negative_sign) negative_sign->invalidate();
    +
    2092 if (special_sign) special_sign->invalidate();
    +
    2093 }
    +
    2094 else if (negative_sign && negative_sign->match(text, this->interval.end, end, flags)) {
    +
    2095 this->interval.end = negative_sign->interval.end;
    +
    2096 if (positive_sign) positive_sign->invalidate();
    +
    2097 if (special_sign) special_sign->invalidate();
    +
    2098 }
    +
    2099 else if (special_sign && special_sign->match(text, this->interval.end, end, flags)) {
    +
    2100 this->interval.end = special_sign->interval.end;
    +
    2101 if (positive_sign) positive_sign->invalidate();
    +
    2102 if (negative_sign) negative_sign->invalidate();
    +
    2103 }
    +
    2104 else {
    +
    2105 if (positive_sign) positive_sign->invalidate();
    +
    2106 if (negative_sign) negative_sign->invalidate();
    +
    2107 if (special_sign) special_sign->invalidate();
    +
    2108 }
    +
    2109
    +
    2110 if (integer->match(text, this->interval.end, end, flags))
    +
    2111 this->interval.end = integer->interval.end;
    2112
    -
    2113 if (integer->match(text, this->interval.end, end, flags))
    -
    2114 this->interval.end = integer->interval.end;
    -
    2115
    -
    2116 if (decimal_separator->match(text, this->interval.end, end, flags) &&
    - -
    2118 this->interval.end = decimal->interval.end;
    -
    2119 else {
    -
    2120 decimal_separator->invalidate();
    -
    2121 decimal->invalidate();
    -
    2122 }
    -
    2123
    -
    2124 if (integer->interval.empty() &&
    -
    2125 decimal->interval.empty())
    -
    2126 {
    -
    2127 // No integer part, no decimal part.
    -
    2128 if (positive_sign) positive_sign->invalidate();
    -
    2129 if (negative_sign) negative_sign->invalidate();
    -
    2130 if (special_sign) special_sign->invalidate();
    -
    2131 integer->invalidate();
    -
    2132 decimal_separator->invalidate();
    -
    2133 decimal->invalidate();
    -
    2134 if (exponent_symbol) exponent_symbol->invalidate();
    -
    2135 if (positive_exp_sign) positive_exp_sign->invalidate();
    -
    2136 if (negative_exp_sign) negative_exp_sign->invalidate();
    -
    2137 if (exponent) exponent->invalidate();
    -
    2138 this->interval.start = (this->interval.end = start) + 1;
    -
    2139 return false;
    -
    2140 }
    -
    2141
    -
    2142 if (exponent_symbol && exponent_symbol->match(text, this->interval.end, end, flags) &&
    - - -
    2145 (exponent && exponent->match(text, exponent_symbol->interval.end, end, flags))))
    -
    2146 {
    -
    2147 this->interval.end = exponent->interval.end;
    -
    2148 if (negative_exp_sign) negative_exp_sign->invalidate();
    -
    2149 }
    -
    2150 else if (exponent_symbol && exponent_symbol->match(text, this->interval.end, end, flags) &&
    - - -
    2153 {
    -
    2154 this->interval.end = exponent->interval.end;
    -
    2155 if (positive_exp_sign) positive_exp_sign->invalidate();
    -
    2156 }
    -
    2157 else {
    -
    2158 if (exponent_symbol) exponent_symbol->invalidate();
    -
    2159 if (positive_exp_sign) positive_exp_sign->invalidate();
    -
    2160 if (negative_exp_sign) negative_exp_sign->invalidate();
    -
    2161 if (exponent) exponent->invalidate();
    -
    2162 }
    -
    2163
    -
    2164 value = (double)integer->value;
    -
    2165 if (decimal->interval)
    -
    2166 value += (double)decimal->value * pow(10.0, -(double)decimal->interval.size());
    -
    2167 if (negative_sign && negative_sign->interval)
    -
    2168 value = -value;
    -
    2169 if (exponent && exponent->interval) {
    -
    2170 double e = (double)exponent->value;
    -
    2171 if (negative_exp_sign && negative_exp_sign->interval)
    -
    2172 e = -e;
    -
    2173 value *= pow(10.0, e);
    -
    2174 }
    -
    2175
    -
    2176 this->interval.start = start;
    -
    2177 return true;
    -
    2178 }
    -
    2179
    -
    2180 virtual void invalidate()
    -
    2181 {
    -
    2182 if (positive_sign) positive_sign->invalidate();
    -
    2183 if (negative_sign) negative_sign->invalidate();
    -
    2184 if (special_sign) special_sign->invalidate();
    -
    2185 integer->invalidate();
    -
    2186 decimal_separator->invalidate();
    -
    2187 decimal->invalidate();
    -
    2188 if (exponent_symbol) exponent_symbol->invalidate();
    -
    2189 if (positive_exp_sign) positive_exp_sign->invalidate();
    -
    2190 if (negative_exp_sign) negative_exp_sign->invalidate();
    -
    2191 if (exponent) exponent->invalidate();
    -
    2192 value = std::numeric_limits<double>::quiet_NaN();
    - -
    2194 }
    -
    2195
    -
    2196 public:
    -
    2197 std::shared_ptr<basic_parser<T>> positive_sign;
    -
    2198 std::shared_ptr<basic_parser<T>> negative_sign;
    -
    2199 std::shared_ptr<basic_parser<T>> special_sign;
    -
    2200 std::shared_ptr<basic_integer<T>> integer;
    -
    2201 std::shared_ptr<basic_parser<T>> decimal_separator;
    -
    2202 std::shared_ptr<basic_integer<T>> decimal;
    -
    2203 std::shared_ptr<basic_parser<T>> exponent_symbol;
    -
    2204 std::shared_ptr<basic_parser<T>> positive_exp_sign;
    -
    2205 std::shared_ptr<basic_parser<T>> negative_exp_sign;
    -
    2206 std::shared_ptr<basic_integer<T>> exponent;
    -
    2207 double value;
    -
    2208 };
    +
    2113 if (decimal_separator->match(text, this->interval.end, end, flags) &&
    + +
    2115 this->interval.end = decimal->interval.end;
    +
    2116 else {
    +
    2117 decimal_separator->invalidate();
    +
    2118 decimal->invalidate();
    +
    2119 }
    +
    2120
    +
    2121 if (integer->interval.empty() &&
    +
    2122 decimal->interval.empty())
    +
    2123 {
    +
    2124 // No integer part, no decimal part.
    +
    2125 if (positive_sign) positive_sign->invalidate();
    +
    2126 if (negative_sign) negative_sign->invalidate();
    +
    2127 if (special_sign) special_sign->invalidate();
    +
    2128 integer->invalidate();
    +
    2129 decimal_separator->invalidate();
    +
    2130 decimal->invalidate();
    +
    2131 if (exponent_symbol) exponent_symbol->invalidate();
    +
    2132 if (positive_exp_sign) positive_exp_sign->invalidate();
    +
    2133 if (negative_exp_sign) negative_exp_sign->invalidate();
    +
    2134 if (exponent) exponent->invalidate();
    +
    2135 this->interval.start = (this->interval.end = start) + 1;
    +
    2136 return false;
    +
    2137 }
    +
    2138
    +
    2139 if (exponent_symbol && exponent_symbol->match(text, this->interval.end, end, flags) &&
    + + +
    2142 (exponent && exponent->match(text, exponent_symbol->interval.end, end, flags))))
    +
    2143 {
    +
    2144 this->interval.end = exponent->interval.end;
    +
    2145 if (negative_exp_sign) negative_exp_sign->invalidate();
    +
    2146 }
    +
    2147 else if (exponent_symbol && exponent_symbol->match(text, this->interval.end, end, flags) &&
    + + +
    2150 {
    +
    2151 this->interval.end = exponent->interval.end;
    +
    2152 if (positive_exp_sign) positive_exp_sign->invalidate();
    +
    2153 }
    +
    2154 else {
    +
    2155 if (exponent_symbol) exponent_symbol->invalidate();
    +
    2156 if (positive_exp_sign) positive_exp_sign->invalidate();
    +
    2157 if (negative_exp_sign) negative_exp_sign->invalidate();
    +
    2158 if (exponent) exponent->invalidate();
    +
    2159 }
    +
    2160
    +
    2161 value = (double)integer->value;
    +
    2162 if (decimal->interval)
    +
    2163 value += (double)decimal->value * pow(10.0, -(double)decimal->interval.size());
    +
    2164 if (negative_sign && negative_sign->interval)
    +
    2165 value = -value;
    +
    2166 if (exponent && exponent->interval) {
    +
    2167 double e = (double)exponent->value;
    +
    2168 if (negative_exp_sign && negative_exp_sign->interval)
    +
    2169 e = -e;
    +
    2170 value *= pow(10.0, e);
    +
    2171 }
    +
    2172
    +
    2173 this->interval.start = start;
    +
    2174 return true;
    +
    2175 }
    +
    2176
    +
    2177 virtual void invalidate()
    +
    2178 {
    +
    2179 if (positive_sign) positive_sign->invalidate();
    +
    2180 if (negative_sign) negative_sign->invalidate();
    +
    2181 if (special_sign) special_sign->invalidate();
    +
    2182 integer->invalidate();
    +
    2183 decimal_separator->invalidate();
    +
    2184 decimal->invalidate();
    +
    2185 if (exponent_symbol) exponent_symbol->invalidate();
    +
    2186 if (positive_exp_sign) positive_exp_sign->invalidate();
    +
    2187 if (negative_exp_sign) negative_exp_sign->invalidate();
    +
    2188 if (exponent) exponent->invalidate();
    +
    2189 value = std::numeric_limits<double>::quiet_NaN();
    + +
    2191 }
    +
    2192
    +
    2193 public:
    +
    2194 std::shared_ptr<basic_parser<T>> positive_sign;
    +
    2195 std::shared_ptr<basic_parser<T>> negative_sign;
    +
    2196 std::shared_ptr<basic_parser<T>> special_sign;
    +
    2197 std::shared_ptr<basic_integer<T>> integer;
    +
    2198 std::shared_ptr<basic_parser<T>> decimal_separator;
    +
    2199 std::shared_ptr<basic_integer<T>> decimal;
    +
    2200 std::shared_ptr<basic_parser<T>> exponent_symbol;
    +
    2201 std::shared_ptr<basic_parser<T>> positive_exp_sign;
    +
    2202 std::shared_ptr<basic_parser<T>> negative_exp_sign;
    +
    2203 std::shared_ptr<basic_integer<T>> exponent;
    +
    2204 double value;
    +
    2205 };
    -
    2209
    - - -
    2212#ifdef _UNICODE
    - -
    2214#else
    - -
    2216#endif
    - -
    2218
    -
    2222 template <class T>
    -
    - -
    2224 {
    -
    2225 public:
    - -
    2227 _In_ const std::shared_ptr<basic_parser<T>>& _positive_sign,
    -
    2228 _In_ const std::shared_ptr<basic_parser<T>>& _negative_sign,
    -
    2229 _In_ const std::shared_ptr<basic_parser<T>>& _special_sign,
    -
    2230 _In_ const std::shared_ptr<basic_parser<T>>& _currency,
    -
    2231 _In_ const std::shared_ptr<basic_parser<T>>& _integer,
    -
    2232 _In_ const std::shared_ptr<basic_parser<T>>& _decimal_separator,
    -
    2233 _In_ const std::shared_ptr<basic_parser<T>>& _decimal,
    -
    2234 _In_ const std::locale& locale = std::locale()) :
    -
    2235 basic_parser<T>(locale),
    - - - - - - - -
    2243 {}
    -
    2244
    -
    2245 virtual bool match(
    -
    2246 _In_reads_or_z_(end) const T* text,
    -
    2247 _In_ size_t start = 0,
    -
    2248 _In_ size_t end = (size_t)-1,
    -
    2249 _In_ int flags = match_default)
    -
    2250 {
    -
    2251 _Assume_(text || start >= end);
    -
    2252 this->interval.end = start;
    -
    2253
    -
    2254 if (positive_sign->match(text, this->interval.end, end, flags)) {
    -
    2255 this->interval.end = positive_sign->interval.end;
    -
    2256 if (negative_sign) negative_sign->invalidate();
    -
    2257 if (special_sign) special_sign->invalidate();
    -
    2258 }
    -
    2259 else if (negative_sign->match(text, this->interval.end, end, flags)) {
    -
    2260 this->interval.end = negative_sign->interval.end;
    -
    2261 if (positive_sign) positive_sign->invalidate();
    -
    2262 if (special_sign) special_sign->invalidate();
    -
    2263 }
    -
    2264 else if (special_sign->match(text, this->interval.end, end, flags)) {
    -
    2265 this->interval.end = special_sign->interval.end;
    -
    2266 if (positive_sign) positive_sign->invalidate();
    -
    2267 if (negative_sign) negative_sign->invalidate();
    -
    2268 }
    -
    2269 else {
    -
    2270 if (positive_sign) positive_sign->invalidate();
    -
    2271 if (negative_sign) negative_sign->invalidate();
    -
    2272 if (special_sign) special_sign->invalidate();
    -
    2273 }
    -
    2274
    -
    2275 if (currency->match(text, this->interval.end, end, flags))
    -
    2276 this->interval.end = currency->interval.end;
    -
    2277 else {
    -
    2278 if (positive_sign) positive_sign->invalidate();
    -
    2279 if (negative_sign) negative_sign->invalidate();
    -
    2280 if (special_sign) special_sign->invalidate();
    -
    2281 integer->invalidate();
    -
    2282 decimal_separator->invalidate();
    -
    2283 decimal->invalidate();
    -
    2284 this->interval.start = (this->interval.end = start) + 1;
    -
    2285 return false;
    -
    2286 }
    -
    2287
    -
    2288 if (integer->match(text, this->interval.end, end, flags))
    -
    2289 this->interval.end = integer->interval.end;
    -
    2290 if (decimal_separator->match(text, this->interval.end, end, flags) &&
    - -
    2292 this->interval.end = decimal->interval.end;
    -
    2293 else {
    -
    2294 decimal_separator->invalidate();
    -
    2295 decimal->invalidate();
    -
    2296 }
    -
    2297
    -
    2298 if (integer->interval.empty() &&
    -
    2299 decimal->interval.empty())
    -
    2300 {
    -
    2301 // No integer part, no decimal part.
    -
    2302 if (positive_sign) positive_sign->invalidate();
    -
    2303 if (negative_sign) negative_sign->invalidate();
    -
    2304 if (special_sign) special_sign->invalidate();
    -
    2305 currency->invalidate();
    -
    2306 integer->invalidate();
    -
    2307 decimal_separator->invalidate();
    -
    2308 decimal->invalidate();
    -
    2309 this->interval.start = (this->interval.end = start) + 1;
    -
    2310 return false;
    -
    2311 }
    -
    2312
    -
    2313 this->interval.start = start;
    -
    2314 return true;
    -
    2315 }
    -
    2316
    -
    2317 virtual void invalidate()
    -
    2318 {
    -
    2319 if (positive_sign) positive_sign->invalidate();
    -
    2320 if (negative_sign) negative_sign->invalidate();
    -
    2321 if (special_sign) special_sign->invalidate();
    -
    2322 currency->invalidate();
    -
    2323 integer->invalidate();
    -
    2324 decimal_separator->invalidate();
    -
    2325 decimal->invalidate();
    - -
    2327 }
    -
    2328
    -
    2329 public:
    -
    2330 std::shared_ptr<basic_parser<T>> positive_sign;
    -
    2331 std::shared_ptr<basic_parser<T>> negative_sign;
    -
    2332 std::shared_ptr<basic_parser<T>> special_sign;
    -
    2333 std::shared_ptr<basic_parser<T>> currency;
    -
    2334 std::shared_ptr<basic_parser<T>> integer;
    -
    2335 std::shared_ptr<basic_parser<T>> decimal_separator;
    -
    2336 std::shared_ptr<basic_parser<T>> decimal;
    -
    2337 };
    +
    2206
    + + +
    2209#ifdef _UNICODE
    + +
    2211#else
    + +
    2213#endif
    + +
    2215
    +
    2219 template <class T>
    +
    + +
    2221 {
    +
    2222 public:
    + +
    2224 _In_ const std::shared_ptr<basic_parser<T>>& _positive_sign,
    +
    2225 _In_ const std::shared_ptr<basic_parser<T>>& _negative_sign,
    +
    2226 _In_ const std::shared_ptr<basic_parser<T>>& _special_sign,
    +
    2227 _In_ const std::shared_ptr<basic_parser<T>>& _currency,
    +
    2228 _In_ const std::shared_ptr<basic_parser<T>>& _integer,
    +
    2229 _In_ const std::shared_ptr<basic_parser<T>>& _decimal_separator,
    +
    2230 _In_ const std::shared_ptr<basic_parser<T>>& _decimal,
    +
    2231 _In_ const std::locale& locale = std::locale()) :
    +
    2232 basic_parser<T>(locale),
    + + + + + + + +
    2240 {}
    +
    2241
    +
    2242 virtual bool match(
    +
    2243 _In_reads_or_z_(end) const T* text,
    +
    2244 _In_ size_t start = 0,
    +
    2245 _In_ size_t end = (size_t)-1,
    +
    2246 _In_ int flags = match_default)
    +
    2247 {
    +
    2248 _Assume_(text || start >= end);
    +
    2249 this->interval.end = start;
    +
    2250
    +
    2251 if (positive_sign->match(text, this->interval.end, end, flags)) {
    +
    2252 this->interval.end = positive_sign->interval.end;
    +
    2253 if (negative_sign) negative_sign->invalidate();
    +
    2254 if (special_sign) special_sign->invalidate();
    +
    2255 }
    +
    2256 else if (negative_sign->match(text, this->interval.end, end, flags)) {
    +
    2257 this->interval.end = negative_sign->interval.end;
    +
    2258 if (positive_sign) positive_sign->invalidate();
    +
    2259 if (special_sign) special_sign->invalidate();
    +
    2260 }
    +
    2261 else if (special_sign->match(text, this->interval.end, end, flags)) {
    +
    2262 this->interval.end = special_sign->interval.end;
    +
    2263 if (positive_sign) positive_sign->invalidate();
    +
    2264 if (negative_sign) negative_sign->invalidate();
    +
    2265 }
    +
    2266 else {
    +
    2267 if (positive_sign) positive_sign->invalidate();
    +
    2268 if (negative_sign) negative_sign->invalidate();
    +
    2269 if (special_sign) special_sign->invalidate();
    +
    2270 }
    +
    2271
    +
    2272 if (currency->match(text, this->interval.end, end, flags))
    +
    2273 this->interval.end = currency->interval.end;
    +
    2274 else {
    +
    2275 if (positive_sign) positive_sign->invalidate();
    +
    2276 if (negative_sign) negative_sign->invalidate();
    +
    2277 if (special_sign) special_sign->invalidate();
    +
    2278 integer->invalidate();
    +
    2279 decimal_separator->invalidate();
    +
    2280 decimal->invalidate();
    +
    2281 this->interval.start = (this->interval.end = start) + 1;
    +
    2282 return false;
    +
    2283 }
    +
    2284
    +
    2285 if (integer->match(text, this->interval.end, end, flags))
    +
    2286 this->interval.end = integer->interval.end;
    +
    2287 if (decimal_separator->match(text, this->interval.end, end, flags) &&
    + +
    2289 this->interval.end = decimal->interval.end;
    +
    2290 else {
    +
    2291 decimal_separator->invalidate();
    +
    2292 decimal->invalidate();
    +
    2293 }
    +
    2294
    +
    2295 if (integer->interval.empty() &&
    +
    2296 decimal->interval.empty())
    +
    2297 {
    +
    2298 // No integer part, no decimal part.
    +
    2299 if (positive_sign) positive_sign->invalidate();
    +
    2300 if (negative_sign) negative_sign->invalidate();
    +
    2301 if (special_sign) special_sign->invalidate();
    +
    2302 currency->invalidate();
    +
    2303 integer->invalidate();
    +
    2304 decimal_separator->invalidate();
    +
    2305 decimal->invalidate();
    +
    2306 this->interval.start = (this->interval.end = start) + 1;
    +
    2307 return false;
    +
    2308 }
    +
    2309
    +
    2310 this->interval.start = start;
    +
    2311 return true;
    +
    2312 }
    +
    2313
    +
    2314 virtual void invalidate()
    +
    2315 {
    +
    2316 if (positive_sign) positive_sign->invalidate();
    +
    2317 if (negative_sign) negative_sign->invalidate();
    +
    2318 if (special_sign) special_sign->invalidate();
    +
    2319 currency->invalidate();
    +
    2320 integer->invalidate();
    +
    2321 decimal_separator->invalidate();
    +
    2322 decimal->invalidate();
    + +
    2324 }
    +
    2325
    +
    2326 public:
    +
    2327 std::shared_ptr<basic_parser<T>> positive_sign;
    +
    2328 std::shared_ptr<basic_parser<T>> negative_sign;
    +
    2329 std::shared_ptr<basic_parser<T>> special_sign;
    +
    2330 std::shared_ptr<basic_parser<T>> currency;
    +
    2331 std::shared_ptr<basic_parser<T>> integer;
    +
    2332 std::shared_ptr<basic_parser<T>> decimal_separator;
    +
    2333 std::shared_ptr<basic_parser<T>> decimal;
    +
    2334 };
    -
    2338
    - - -
    2341#ifdef _UNICODE
    - -
    2343#else
    - -
    2345#endif
    - -
    2347
    -
    2351 template <class T>
    -
    - -
    2353 {
    -
    2354 public:
    - -
    2356 _In_ const std::shared_ptr<basic_parser<T>>& digit_0,
    -
    2357 _In_ const std::shared_ptr<basic_parser<T>>& digit_1,
    -
    2358 _In_ const std::shared_ptr<basic_parser<T>>& digit_2,
    -
    2359 _In_ const std::shared_ptr<basic_parser<T>>& digit_3,
    -
    2360 _In_ const std::shared_ptr<basic_parser<T>>& digit_4,
    -
    2361 _In_ const std::shared_ptr<basic_parser<T>>& digit_5,
    -
    2362 _In_ const std::shared_ptr<basic_parser<T>>& digit_6,
    -
    2363 _In_ const std::shared_ptr<basic_parser<T>>& digit_7,
    -
    2364 _In_ const std::shared_ptr<basic_parser<T>>& digit_8,
    -
    2365 _In_ const std::shared_ptr<basic_parser<T>>& digit_9,
    -
    2366 _In_ const std::shared_ptr<basic_parser<T>>& separator,
    -
    2367 _In_ const std::locale& locale = std::locale()) :
    -
    2368 basic_parser<T>(locale),
    -
    2369 m_digit_0(digit_0),
    -
    2370 m_digit_1(digit_1),
    -
    2371 m_digit_2(digit_2),
    -
    2372 m_digit_3(digit_3),
    -
    2373 m_digit_4(digit_4),
    -
    2374 m_digit_5(digit_5),
    -
    2375 m_digit_6(digit_6),
    -
    2376 m_digit_7(digit_7),
    -
    2377 m_digit_8(digit_8),
    -
    2378 m_digit_9(digit_9),
    -
    2379 m_separator(separator)
    -
    2380 {
    -
    2381 value.s_addr = 0;
    -
    2382 }
    -
    2383
    -
    2384 virtual bool match(
    -
    2385 _In_reads_or_z_(end) const T* text,
    -
    2386 _In_ size_t start = 0,
    -
    2387 _In_ size_t end = (size_t)-1,
    -
    2388 _In_ int flags = match_default)
    -
    2389 {
    -
    2390 _Assume_(text || start >= end);
    -
    2391 this->interval.end = start;
    -
    2392 value.s_addr = 0;
    -
    2393
    -
    2394 size_t i;
    -
    2395 for (i = 0; i < 4; i++) {
    -
    2396 if (i) {
    -
    2397 if (m_separator->match(text, this->interval.end, end, flags))
    -
    2398 this->interval.end = m_separator->interval.end;
    -
    2399 else
    -
    2400 goto error;
    -
    2401 }
    -
    2402
    -
    2403 components[i].start = this->interval.end;
    -
    2404 bool is_empty = true;
    -
    2405 size_t x;
    -
    2406 for (x = 0; this->interval.end < end && text[this->interval.end];) {
    -
    2407 size_t dig, digit_end;
    -
    2408 if (m_digit_0->match(text, this->interval.end, end, flags)) { dig = 0; digit_end = m_digit_0->interval.end; }
    -
    2409 else if (m_digit_1->match(text, this->interval.end, end, flags)) { dig = 1; digit_end = m_digit_1->interval.end; }
    -
    2410 else if (m_digit_2->match(text, this->interval.end, end, flags)) { dig = 2; digit_end = m_digit_2->interval.end; }
    -
    2411 else if (m_digit_3->match(text, this->interval.end, end, flags)) { dig = 3; digit_end = m_digit_3->interval.end; }
    -
    2412 else if (m_digit_4->match(text, this->interval.end, end, flags)) { dig = 4; digit_end = m_digit_4->interval.end; }
    -
    2413 else if (m_digit_5->match(text, this->interval.end, end, flags)) { dig = 5; digit_end = m_digit_5->interval.end; }
    -
    2414 else if (m_digit_6->match(text, this->interval.end, end, flags)) { dig = 6; digit_end = m_digit_6->interval.end; }
    -
    2415 else if (m_digit_7->match(text, this->interval.end, end, flags)) { dig = 7; digit_end = m_digit_7->interval.end; }
    -
    2416 else if (m_digit_8->match(text, this->interval.end, end, flags)) { dig = 8; digit_end = m_digit_8->interval.end; }
    -
    2417 else if (m_digit_9->match(text, this->interval.end, end, flags)) { dig = 9; digit_end = m_digit_9->interval.end; }
    -
    2418 else break;
    -
    2419 size_t x_n = x * 10 + dig;
    -
    2420 if (x_n <= 255) {
    -
    2421 x = x_n;
    -
    2422 this->interval.end = digit_end;
    -
    2423 is_empty = false;
    -
    2424 }
    -
    2425 else
    -
    2426 break;
    -
    2427 }
    -
    2428 if (is_empty)
    -
    2429 goto error;
    -
    2430 components[i].end = this->interval.end;
    -
    2431 value.s_addr = (value.s_addr << 8) | (uint8_t)x;
    -
    2432 }
    -
    2433 if (i < 4)
    -
    2434 goto error;
    +
    2335
    + + +
    2338#ifdef _UNICODE
    + +
    2340#else
    + +
    2342#endif
    + +
    2344
    +
    2348 template <class T>
    +
    + +
    2350 {
    +
    2351 public:
    + +
    2353 _In_ const std::shared_ptr<basic_parser<T>>& digit_0,
    +
    2354 _In_ const std::shared_ptr<basic_parser<T>>& digit_1,
    +
    2355 _In_ const std::shared_ptr<basic_parser<T>>& digit_2,
    +
    2356 _In_ const std::shared_ptr<basic_parser<T>>& digit_3,
    +
    2357 _In_ const std::shared_ptr<basic_parser<T>>& digit_4,
    +
    2358 _In_ const std::shared_ptr<basic_parser<T>>& digit_5,
    +
    2359 _In_ const std::shared_ptr<basic_parser<T>>& digit_6,
    +
    2360 _In_ const std::shared_ptr<basic_parser<T>>& digit_7,
    +
    2361 _In_ const std::shared_ptr<basic_parser<T>>& digit_8,
    +
    2362 _In_ const std::shared_ptr<basic_parser<T>>& digit_9,
    +
    2363 _In_ const std::shared_ptr<basic_parser<T>>& separator,
    +
    2364 _In_ const std::locale& locale = std::locale()) :
    +
    2365 basic_parser<T>(locale),
    +
    2366 m_digit_0(digit_0),
    +
    2367 m_digit_1(digit_1),
    +
    2368 m_digit_2(digit_2),
    +
    2369 m_digit_3(digit_3),
    +
    2370 m_digit_4(digit_4),
    +
    2371 m_digit_5(digit_5),
    +
    2372 m_digit_6(digit_6),
    +
    2373 m_digit_7(digit_7),
    +
    2374 m_digit_8(digit_8),
    +
    2375 m_digit_9(digit_9),
    +
    2376 m_separator(separator)
    +
    2377 {
    +
    2378 value.s_addr = 0;
    +
    2379 }
    +
    2380
    +
    2381 virtual bool match(
    +
    2382 _In_reads_or_z_(end) const T* text,
    +
    2383 _In_ size_t start = 0,
    +
    2384 _In_ size_t end = (size_t)-1,
    +
    2385 _In_ int flags = match_default)
    +
    2386 {
    +
    2387 _Assume_(text || start >= end);
    +
    2388 this->interval.end = start;
    +
    2389 value.s_addr = 0;
    +
    2390
    +
    2391 size_t i;
    +
    2392 for (i = 0; i < 4; i++) {
    +
    2393 if (i) {
    +
    2394 if (m_separator->match(text, this->interval.end, end, flags))
    +
    2395 this->interval.end = m_separator->interval.end;
    +
    2396 else
    +
    2397 goto error;
    +
    2398 }
    +
    2399
    +
    2400 components[i].start = this->interval.end;
    +
    2401 bool is_empty = true;
    +
    2402 size_t x;
    +
    2403 for (x = 0; this->interval.end < end && text[this->interval.end];) {
    +
    2404 size_t dig, digit_end;
    +
    2405 if (m_digit_0->match(text, this->interval.end, end, flags)) { dig = 0; digit_end = m_digit_0->interval.end; }
    +
    2406 else if (m_digit_1->match(text, this->interval.end, end, flags)) { dig = 1; digit_end = m_digit_1->interval.end; }
    +
    2407 else if (m_digit_2->match(text, this->interval.end, end, flags)) { dig = 2; digit_end = m_digit_2->interval.end; }
    +
    2408 else if (m_digit_3->match(text, this->interval.end, end, flags)) { dig = 3; digit_end = m_digit_3->interval.end; }
    +
    2409 else if (m_digit_4->match(text, this->interval.end, end, flags)) { dig = 4; digit_end = m_digit_4->interval.end; }
    +
    2410 else if (m_digit_5->match(text, this->interval.end, end, flags)) { dig = 5; digit_end = m_digit_5->interval.end; }
    +
    2411 else if (m_digit_6->match(text, this->interval.end, end, flags)) { dig = 6; digit_end = m_digit_6->interval.end; }
    +
    2412 else if (m_digit_7->match(text, this->interval.end, end, flags)) { dig = 7; digit_end = m_digit_7->interval.end; }
    +
    2413 else if (m_digit_8->match(text, this->interval.end, end, flags)) { dig = 8; digit_end = m_digit_8->interval.end; }
    +
    2414 else if (m_digit_9->match(text, this->interval.end, end, flags)) { dig = 9; digit_end = m_digit_9->interval.end; }
    +
    2415 else break;
    +
    2416 size_t x_n = x * 10 + dig;
    +
    2417 if (x_n <= 255) {
    +
    2418 x = x_n;
    +
    2419 this->interval.end = digit_end;
    +
    2420 is_empty = false;
    +
    2421 }
    +
    2422 else
    +
    2423 break;
    +
    2424 }
    +
    2425 if (is_empty)
    +
    2426 goto error;
    +
    2427 components[i].end = this->interval.end;
    +
    2428 value.s_addr = (value.s_addr << 8) | (uint8_t)x;
    +
    2429 }
    +
    2430 if (i < 4)
    +
    2431 goto error;
    +
    2432
    +
    2433 this->interval.start = start;
    +
    2434 return true;
    2435
    -
    2436 this->interval.start = start;
    -
    2437 return true;
    -
    2438
    -
    2439 error:
    -
    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 this->interval.start = (this->interval.end = start) + 1;
    -
    2450 return false;
    -
    2451 }
    -
    2452
    -
    2453 virtual void invalidate()
    -
    2454 {
    -
    2455 components[0].start = 1;
    -
    2456 components[0].end = 0;
    -
    2457 components[1].start = 1;
    -
    2458 components[1].end = 0;
    -
    2459 components[2].start = 1;
    -
    2460 components[2].end = 0;
    -
    2461 components[3].start = 1;
    -
    2462 components[3].end = 0;
    -
    2463 value.s_addr = 0;
    - -
    2465 }
    -
    2466
    -
    2467 public:
    - - -
    2470
    -
    2471 protected:
    -
    2472 std::shared_ptr<basic_parser<T>>
    -
    2473 m_digit_0,
    -
    2474 m_digit_1,
    -
    2475 m_digit_2,
    -
    2476 m_digit_3,
    -
    2477 m_digit_4,
    -
    2478 m_digit_5,
    -
    2479 m_digit_6,
    -
    2480 m_digit_7,
    -
    2481 m_digit_8,
    -
    2482 m_digit_9;
    -
    2483 std::shared_ptr<basic_parser<T>> m_separator;
    -
    2484 };
    +
    2436 error:
    +
    2437 components[0].start = 1;
    +
    2438 components[0].end = 0;
    +
    2439 components[1].start = 1;
    +
    2440 components[1].end = 0;
    +
    2441 components[2].start = 1;
    +
    2442 components[2].end = 0;
    +
    2443 components[3].start = 1;
    +
    2444 components[3].end = 0;
    +
    2445 value.s_addr = 0;
    +
    2446 this->interval.start = (this->interval.end = start) + 1;
    +
    2447 return false;
    +
    2448 }
    +
    2449
    +
    2450 virtual void invalidate()
    +
    2451 {
    +
    2452 components[0].start = 1;
    +
    2453 components[0].end = 0;
    +
    2454 components[1].start = 1;
    +
    2455 components[1].end = 0;
    +
    2456 components[2].start = 1;
    +
    2457 components[2].end = 0;
    +
    2458 components[3].start = 1;
    +
    2459 components[3].end = 0;
    +
    2460 value.s_addr = 0;
    + +
    2462 }
    +
    2463
    +
    2464 public:
    + + +
    2467
    +
    2468 protected:
    +
    2469 std::shared_ptr<basic_parser<T>>
    +
    2470 m_digit_0,
    +
    2471 m_digit_1,
    +
    2472 m_digit_2,
    +
    2473 m_digit_3,
    +
    2474 m_digit_4,
    +
    2475 m_digit_5,
    +
    2476 m_digit_6,
    +
    2477 m_digit_7,
    +
    2478 m_digit_8,
    +
    2479 m_digit_9;
    +
    2480 std::shared_ptr<basic_parser<T>> m_separator;
    +
    2481 };
    -
    2485
    - - -
    2488#ifdef _UNICODE
    - -
    2490#else
    - -
    2492#endif
    - -
    2494
    -
    2498 template <class T>
    -
    - -
    2500 {
    -
    2501 public:
    -
    2502 basic_ipv6_scope_id_char(_In_ const std::locale& locale = std::locale()) : basic_parser<T>(locale) {}
    -
    2503
    -
    2504 virtual bool match(
    -
    2505 _In_reads_or_z_(end) const T* text,
    -
    2506 _In_ size_t start = 0,
    -
    2507 _In_ size_t end = (size_t)-1,
    -
    2508 _In_ int flags = match_default)
    -
    2509 {
    -
    2510 _Assume_(text || start >= end);
    -
    2511 if (start < end && text[start]) {
    -
    2512 if (text[start] == '-' ||
    -
    2513 text[start] == '_' ||
    -
    2514 text[start] == ':' ||
    -
    2515 std::use_facet<std::ctype<T>>(this->m_locale).is(std::ctype_base::alnum, text[start]))
    -
    2516 {
    -
    2517 this->interval.end = (this->interval.start = start) + 1;
    -
    2518 return true;
    -
    2519 }
    -
    2520 }
    -
    2521 this->interval.start = (this->interval.end = start) + 1;
    -
    2522 return false;
    -
    2523 }
    -
    2524 };
    +
    2482
    + + +
    2485#ifdef _UNICODE
    + +
    2487#else
    + +
    2489#endif
    + +
    2491
    +
    2495 template <class T>
    +
    + +
    2497 {
    +
    2498 public:
    +
    2499 basic_ipv6_scope_id_char(_In_ const std::locale& locale = std::locale()) : basic_parser<T>(locale) {}
    +
    2500
    +
    2501 virtual bool match(
    +
    2502 _In_reads_or_z_(end) const T* text,
    +
    2503 _In_ size_t start = 0,
    +
    2504 _In_ size_t end = (size_t)-1,
    +
    2505 _In_ int flags = match_default)
    +
    2506 {
    +
    2507 _Assume_(text || start >= end);
    +
    2508 if (start < end && text[start]) {
    +
    2509 if (text[start] == '-' ||
    +
    2510 text[start] == '_' ||
    +
    2511 text[start] == ':' ||
    +
    2512 std::use_facet<std::ctype<T>>(this->m_locale).is(std::ctype_base::alnum, text[start]))
    +
    2513 {
    +
    2514 this->interval.end = (this->interval.start = start) + 1;
    +
    2515 return true;
    +
    2516 }
    +
    2517 }
    +
    2518 this->interval.start = (this->interval.end = start) + 1;
    +
    2519 return false;
    +
    2520 }
    +
    2521 };
    -
    2525
    - - -
    2528#ifdef _UNICODE
    - -
    2530#else
    - -
    2532#endif
    -
    2533
    -
    - -
    2538 {
    -
    2539 public:
    -
    2540 sgml_ipv6_scope_id_char(_In_ const std::locale& locale = std::locale()) : sgml_parser(locale) {}
    -
    2541
    -
    2542 virtual bool match(
    -
    2543 _In_reads_or_z_(end) const char* text,
    -
    2544 _In_ size_t start = 0,
    -
    2545 _In_ size_t end = (size_t)-1,
    -
    2546 _In_ int flags = match_default)
    -
    2547 {
    -
    2548 _Assume_(text || start >= end);
    -
    2549 if (start < end && text[start]) {
    -
    2550 wchar_t buf[3];
    -
    2551 const wchar_t* chr = next_sgml_cp(text, start, end, this->interval.end, buf);
    -
    2552 const wchar_t* chr_end = chr + stdex::strlen(chr);
    -
    2553 if (((chr[0] == L'-' ||
    -
    2554 chr[0] == L'_' ||
    -
    2555 chr[0] == L':') && chr[1] == 0) ||
    -
    2556 std::use_facet<std::ctype<wchar_t>>(m_locale).scan_not(std::ctype_base::alnum, chr, chr_end) == chr_end)
    -
    2557 {
    -
    2558 this->interval.start = start;
    -
    2559 return true;
    -
    2560 }
    -
    2561 }
    -
    2562 this->interval.start = (this->interval.end = start) + 1;
    -
    2563 return false;
    -
    2564 }
    -
    2565 };
    +
    2522
    + + +
    2525#ifdef _UNICODE
    + +
    2527#else
    + +
    2529#endif
    +
    2530
    +
    + +
    2535 {
    +
    2536 public:
    +
    2537 sgml_ipv6_scope_id_char(_In_ const std::locale& locale = std::locale()) : sgml_parser(locale) {}
    +
    2538
    +
    2539 virtual bool match(
    +
    2540 _In_reads_or_z_(end) const char* text,
    +
    2541 _In_ size_t start = 0,
    +
    2542 _In_ size_t end = (size_t)-1,
    +
    2543 _In_ int flags = match_default)
    +
    2544 {
    +
    2545 _Assume_(text || start >= end);
    +
    2546 if (start < end && text[start]) {
    +
    2547 wchar_t buf[3];
    +
    2548 const wchar_t* chr = next_sgml_cp(text, start, end, this->interval.end, buf);
    +
    2549 const wchar_t* chr_end = chr + stdex::strlen(chr);
    +
    2550 if (((chr[0] == L'-' ||
    +
    2551 chr[0] == L'_' ||
    +
    2552 chr[0] == L':') && chr[1] == 0) ||
    +
    2553 std::use_facet<std::ctype<wchar_t>>(m_locale).scan_not(std::ctype_base::alnum, chr, chr_end) == chr_end)
    +
    2554 {
    +
    2555 this->interval.start = start;
    +
    2556 return true;
    +
    2557 }
    +
    2558 }
    +
    2559 this->interval.start = (this->interval.end = start) + 1;
    +
    2560 return false;
    +
    2561 }
    +
    2562 };
    -
    2566
    -
    2570 template <class T>
    -
    - -
    2572 {
    -
    2573 public:
    - -
    2575 _In_ const std::shared_ptr<basic_parser<T>>& digit_0,
    -
    2576 _In_ const std::shared_ptr<basic_parser<T>>& digit_1,
    -
    2577 _In_ const std::shared_ptr<basic_parser<T>>& digit_2,
    -
    2578 _In_ const std::shared_ptr<basic_parser<T>>& digit_3,
    -
    2579 _In_ const std::shared_ptr<basic_parser<T>>& digit_4,
    -
    2580 _In_ const std::shared_ptr<basic_parser<T>>& digit_5,
    -
    2581 _In_ const std::shared_ptr<basic_parser<T>>& digit_6,
    -
    2582 _In_ const std::shared_ptr<basic_parser<T>>& digit_7,
    -
    2583 _In_ const std::shared_ptr<basic_parser<T>>& digit_8,
    -
    2584 _In_ const std::shared_ptr<basic_parser<T>>& digit_9,
    -
    2585 _In_ const std::shared_ptr<basic_parser<T>>& digit_10,
    -
    2586 _In_ const std::shared_ptr<basic_parser<T>>& digit_11,
    -
    2587 _In_ const std::shared_ptr<basic_parser<T>>& digit_12,
    -
    2588 _In_ const std::shared_ptr<basic_parser<T>>& digit_13,
    -
    2589 _In_ const std::shared_ptr<basic_parser<T>>& digit_14,
    -
    2590 _In_ const std::shared_ptr<basic_parser<T>>& digit_15,
    -
    2591 _In_ const std::shared_ptr<basic_parser<T>>& separator,
    -
    2592 _In_ const std::shared_ptr<basic_parser<T>>& scope_id_separator = nullptr,
    -
    2593 _In_ const std::shared_ptr<basic_parser<T>>& _scope_id = nullptr,
    -
    2594 _In_ const std::locale& locale = std::locale()) :
    -
    2595 basic_parser<T>(locale),
    -
    2596 m_digit_0(digit_0),
    -
    2597 m_digit_1(digit_1),
    -
    2598 m_digit_2(digit_2),
    -
    2599 m_digit_3(digit_3),
    -
    2600 m_digit_4(digit_4),
    -
    2601 m_digit_5(digit_5),
    -
    2602 m_digit_6(digit_6),
    -
    2603 m_digit_7(digit_7),
    -
    2604 m_digit_8(digit_8),
    -
    2605 m_digit_9(digit_9),
    -
    2606 m_digit_10(digit_10),
    -
    2607 m_digit_11(digit_11),
    -
    2608 m_digit_12(digit_12),
    -
    2609 m_digit_13(digit_13),
    -
    2610 m_digit_14(digit_14),
    -
    2611 m_digit_15(digit_15),
    -
    2612 m_separator(separator),
    -
    2613 m_scope_id_separator(scope_id_separator),
    - -
    2615 {
    -
    2616 memset(&value, 0, sizeof(value));
    -
    2617 }
    -
    2618
    -
    2619 virtual bool match(
    -
    2620 _In_reads_or_z_(end) const T* text,
    -
    2621 _In_ size_t start = 0,
    -
    2622 _In_ size_t end = (size_t)-1,
    -
    2623 _In_ int flags = match_default)
    -
    2624 {
    -
    2625 _Assume_(text || start >= end);
    -
    2626 this->interval.end = start;
    -
    2627 memset(&value, 0, sizeof(value));
    -
    2628
    -
    2629 size_t i, compaction_i = (size_t)-1, compaction_start = start;
    -
    2630 for (i = 0; i < 8; i++) {
    -
    2631 bool is_empty = true;
    -
    2632
    -
    2633 if (m_separator->match(text, this->interval.end, end, flags)) {
    -
    2634 if (m_separator->match(text, m_separator->interval.end, end, flags)) {
    -
    2635 // :: found
    -
    2636 if (compaction_i == (size_t)-1) {
    -
    2637 // Zero compaction start
    -
    2638 compaction_i = i;
    -
    2639 compaction_start = m_separator->interval.start;
    -
    2640 this->interval.end = m_separator->interval.end;
    -
    2641 }
    -
    2642 else {
    -
    2643 // More than one zero compaction
    -
    2644 break;
    -
    2645 }
    -
    2646 }
    -
    2647 else if (i) {
    -
    2648 // Inner : found
    -
    2649 this->interval.end = m_separator->interval.end;
    -
    2650 }
    -
    2651 else {
    -
    2652 // Leading : found
    -
    2653 goto error;
    -
    2654 }
    -
    2655 }
    -
    2656 else if (i) {
    -
    2657 // : missing
    -
    2658 break;
    -
    2659 }
    -
    2660
    -
    2661 components[i].start = this->interval.end;
    -
    2662 size_t x;
    -
    2663 for (x = 0; this->interval.end < end && text[this->interval.end];) {
    -
    2664 size_t dig, digit_end;
    -
    2665 if (m_digit_0->match(text, this->interval.end, end, flags)) { dig = 0; digit_end = m_digit_0->interval.end; }
    -
    2666 else if (m_digit_1->match(text, this->interval.end, end, flags)) { dig = 1; digit_end = m_digit_1->interval.end; }
    -
    2667 else if (m_digit_2->match(text, this->interval.end, end, flags)) { dig = 2; digit_end = m_digit_2->interval.end; }
    -
    2668 else if (m_digit_3->match(text, this->interval.end, end, flags)) { dig = 3; digit_end = m_digit_3->interval.end; }
    -
    2669 else if (m_digit_4->match(text, this->interval.end, end, flags)) { dig = 4; digit_end = m_digit_4->interval.end; }
    -
    2670 else if (m_digit_5->match(text, this->interval.end, end, flags)) { dig = 5; digit_end = m_digit_5->interval.end; }
    -
    2671 else if (m_digit_6->match(text, this->interval.end, end, flags)) { dig = 6; digit_end = m_digit_6->interval.end; }
    -
    2672 else if (m_digit_7->match(text, this->interval.end, end, flags)) { dig = 7; digit_end = m_digit_7->interval.end; }
    -
    2673 else if (m_digit_8->match(text, this->interval.end, end, flags)) { dig = 8; digit_end = m_digit_8->interval.end; }
    -
    2674 else if (m_digit_9->match(text, this->interval.end, end, flags)) { dig = 9; digit_end = m_digit_9->interval.end; }
    -
    2675 else if (m_digit_10->match(text, this->interval.end, end, flags)) { dig = 10; digit_end = m_digit_10->interval.end; }
    -
    2676 else if (m_digit_11->match(text, this->interval.end, end, flags)) { dig = 11; digit_end = m_digit_11->interval.end; }
    -
    2677 else if (m_digit_12->match(text, this->interval.end, end, flags)) { dig = 12; digit_end = m_digit_12->interval.end; }
    -
    2678 else if (m_digit_13->match(text, this->interval.end, end, flags)) { dig = 13; digit_end = m_digit_13->interval.end; }
    -
    2679 else if (m_digit_14->match(text, this->interval.end, end, flags)) { dig = 14; digit_end = m_digit_14->interval.end; }
    -
    2680 else if (m_digit_15->match(text, this->interval.end, end, flags)) { dig = 15; digit_end = m_digit_15->interval.end; }
    -
    2681 else break;
    -
    2682 size_t x_n = x * 16 + dig;
    -
    2683 if (x_n <= 0xffff) {
    -
    2684 x = x_n;
    -
    2685 this->interval.end = digit_end;
    -
    2686 is_empty = false;
    -
    2687 }
    -
    2688 else
    -
    2689 break;
    -
    2690 }
    -
    2691 if (is_empty) {
    -
    2692 if (compaction_i != (size_t)-1) {
    -
    2693 // Zero compaction active: no sweat.
    -
    2694 break;
    -
    2695 }
    -
    2696 goto error;
    -
    2697 }
    -
    2698 components[i].end = this->interval.end;
    -
    2699 this->value.s6_words[i] = (uint16_t)x;
    -
    2700 }
    -
    2701
    -
    2702 if (compaction_i != (size_t)-1) {
    -
    2703 // Align components right due to zero compaction.
    -
    2704 size_t j, k;
    -
    2705 for (j = 8, k = i; k > compaction_i;) {
    -
    2706 this->value.s6_words[--j] = this->value.s6_words[--k];
    - -
    2708 }
    -
    2709 for (; j > compaction_i;) {
    -
    2710 this->value.s6_words[--j] = 0;
    -
    2711 components[j].start =
    - -
    2713 }
    -
    2714 }
    -
    2715 else if (i < 8)
    -
    2716 goto error;
    -
    2717
    -
    2718 if (m_scope_id_separator && m_scope_id_separator->match(text, this->interval.end, end, flags) &&
    -
    2719 scope_id && scope_id->match(text, m_scope_id_separator->interval.end, end, flags))
    -
    2720 this->interval.end = scope_id->interval.end;
    -
    2721 else if (scope_id)
    -
    2722 scope_id->invalidate();
    +
    2563
    +
    2567 template <class T>
    +
    + +
    2569 {
    +
    2570 public:
    + +
    2572 _In_ const std::shared_ptr<basic_parser<T>>& digit_0,
    +
    2573 _In_ const std::shared_ptr<basic_parser<T>>& digit_1,
    +
    2574 _In_ const std::shared_ptr<basic_parser<T>>& digit_2,
    +
    2575 _In_ const std::shared_ptr<basic_parser<T>>& digit_3,
    +
    2576 _In_ const std::shared_ptr<basic_parser<T>>& digit_4,
    +
    2577 _In_ const std::shared_ptr<basic_parser<T>>& digit_5,
    +
    2578 _In_ const std::shared_ptr<basic_parser<T>>& digit_6,
    +
    2579 _In_ const std::shared_ptr<basic_parser<T>>& digit_7,
    +
    2580 _In_ const std::shared_ptr<basic_parser<T>>& digit_8,
    +
    2581 _In_ const std::shared_ptr<basic_parser<T>>& digit_9,
    +
    2582 _In_ const std::shared_ptr<basic_parser<T>>& digit_10,
    +
    2583 _In_ const std::shared_ptr<basic_parser<T>>& digit_11,
    +
    2584 _In_ const std::shared_ptr<basic_parser<T>>& digit_12,
    +
    2585 _In_ const std::shared_ptr<basic_parser<T>>& digit_13,
    +
    2586 _In_ const std::shared_ptr<basic_parser<T>>& digit_14,
    +
    2587 _In_ const std::shared_ptr<basic_parser<T>>& digit_15,
    +
    2588 _In_ const std::shared_ptr<basic_parser<T>>& separator,
    +
    2589 _In_ const std::shared_ptr<basic_parser<T>>& scope_id_separator = nullptr,
    +
    2590 _In_ const std::shared_ptr<basic_parser<T>>& _scope_id = nullptr,
    +
    2591 _In_ const std::locale& locale = std::locale()) :
    +
    2592 basic_parser<T>(locale),
    +
    2593 m_digit_0(digit_0),
    +
    2594 m_digit_1(digit_1),
    +
    2595 m_digit_2(digit_2),
    +
    2596 m_digit_3(digit_3),
    +
    2597 m_digit_4(digit_4),
    +
    2598 m_digit_5(digit_5),
    +
    2599 m_digit_6(digit_6),
    +
    2600 m_digit_7(digit_7),
    +
    2601 m_digit_8(digit_8),
    +
    2602 m_digit_9(digit_9),
    +
    2603 m_digit_10(digit_10),
    +
    2604 m_digit_11(digit_11),
    +
    2605 m_digit_12(digit_12),
    +
    2606 m_digit_13(digit_13),
    +
    2607 m_digit_14(digit_14),
    +
    2608 m_digit_15(digit_15),
    +
    2609 m_separator(separator),
    +
    2610 m_scope_id_separator(scope_id_separator),
    + +
    2612 {
    +
    2613 memset(&value, 0, sizeof(value));
    +
    2614 }
    +
    2615
    +
    2616 virtual bool match(
    +
    2617 _In_reads_or_z_(end) const T* text,
    +
    2618 _In_ size_t start = 0,
    +
    2619 _In_ size_t end = (size_t)-1,
    +
    2620 _In_ int flags = match_default)
    +
    2621 {
    +
    2622 _Assume_(text || start >= end);
    +
    2623 this->interval.end = start;
    +
    2624 memset(&value, 0, sizeof(value));
    +
    2625
    +
    2626 size_t i, compaction_i = (size_t)-1, compaction_start = start;
    +
    2627 for (i = 0; i < 8; i++) {
    +
    2628 bool is_empty = true;
    +
    2629
    +
    2630 if (m_separator->match(text, this->interval.end, end, flags)) {
    +
    2631 if (m_separator->match(text, m_separator->interval.end, end, flags)) {
    +
    2632 // :: found
    +
    2633 if (compaction_i == (size_t)-1) {
    +
    2634 // Zero compaction start
    +
    2635 compaction_i = i;
    +
    2636 compaction_start = m_separator->interval.start;
    +
    2637 this->interval.end = m_separator->interval.end;
    +
    2638 }
    +
    2639 else {
    +
    2640 // More than one zero compaction
    +
    2641 break;
    +
    2642 }
    +
    2643 }
    +
    2644 else if (i) {
    +
    2645 // Inner : found
    +
    2646 this->interval.end = m_separator->interval.end;
    +
    2647 }
    +
    2648 else {
    +
    2649 // Leading : found
    +
    2650 goto error;
    +
    2651 }
    +
    2652 }
    +
    2653 else if (i) {
    +
    2654 // : missing
    +
    2655 break;
    +
    2656 }
    +
    2657
    +
    2658 components[i].start = this->interval.end;
    +
    2659 size_t x;
    +
    2660 for (x = 0; this->interval.end < end && text[this->interval.end];) {
    +
    2661 size_t dig, digit_end;
    +
    2662 if (m_digit_0->match(text, this->interval.end, end, flags)) { dig = 0; digit_end = m_digit_0->interval.end; }
    +
    2663 else if (m_digit_1->match(text, this->interval.end, end, flags)) { dig = 1; digit_end = m_digit_1->interval.end; }
    +
    2664 else if (m_digit_2->match(text, this->interval.end, end, flags)) { dig = 2; digit_end = m_digit_2->interval.end; }
    +
    2665 else if (m_digit_3->match(text, this->interval.end, end, flags)) { dig = 3; digit_end = m_digit_3->interval.end; }
    +
    2666 else if (m_digit_4->match(text, this->interval.end, end, flags)) { dig = 4; digit_end = m_digit_4->interval.end; }
    +
    2667 else if (m_digit_5->match(text, this->interval.end, end, flags)) { dig = 5; digit_end = m_digit_5->interval.end; }
    +
    2668 else if (m_digit_6->match(text, this->interval.end, end, flags)) { dig = 6; digit_end = m_digit_6->interval.end; }
    +
    2669 else if (m_digit_7->match(text, this->interval.end, end, flags)) { dig = 7; digit_end = m_digit_7->interval.end; }
    +
    2670 else if (m_digit_8->match(text, this->interval.end, end, flags)) { dig = 8; digit_end = m_digit_8->interval.end; }
    +
    2671 else if (m_digit_9->match(text, this->interval.end, end, flags)) { dig = 9; digit_end = m_digit_9->interval.end; }
    +
    2672 else if (m_digit_10->match(text, this->interval.end, end, flags)) { dig = 10; digit_end = m_digit_10->interval.end; }
    +
    2673 else if (m_digit_11->match(text, this->interval.end, end, flags)) { dig = 11; digit_end = m_digit_11->interval.end; }
    +
    2674 else if (m_digit_12->match(text, this->interval.end, end, flags)) { dig = 12; digit_end = m_digit_12->interval.end; }
    +
    2675 else if (m_digit_13->match(text, this->interval.end, end, flags)) { dig = 13; digit_end = m_digit_13->interval.end; }
    +
    2676 else if (m_digit_14->match(text, this->interval.end, end, flags)) { dig = 14; digit_end = m_digit_14->interval.end; }
    +
    2677 else if (m_digit_15->match(text, this->interval.end, end, flags)) { dig = 15; digit_end = m_digit_15->interval.end; }
    +
    2678 else break;
    +
    2679 size_t x_n = x * 16 + dig;
    +
    2680 if (x_n <= 0xffff) {
    +
    2681 x = x_n;
    +
    2682 this->interval.end = digit_end;
    +
    2683 is_empty = false;
    +
    2684 }
    +
    2685 else
    +
    2686 break;
    +
    2687 }
    +
    2688 if (is_empty) {
    +
    2689 if (compaction_i != (size_t)-1) {
    +
    2690 // Zero compaction active: no sweat.
    +
    2691 break;
    +
    2692 }
    +
    2693 goto error;
    +
    2694 }
    +
    2695 components[i].end = this->interval.end;
    +
    2696 this->value.s6_words[i] = (uint16_t)x;
    +
    2697 }
    +
    2698
    +
    2699 if (compaction_i != (size_t)-1) {
    +
    2700 // Align components right due to zero compaction.
    +
    2701 size_t j, k;
    +
    2702 for (j = 8, k = i; k > compaction_i;) {
    +
    2703 this->value.s6_words[--j] = this->value.s6_words[--k];
    + +
    2705 }
    +
    2706 for (; j > compaction_i;) {
    +
    2707 this->value.s6_words[--j] = 0;
    +
    2708 components[j].start =
    + +
    2710 }
    +
    2711 }
    +
    2712 else if (i < 8)
    +
    2713 goto error;
    +
    2714
    +
    2715 if (m_scope_id_separator && m_scope_id_separator->match(text, this->interval.end, end, flags) &&
    +
    2716 scope_id && scope_id->match(text, m_scope_id_separator->interval.end, end, flags))
    +
    2717 this->interval.end = scope_id->interval.end;
    +
    2718 else if (scope_id)
    +
    2719 scope_id->invalidate();
    +
    2720
    +
    2721 this->interval.start = start;
    +
    2722 return true;
    2723
    -
    2724 this->interval.start = start;
    -
    2725 return true;
    -
    2726
    -
    2727 error:
    -
    2728 components[0].start = 1;
    -
    2729 components[0].end = 0;
    -
    2730 components[1].start = 1;
    -
    2731 components[1].end = 0;
    -
    2732 components[2].start = 1;
    -
    2733 components[2].end = 0;
    -
    2734 components[3].start = 1;
    -
    2735 components[3].end = 0;
    -
    2736 components[4].start = 1;
    -
    2737 components[4].end = 0;
    -
    2738 components[5].start = 1;
    -
    2739 components[5].end = 0;
    -
    2740 components[6].start = 1;
    -
    2741 components[6].end = 0;
    -
    2742 components[7].start = 1;
    -
    2743 components[7].end = 0;
    -
    2744 memset(&value, 0, sizeof(value));
    -
    2745 if (scope_id) scope_id->invalidate();
    -
    2746 this->interval.start = (this->interval.end = start) + 1;
    -
    2747 return false;
    -
    2748 }
    -
    2749
    -
    2750 virtual void invalidate()
    -
    2751 {
    -
    2752 components[0].start = 1;
    -
    2753 components[0].end = 0;
    -
    2754 components[1].start = 1;
    -
    2755 components[1].end = 0;
    -
    2756 components[2].start = 1;
    -
    2757 components[2].end = 0;
    -
    2758 components[3].start = 1;
    -
    2759 components[3].end = 0;
    -
    2760 components[4].start = 1;
    -
    2761 components[4].end = 0;
    -
    2762 components[5].start = 1;
    -
    2763 components[5].end = 0;
    -
    2764 components[6].start = 1;
    -
    2765 components[6].end = 0;
    -
    2766 components[7].start = 1;
    -
    2767 components[7].end = 0;
    -
    2768 memset(&value, 0, sizeof(value));
    -
    2769 if (scope_id) scope_id->invalidate();
    - -
    2771 }
    -
    2772
    -
    2773 public:
    - - -
    2776 std::shared_ptr<basic_parser<T>> scope_id;
    -
    2777
    -
    2778 protected:
    -
    2779 std::shared_ptr<basic_parser<T>>
    -
    2780 m_digit_0,
    -
    2781 m_digit_1,
    -
    2782 m_digit_2,
    -
    2783 m_digit_3,
    -
    2784 m_digit_4,
    -
    2785 m_digit_5,
    -
    2786 m_digit_6,
    -
    2787 m_digit_7,
    -
    2788 m_digit_8,
    -
    2789 m_digit_9,
    -
    2790 m_digit_10,
    -
    2791 m_digit_11,
    -
    2792 m_digit_12,
    -
    2793 m_digit_13,
    -
    2794 m_digit_14,
    -
    2795 m_digit_15;
    -
    2796 std::shared_ptr<basic_parser<T>> m_separator, m_scope_id_separator;
    -
    2797 };
    +
    2724 error:
    +
    2725 components[0].start = 1;
    +
    2726 components[0].end = 0;
    +
    2727 components[1].start = 1;
    +
    2728 components[1].end = 0;
    +
    2729 components[2].start = 1;
    +
    2730 components[2].end = 0;
    +
    2731 components[3].start = 1;
    +
    2732 components[3].end = 0;
    +
    2733 components[4].start = 1;
    +
    2734 components[4].end = 0;
    +
    2735 components[5].start = 1;
    +
    2736 components[5].end = 0;
    +
    2737 components[6].start = 1;
    +
    2738 components[6].end = 0;
    +
    2739 components[7].start = 1;
    +
    2740 components[7].end = 0;
    +
    2741 memset(&value, 0, sizeof(value));
    +
    2742 if (scope_id) scope_id->invalidate();
    +
    2743 this->interval.start = (this->interval.end = start) + 1;
    +
    2744 return false;
    +
    2745 }
    +
    2746
    +
    2747 virtual void invalidate()
    +
    2748 {
    +
    2749 components[0].start = 1;
    +
    2750 components[0].end = 0;
    +
    2751 components[1].start = 1;
    +
    2752 components[1].end = 0;
    +
    2753 components[2].start = 1;
    +
    2754 components[2].end = 0;
    +
    2755 components[3].start = 1;
    +
    2756 components[3].end = 0;
    +
    2757 components[4].start = 1;
    +
    2758 components[4].end = 0;
    +
    2759 components[5].start = 1;
    +
    2760 components[5].end = 0;
    +
    2761 components[6].start = 1;
    +
    2762 components[6].end = 0;
    +
    2763 components[7].start = 1;
    +
    2764 components[7].end = 0;
    +
    2765 memset(&value, 0, sizeof(value));
    +
    2766 if (scope_id) scope_id->invalidate();
    + +
    2768 }
    +
    2769
    +
    2770 public:
    + + +
    2773 std::shared_ptr<basic_parser<T>> scope_id;
    +
    2774
    +
    2775 protected:
    +
    2776 std::shared_ptr<basic_parser<T>>
    +
    2777 m_digit_0,
    +
    2778 m_digit_1,
    +
    2779 m_digit_2,
    +
    2780 m_digit_3,
    +
    2781 m_digit_4,
    +
    2782 m_digit_5,
    +
    2783 m_digit_6,
    +
    2784 m_digit_7,
    +
    2785 m_digit_8,
    +
    2786 m_digit_9,
    +
    2787 m_digit_10,
    +
    2788 m_digit_11,
    +
    2789 m_digit_12,
    +
    2790 m_digit_13,
    +
    2791 m_digit_14,
    +
    2792 m_digit_15;
    +
    2793 std::shared_ptr<basic_parser<T>> m_separator, m_scope_id_separator;
    +
    2794 };
    -
    2798
    - - -
    2801#ifdef _UNICODE
    - -
    2803#else
    - -
    2805#endif
    - -
    2807
    -
    2811 template <class T>
    -
    - -
    2813 {
    -
    2814 public:
    - -
    2816 _In_ bool allow_idn,
    -
    2817 _In_ const std::locale& locale = std::locale()) :
    -
    2818 basic_parser<T>(locale),
    -
    2819 m_allow_idn(allow_idn),
    -
    2820 allow_on_edge(true)
    -
    2821 {}
    -
    2822
    -
    2823 virtual bool match(
    -
    2824 _In_reads_or_z_(end) const T* text,
    -
    2825 _In_ size_t start = 0,
    -
    2826 _In_ size_t end = (size_t)-1,
    -
    2827 _In_ int flags = match_default)
    -
    2828 {
    -
    2829 _Assume_(text || start >= end);
    -
    2830 if (start < end && text[start]) {
    -
    2831 if (('A' <= text[start] && text[start] <= 'Z') ||
    -
    2832 ('a' <= text[start] && text[start] <= 'z') ||
    -
    2833 ('0' <= text[start] && text[start] <= '9'))
    -
    2834 allow_on_edge = true;
    -
    2835 else if (text[start] == '-')
    -
    2836 allow_on_edge = false;
    -
    2837 else if (m_allow_idn && std::use_facet<std::ctype<T>>(this->m_locale).is(std::ctype_base::alnum, text[start]))
    -
    2838 allow_on_edge = true;
    -
    2839 else {
    -
    2840 this->interval.start = (this->interval.end = start) + 1;
    -
    2841 return false;
    -
    2842 }
    -
    2843 this->interval.end = (this->interval.start = start) + 1;
    -
    2844 return true;
    -
    2845 }
    -
    2846 this->interval.start = (this->interval.end = start) + 1;
    -
    2847 return false;
    -
    2848 }
    +
    2795
    + + +
    2798#ifdef _UNICODE
    + +
    2800#else
    + +
    2802#endif
    + +
    2804
    +
    2808 template <class T>
    +
    + +
    2810 {
    +
    2811 public:
    + +
    2813 _In_ bool allow_idn,
    +
    2814 _In_ const std::locale& locale = std::locale()) :
    +
    2815 basic_parser<T>(locale),
    +
    2816 m_allow_idn(allow_idn),
    +
    2817 allow_on_edge(true)
    +
    2818 {}
    +
    2819
    +
    2820 virtual bool match(
    +
    2821 _In_reads_or_z_(end) const T* text,
    +
    2822 _In_ size_t start = 0,
    +
    2823 _In_ size_t end = (size_t)-1,
    +
    2824 _In_ int flags = match_default)
    +
    2825 {
    +
    2826 _Assume_(text || start >= end);
    +
    2827 if (start < end && text[start]) {
    +
    2828 if (('A' <= text[start] && text[start] <= 'Z') ||
    +
    2829 ('a' <= text[start] && text[start] <= 'z') ||
    +
    2830 ('0' <= text[start] && text[start] <= '9'))
    +
    2831 allow_on_edge = true;
    +
    2832 else if (text[start] == '-')
    +
    2833 allow_on_edge = false;
    +
    2834 else if (m_allow_idn && std::use_facet<std::ctype<T>>(this->m_locale).is(std::ctype_base::alnum, text[start]))
    +
    2835 allow_on_edge = true;
    +
    2836 else {
    +
    2837 this->interval.start = (this->interval.end = start) + 1;
    +
    2838 return false;
    +
    2839 }
    +
    2840 this->interval.end = (this->interval.start = start) + 1;
    +
    2841 return true;
    +
    2842 }
    +
    2843 this->interval.start = (this->interval.end = start) + 1;
    +
    2844 return false;
    +
    2845 }
    +
    2846
    +
    2847 public:
    +
    2849
    -
    2850 public:
    - -
    2852
    -
    2853 protected:
    -
    2854 bool m_allow_idn;
    -
    2855 };
    +
    2850 protected:
    +
    2851 bool m_allow_idn;
    +
    2852 };
    -
    2856
    - - -
    2859#ifdef _UNICODE
    - -
    2861#else
    - -
    2863#endif
    -
    2864
    -
    - -
    2869 {
    -
    2870 public:
    - -
    2872 _In_ bool allow_idn,
    -
    2873 _In_ const std::locale& locale = std::locale()) :
    - -
    2875 {}
    -
    2876
    -
    2877 virtual bool match(
    -
    2878 _In_reads_or_z_(end) const char* text,
    -
    2879 _In_ size_t start = 0,
    -
    2880 _In_ size_t end = (size_t)-1,
    -
    2881 _In_ int flags = match_default)
    -
    2882 {
    -
    2883 _Assume_(text || start >= end);
    -
    2884 if (start < end && text[start]) {
    -
    2885 wchar_t buf[3];
    -
    2886 const wchar_t* chr = next_sgml_cp(text, start, end, this->interval.end, buf);
    -
    2887 const wchar_t* chr_end = chr + stdex::strlen(chr);
    -
    2888 if ((('A' <= chr[0] && chr[0] <= 'Z') ||
    -
    2889 ('a' <= chr[0] && chr[0] <= 'z') ||
    -
    2890 ('0' <= chr[0] && chr[0] <= '9')) && chr[1] == 0)
    -
    2891 allow_on_edge = true;
    -
    2892 else if (chr[0] == '-' && chr[1] == 0)
    -
    2893 allow_on_edge = false;
    -
    2894 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)
    -
    2895 allow_on_edge = true;
    -
    2896 else {
    -
    2897 this->interval.start = (this->interval.end = start) + 1;
    -
    2898 return false;
    -
    2899 }
    -
    2900 this->interval.start = start;
    -
    2901 return true;
    -
    2902 }
    -
    2903 this->interval.start = (this->interval.end = start) + 1;
    -
    2904 return false;
    -
    2905 }
    -
    2906 };
    +
    2853
    + + +
    2856#ifdef _UNICODE
    + +
    2858#else
    + +
    2860#endif
    +
    2861
    +
    + +
    2866 {
    +
    2867 public:
    + +
    2869 _In_ bool allow_idn,
    +
    2870 _In_ const std::locale& locale = std::locale()) :
    + +
    2872 {}
    +
    2873
    +
    2874 virtual bool match(
    +
    2875 _In_reads_or_z_(end) const char* text,
    +
    2876 _In_ size_t start = 0,
    +
    2877 _In_ size_t end = (size_t)-1,
    +
    2878 _In_ int flags = match_default)
    +
    2879 {
    +
    2880 _Assume_(text || start >= end);
    +
    2881 if (start < end && text[start]) {
    +
    2882 wchar_t buf[3];
    +
    2883 const wchar_t* chr = next_sgml_cp(text, start, end, this->interval.end, buf);
    +
    2884 const wchar_t* chr_end = chr + stdex::strlen(chr);
    +
    2885 if ((('A' <= chr[0] && chr[0] <= 'Z') ||
    +
    2886 ('a' <= chr[0] && chr[0] <= 'z') ||
    +
    2887 ('0' <= chr[0] && chr[0] <= '9')) && chr[1] == 0)
    +
    2888 allow_on_edge = true;
    +
    2889 else if (chr[0] == '-' && chr[1] == 0)
    +
    2890 allow_on_edge = false;
    +
    2891 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)
    +
    2892 allow_on_edge = true;
    +
    2893 else {
    +
    2894 this->interval.start = (this->interval.end = start) + 1;
    +
    2895 return false;
    +
    2896 }
    +
    2897 this->interval.start = start;
    +
    2898 return true;
    +
    2899 }
    +
    2900 this->interval.start = (this->interval.end = start) + 1;
    +
    2901 return false;
    +
    2902 }
    +
    2903 };
    -
    2907
    -
    2911 template <class T>
    -
    - -
    2913 {
    -
    2914 public:
    - -
    2916 _In_ bool allow_absolute,
    -
    2917 _In_ const std::shared_ptr<basic_dns_domain_char<T>>& domain_char,
    -
    2918 _In_ const std::shared_ptr<basic_parser<T>>& separator,
    -
    2919 _In_ const std::locale& locale = std::locale()) :
    -
    2920 basic_parser<T>(locale),
    - -
    2922 m_domain_char(domain_char),
    -
    2923 m_separator(separator)
    -
    2924 {}
    -
    2925
    -
    2926 virtual bool match(
    -
    2927 _In_reads_or_z_(end) const T* text,
    -
    2928 _In_ size_t start = 0,
    -
    2929 _In_ size_t end = (size_t)-1,
    -
    2930 _In_ int flags = match_default)
    -
    2931 {
    -
    2932 _Assume_(text || start >= end);
    -
    2933 size_t i = start, count;
    -
    2934 for (count = 0; i < end && text[i] && count < 127; count++) {
    -
    2935 if (m_domain_char->match(text, i, end, flags) &&
    -
    2936 m_domain_char->allow_on_edge)
    -
    2937 {
    -
    2938 // Domain start
    -
    2939 this->interval.end = i = m_domain_char->interval.end;
    -
    2940 while (i < end && text[i]) {
    -
    2941 if (m_domain_char->allow_on_edge &&
    -
    2942 m_separator->match(text, i, end, flags))
    -
    2943 {
    -
    2944 // Domain end
    -
    2945 if (m_allow_absolute)
    -
    2946 this->interval.end = i = m_separator->interval.end;
    -
    2947 else {
    -
    2948 this->interval.end = i;
    -
    2949 i = m_separator->interval.end;
    -
    2950 }
    -
    2951 break;
    -
    2952 }
    -
    2953 if (m_domain_char->match(text, i, end, flags)) {
    -
    2954 if (m_domain_char->allow_on_edge)
    -
    2955 this->interval.end = i = m_domain_char->interval.end;
    -
    2956 else
    -
    2957 i = m_domain_char->interval.end;
    -
    2958 }
    -
    2959 else {
    -
    2960 this->interval.start = start;
    -
    2961 return true;
    -
    2962 }
    -
    2963 }
    -
    2964 }
    -
    2965 else
    -
    2966 break;
    -
    2967 }
    -
    2968 if (count) {
    -
    2969 this->interval.start = start;
    -
    2970 return true;
    -
    2971 }
    -
    2972 this->interval.start = (this->interval.end = start) + 1;
    -
    2973 return false;
    -
    2974 }
    -
    2975
    -
    2976 protected:
    - -
    2978 std::shared_ptr<basic_dns_domain_char<T>> m_domain_char;
    -
    2979 std::shared_ptr<basic_parser<T>> m_separator;
    -
    2980 };
    +
    2904
    +
    2908 template <class T>
    +
    + +
    2910 {
    +
    2911 public:
    + +
    2913 _In_ bool allow_absolute,
    +
    2914 _In_ const std::shared_ptr<basic_dns_domain_char<T>>& domain_char,
    +
    2915 _In_ const std::shared_ptr<basic_parser<T>>& separator,
    +
    2916 _In_ const std::locale& locale = std::locale()) :
    +
    2917 basic_parser<T>(locale),
    + +
    2919 m_domain_char(domain_char),
    +
    2920 m_separator(separator)
    +
    2921 {}
    +
    2922
    +
    2923 virtual bool match(
    +
    2924 _In_reads_or_z_(end) const T* text,
    +
    2925 _In_ size_t start = 0,
    +
    2926 _In_ size_t end = (size_t)-1,
    +
    2927 _In_ int flags = match_default)
    +
    2928 {
    +
    2929 _Assume_(text || start >= end);
    +
    2930 size_t i = start, count;
    +
    2931 for (count = 0; i < end && text[i] && count < 127; count++) {
    +
    2932 if (m_domain_char->match(text, i, end, flags) &&
    +
    2933 m_domain_char->allow_on_edge)
    +
    2934 {
    +
    2935 // Domain start
    +
    2936 this->interval.end = i = m_domain_char->interval.end;
    +
    2937 while (i < end && text[i]) {
    +
    2938 if (m_domain_char->allow_on_edge &&
    +
    2939 m_separator->match(text, i, end, flags))
    +
    2940 {
    +
    2941 // Domain end
    +
    2942 if (m_allow_absolute)
    +
    2943 this->interval.end = i = m_separator->interval.end;
    +
    2944 else {
    +
    2945 this->interval.end = i;
    +
    2946 i = m_separator->interval.end;
    +
    2947 }
    +
    2948 break;
    +
    2949 }
    +
    2950 if (m_domain_char->match(text, i, end, flags)) {
    +
    2951 if (m_domain_char->allow_on_edge)
    +
    2952 this->interval.end = i = m_domain_char->interval.end;
    +
    2953 else
    +
    2954 i = m_domain_char->interval.end;
    +
    2955 }
    +
    2956 else {
    +
    2957 this->interval.start = start;
    +
    2958 return true;
    +
    2959 }
    +
    2960 }
    +
    2961 }
    +
    2962 else
    +
    2963 break;
    +
    2964 }
    +
    2965 if (count) {
    +
    2966 this->interval.start = start;
    +
    2967 return true;
    +
    2968 }
    +
    2969 this->interval.start = (this->interval.end = start) + 1;
    +
    2970 return false;
    +
    2971 }
    +
    2972
    +
    2973 protected:
    + +
    2975 std::shared_ptr<basic_dns_domain_char<T>> m_domain_char;
    +
    2976 std::shared_ptr<basic_parser<T>> m_separator;
    +
    2977 };
    -
    2981
    - - -
    2984#ifdef _UNICODE
    -
    2985 using tdns_name = wdns_name;
    -
    2986#else
    -
    2987 using tdns_name = dns_name;
    -
    2988#endif
    - -
    2990
    -
    2994 template <class T>
    -
    - -
    2996 {
    -
    2997 public:
    -
    2998 basic_url_username_char(_In_ const std::locale& locale = std::locale()) : basic_parser<T>(locale) {}
    -
    2999
    -
    3000 virtual bool match(
    -
    3001 _In_reads_or_z_(end) const T* text,
    -
    3002 _In_ size_t start = 0,
    -
    3003 _In_ size_t end = (size_t)-1,
    -
    3004 _In_ int flags = match_default)
    -
    3005 {
    -
    3006 _Assume_(text || start >= end);
    -
    3007 if (start < end && text[start]) {
    -
    3008 if (text[start] == '-' ||
    -
    3009 text[start] == '.' ||
    -
    3010 text[start] == '_' ||
    -
    3011 text[start] == '~' ||
    -
    3012 text[start] == '%' ||
    -
    3013 text[start] == '!' ||
    -
    3014 text[start] == '$' ||
    -
    3015 text[start] == '&' ||
    -
    3016 text[start] == '\'' ||
    -
    3017 //text[start] == '(' ||
    -
    3018 //text[start] == ')' ||
    -
    3019 text[start] == '*' ||
    -
    3020 text[start] == '+' ||
    -
    3021 text[start] == ',' ||
    -
    3022 text[start] == ';' ||
    -
    3023 text[start] == '=' ||
    -
    3024 std::use_facet<std::ctype<T>>(this->m_locale).is(std::ctype_base::alnum, text[start]))
    -
    3025 {
    -
    3026 this->interval.end = (this->interval.start = start) + 1;
    -
    3027 return true;
    -
    3028 }
    -
    3029 }
    -
    3030 this->interval.start = (this->interval.end = start) + 1;
    -
    3031 return false;
    -
    3032 }
    -
    3033 };
    +
    2978
    + + +
    2981#ifdef _UNICODE
    +
    2982 using tdns_name = wdns_name;
    +
    2983#else
    +
    2984 using tdns_name = dns_name;
    +
    2985#endif
    + +
    2987
    +
    2991 template <class T>
    +
    + +
    2993 {
    +
    2994 public:
    +
    2995 basic_url_username_char(_In_ const std::locale& locale = std::locale()) : basic_parser<T>(locale) {}
    +
    2996
    +
    2997 virtual bool match(
    +
    2998 _In_reads_or_z_(end) const T* text,
    +
    2999 _In_ size_t start = 0,
    +
    3000 _In_ size_t end = (size_t)-1,
    +
    3001 _In_ int flags = match_default)
    +
    3002 {
    +
    3003 _Assume_(text || start >= end);
    +
    3004 if (start < end && text[start]) {
    +
    3005 if (text[start] == '-' ||
    +
    3006 text[start] == '.' ||
    +
    3007 text[start] == '_' ||
    +
    3008 text[start] == '~' ||
    +
    3009 text[start] == '%' ||
    +
    3010 text[start] == '!' ||
    +
    3011 text[start] == '$' ||
    +
    3012 text[start] == '&' ||
    +
    3013 text[start] == '\'' ||
    +
    3014 //text[start] == '(' ||
    +
    3015 //text[start] == ')' ||
    +
    3016 text[start] == '*' ||
    +
    3017 text[start] == '+' ||
    +
    3018 text[start] == ',' ||
    +
    3019 text[start] == ';' ||
    +
    3020 text[start] == '=' ||
    +
    3021 std::use_facet<std::ctype<T>>(this->m_locale).is(std::ctype_base::alnum, text[start]))
    +
    3022 {
    +
    3023 this->interval.end = (this->interval.start = start) + 1;
    +
    3024 return true;
    +
    3025 }
    +
    3026 }
    +
    3027 this->interval.start = (this->interval.end = start) + 1;
    +
    3028 return false;
    +
    3029 }
    +
    3030 };
    -
    3034
    - - -
    3037#ifdef _UNICODE
    - -
    3039#else
    - -
    3041#endif
    -
    3042
    -
    - -
    3047 {
    -
    3048 public:
    -
    3049 sgml_url_username_char(_In_ const std::locale& locale = std::locale()) : basic_url_username_char<char>(locale) {}
    -
    3050
    -
    3051 virtual bool match(
    -
    3052 _In_reads_or_z_(end) const char* text,
    -
    3053 _In_ size_t start = 0,
    -
    3054 _In_ size_t end = (size_t)-1,
    -
    3055 _In_ int flags = match_default)
    -
    3056 {
    -
    3057 _Assume_(text || start >= end);
    -
    3058 if (start < end && text[start]) {
    -
    3059 wchar_t buf[3];
    -
    3060 const wchar_t* chr = next_sgml_cp(text, start, end, this->interval.end, buf);
    -
    3061 const wchar_t* chr_end = chr + stdex::strlen(chr);
    -
    3062 if (((chr[0] == L'-' ||
    -
    3063 chr[0] == L'.' ||
    -
    3064 chr[0] == L'_' ||
    -
    3065 chr[0] == L'~' ||
    -
    3066 chr[0] == L'%' ||
    -
    3067 chr[0] == L'!' ||
    -
    3068 chr[0] == L'$' ||
    -
    3069 chr[0] == L'&' ||
    -
    3070 chr[0] == L'\'' ||
    -
    3071 //chr[0] == L'(' ||
    -
    3072 //chr[0] == L')' ||
    -
    3073 chr[0] == L'*' ||
    -
    3074 chr[0] == L'+' ||
    -
    3075 chr[0] == L',' ||
    -
    3076 chr[0] == L';' ||
    -
    3077 chr[0] == L'=') && chr[1] == 0) ||
    -
    3078 std::use_facet<std::ctype<wchar_t>>(m_locale).scan_not(std::ctype_base::alnum, chr, chr_end) == chr_end)
    -
    3079 {
    -
    3080 this->interval.start = start;
    -
    3081 return true;
    -
    3082 }
    -
    3083 }
    -
    3084
    -
    3085 this->interval.start = (this->interval.end = start) + 1;
    -
    3086 return false;
    -
    3087 }
    -
    3088 };
    +
    3031
    + + +
    3034#ifdef _UNICODE
    + +
    3036#else
    + +
    3038#endif
    +
    3039
    +
    + +
    3044 {
    +
    3045 public:
    +
    3046 sgml_url_username_char(_In_ const std::locale& locale = std::locale()) : basic_url_username_char<char>(locale) {}
    +
    3047
    +
    3048 virtual bool match(
    +
    3049 _In_reads_or_z_(end) const char* text,
    +
    3050 _In_ size_t start = 0,
    +
    3051 _In_ size_t end = (size_t)-1,
    +
    3052 _In_ int flags = match_default)
    +
    3053 {
    +
    3054 _Assume_(text || start >= end);
    +
    3055 if (start < end && text[start]) {
    +
    3056 wchar_t buf[3];
    +
    3057 const wchar_t* chr = next_sgml_cp(text, start, end, this->interval.end, buf);
    +
    3058 const wchar_t* chr_end = chr + stdex::strlen(chr);
    +
    3059 if (((chr[0] == L'-' ||
    +
    3060 chr[0] == L'.' ||
    +
    3061 chr[0] == L'_' ||
    +
    3062 chr[0] == L'~' ||
    +
    3063 chr[0] == L'%' ||
    +
    3064 chr[0] == L'!' ||
    +
    3065 chr[0] == L'$' ||
    +
    3066 chr[0] == L'&' ||
    +
    3067 chr[0] == L'\'' ||
    +
    3068 //chr[0] == L'(' ||
    +
    3069 //chr[0] == L')' ||
    +
    3070 chr[0] == L'*' ||
    +
    3071 chr[0] == L'+' ||
    +
    3072 chr[0] == L',' ||
    +
    3073 chr[0] == L';' ||
    +
    3074 chr[0] == L'=') && chr[1] == 0) ||
    +
    3075 std::use_facet<std::ctype<wchar_t>>(m_locale).scan_not(std::ctype_base::alnum, chr, chr_end) == chr_end)
    +
    3076 {
    +
    3077 this->interval.start = start;
    +
    3078 return true;
    +
    3079 }
    +
    3080 }
    +
    3081
    +
    3082 this->interval.start = (this->interval.end = start) + 1;
    +
    3083 return false;
    +
    3084 }
    +
    3085 };
    -
    3089
    -
    3093 template <class T>
    -
    - -
    3095 {
    -
    3096 public:
    -
    3097 basic_url_password_char(_In_ const std::locale& locale = std::locale()) : basic_parser<T>(locale) {}
    -
    3098
    -
    3099 virtual bool match(
    -
    3100 _In_reads_or_z_(end) const T* text,
    -
    3101 _In_ size_t start = 0,
    -
    3102 _In_ size_t end = (size_t)-1,
    -
    3103 _In_ int flags = match_default)
    -
    3104 {
    -
    3105 _Assume_(text || start >= end);
    -
    3106 if (start < end && text[start]) {
    -
    3107 if (text[start] == '-' ||
    -
    3108 text[start] == '.' ||
    -
    3109 text[start] == '_' ||
    -
    3110 text[start] == '~' ||
    -
    3111 text[start] == '%' ||
    -
    3112 text[start] == '!' ||
    -
    3113 text[start] == '$' ||
    -
    3114 text[start] == '&' ||
    -
    3115 text[start] == '\'' ||
    -
    3116 text[start] == '(' ||
    -
    3117 text[start] == ')' ||
    -
    3118 text[start] == '*' ||
    -
    3119 text[start] == '+' ||
    -
    3120 text[start] == ',' ||
    -
    3121 text[start] == ';' ||
    -
    3122 text[start] == '=' ||
    -
    3123 text[start] == ':' ||
    -
    3124 std::use_facet<std::ctype<T>>(this->m_locale).is(std::ctype_base::alnum, text[start]))
    -
    3125 {
    -
    3126 this->interval.end = (this->interval.start = start) + 1;
    -
    3127 return true;
    -
    3128 }
    -
    3129 }
    -
    3130 this->interval.start = (this->interval.end = start) + 1;
    -
    3131 return false;
    -
    3132 }
    -
    3133 };
    +
    3086
    +
    3090 template <class T>
    +
    + +
    3092 {
    +
    3093 public:
    +
    3094 basic_url_password_char(_In_ const std::locale& locale = std::locale()) : basic_parser<T>(locale) {}
    +
    3095
    +
    3096 virtual bool match(
    +
    3097 _In_reads_or_z_(end) const T* text,
    +
    3098 _In_ size_t start = 0,
    +
    3099 _In_ size_t end = (size_t)-1,
    +
    3100 _In_ int flags = match_default)
    +
    3101 {
    +
    3102 _Assume_(text || start >= end);
    +
    3103 if (start < end && text[start]) {
    +
    3104 if (text[start] == '-' ||
    +
    3105 text[start] == '.' ||
    +
    3106 text[start] == '_' ||
    +
    3107 text[start] == '~' ||
    +
    3108 text[start] == '%' ||
    +
    3109 text[start] == '!' ||
    +
    3110 text[start] == '$' ||
    +
    3111 text[start] == '&' ||
    +
    3112 text[start] == '\'' ||
    +
    3113 text[start] == '(' ||
    +
    3114 text[start] == ')' ||
    +
    3115 text[start] == '*' ||
    +
    3116 text[start] == '+' ||
    +
    3117 text[start] == ',' ||
    +
    3118 text[start] == ';' ||
    +
    3119 text[start] == '=' ||
    +
    3120 text[start] == ':' ||
    +
    3121 std::use_facet<std::ctype<T>>(this->m_locale).is(std::ctype_base::alnum, text[start]))
    +
    3122 {
    +
    3123 this->interval.end = (this->interval.start = start) + 1;
    +
    3124 return true;
    +
    3125 }
    +
    3126 }
    +
    3127 this->interval.start = (this->interval.end = start) + 1;
    +
    3128 return false;
    +
    3129 }
    +
    3130 };
    -
    3134
    - - -
    3137#ifdef _UNICODE
    - -
    3139#else
    - -
    3141#endif
    -
    3142
    -
    - -
    3147 {
    -
    3148 public:
    -
    3149 sgml_url_password_char(_In_ const std::locale& locale = std::locale()) : basic_url_password_char<char>(locale) {}
    -
    3150
    -
    3151 virtual bool match(
    -
    3152 _In_reads_or_z_(end) const char* text,
    -
    3153 _In_ size_t start = 0,
    -
    3154 _In_ size_t end = (size_t)-1,
    -
    3155 _In_ int flags = match_default)
    -
    3156 {
    -
    3157 _Assume_(text || start >= end);
    -
    3158 if (start < end && text[start]) {
    -
    3159 wchar_t buf[3];
    -
    3160 const wchar_t* chr = next_sgml_cp(text, start, end, this->interval.end, buf);
    -
    3161 const wchar_t* chr_end = chr + stdex::strlen(chr);
    -
    3162 if (((chr[0] == L'-' ||
    -
    3163 chr[0] == L'.' ||
    -
    3164 chr[0] == L'_' ||
    -
    3165 chr[0] == L'~' ||
    -
    3166 chr[0] == L'%' ||
    -
    3167 chr[0] == L'!' ||
    -
    3168 chr[0] == L'$' ||
    -
    3169 chr[0] == L'&' ||
    -
    3170 chr[0] == L'\'' ||
    -
    3171 chr[0] == L'(' ||
    -
    3172 chr[0] == L')' ||
    -
    3173 chr[0] == L'*' ||
    -
    3174 chr[0] == L'+' ||
    -
    3175 chr[0] == L',' ||
    -
    3176 chr[0] == L';' ||
    -
    3177 chr[0] == L'=' ||
    -
    3178 chr[0] == L':') && chr[1] == 0) ||
    -
    3179 std::use_facet<std::ctype<wchar_t>>(m_locale).scan_not(std::ctype_base::alnum, chr, chr_end) == chr_end)
    -
    3180 {
    -
    3181 this->interval.start = start;
    -
    3182 return true;
    -
    3183 }
    -
    3184 }
    -
    3185 this->interval.start = (this->interval.end = start) + 1;
    -
    3186 return false;
    -
    3187 }
    -
    3188 };
    +
    3131
    + + +
    3134#ifdef _UNICODE
    + +
    3136#else
    + +
    3138#endif
    +
    3139
    +
    + +
    3144 {
    +
    3145 public:
    +
    3146 sgml_url_password_char(_In_ const std::locale& locale = std::locale()) : basic_url_password_char<char>(locale) {}
    +
    3147
    +
    3148 virtual bool match(
    +
    3149 _In_reads_or_z_(end) const char* text,
    +
    3150 _In_ size_t start = 0,
    +
    3151 _In_ size_t end = (size_t)-1,
    +
    3152 _In_ int flags = match_default)
    +
    3153 {
    +
    3154 _Assume_(text || start >= end);
    +
    3155 if (start < end && text[start]) {
    +
    3156 wchar_t buf[3];
    +
    3157 const wchar_t* chr = next_sgml_cp(text, start, end, this->interval.end, buf);
    +
    3158 const wchar_t* chr_end = chr + stdex::strlen(chr);
    +
    3159 if (((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'$' ||
    +
    3166 chr[0] == L'&' ||
    +
    3167 chr[0] == L'\'' ||
    +
    3168 chr[0] == L'(' ||
    +
    3169 chr[0] == L')' ||
    +
    3170 chr[0] == L'*' ||
    +
    3171 chr[0] == L'+' ||
    +
    3172 chr[0] == L',' ||
    +
    3173 chr[0] == L';' ||
    +
    3174 chr[0] == L'=' ||
    +
    3175 chr[0] == L':') && chr[1] == 0) ||
    +
    3176 std::use_facet<std::ctype<wchar_t>>(m_locale).scan_not(std::ctype_base::alnum, chr, chr_end) == chr_end)
    +
    3177 {
    +
    3178 this->interval.start = start;
    +
    3179 return true;
    +
    3180 }
    +
    3181 }
    +
    3182 this->interval.start = (this->interval.end = start) + 1;
    +
    3183 return false;
    +
    3184 }
    +
    3185 };
    -
    3189
    -
    3193 template <class T>
    -
    - -
    3195 {
    -
    3196 public:
    -
    3197 basic_url_path_char(_In_ const std::locale& locale = std::locale()) : basic_parser<T>(locale) {}
    -
    3198
    -
    3199 virtual bool match(
    -
    3200 _In_reads_or_z_(end) const T* text,
    -
    3201 _In_ size_t start = 0,
    -
    3202 _In_ size_t end = (size_t)-1,
    -
    3203 _In_ int flags = match_default)
    -
    3204 {
    -
    3205 _Assume_(text || start >= end);
    -
    3206 if (start < end && text[start]) {
    -
    3207 if (text[start] == '/' ||
    -
    3208 text[start] == '-' ||
    -
    3209 text[start] == '.' ||
    -
    3210 text[start] == '_' ||
    -
    3211 text[start] == '~' ||
    -
    3212 text[start] == '%' ||
    -
    3213 text[start] == '!' ||
    -
    3214 text[start] == '$' ||
    -
    3215 text[start] == '&' ||
    -
    3216 text[start] == '\'' ||
    -
    3217 text[start] == '(' ||
    -
    3218 text[start] == ')' ||
    -
    3219 text[start] == '*' ||
    -
    3220 text[start] == '+' ||
    -
    3221 text[start] == ',' ||
    -
    3222 text[start] == ';' ||
    -
    3223 text[start] == '=' ||
    -
    3224 text[start] == ':' ||
    -
    3225 text[start] == '@' ||
    -
    3226 text[start] == '?' ||
    -
    3227 text[start] == '#' ||
    -
    3228 std::use_facet<std::ctype<T>>(this->m_locale).is(std::ctype_base::alnum, text[start]))
    -
    3229 {
    -
    3230 this->interval.end = (this->interval.start = start) + 1;
    -
    3231 return true;
    -
    3232 }
    -
    3233 }
    -
    3234 this->interval.start = (this->interval.end = start) + 1;
    -
    3235 return false;
    -
    3236 }
    -
    3237 };
    +
    3186
    +
    3190 template <class T>
    +
    + +
    3192 {
    +
    3193 public:
    +
    3194 basic_url_path_char(_In_ const std::locale& locale = std::locale()) : basic_parser<T>(locale) {}
    +
    3195
    +
    3196 virtual bool match(
    +
    3197 _In_reads_or_z_(end) const T* text,
    +
    3198 _In_ size_t start = 0,
    +
    3199 _In_ size_t end = (size_t)-1,
    +
    3200 _In_ int flags = match_default)
    +
    3201 {
    +
    3202 _Assume_(text || start >= end);
    +
    3203 if (start < end && text[start]) {
    +
    3204 if (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 text[start] == ')' ||
    +
    3216 text[start] == '*' ||
    +
    3217 text[start] == '+' ||
    +
    3218 text[start] == ',' ||
    +
    3219 text[start] == ';' ||
    +
    3220 text[start] == '=' ||
    +
    3221 text[start] == ':' ||
    +
    3222 text[start] == '@' ||
    +
    3223 text[start] == '?' ||
    +
    3224 text[start] == '#' ||
    +
    3225 std::use_facet<std::ctype<T>>(this->m_locale).is(std::ctype_base::alnum, text[start]))
    +
    3226 {
    +
    3227 this->interval.end = (this->interval.start = start) + 1;
    +
    3228 return true;
    +
    3229 }
    +
    3230 }
    +
    3231 this->interval.start = (this->interval.end = start) + 1;
    +
    3232 return false;
    +
    3233 }
    +
    3234 };
    -
    3238
    - - -
    3241#ifdef _UNICODE
    - -
    3243#else
    - -
    3245#endif
    -
    3246
    -
    - -
    3251 {
    -
    3252 public:
    -
    3253 sgml_url_path_char(_In_ const std::locale& locale = std::locale()) : basic_url_path_char<char>(locale) {}
    -
    3254
    -
    3255 virtual bool match(
    -
    3256 _In_reads_or_z_(end) const char* text,
    -
    3257 _In_ size_t start = 0,
    -
    3258 _In_ size_t end = (size_t)-1,
    -
    3259 _In_ int flags = match_default)
    -
    3260 {
    -
    3261 _Assume_(text || start >= end);
    -
    3262 if (start < end && text[start]) {
    -
    3263 wchar_t buf[3];
    -
    3264 const wchar_t* chr = next_sgml_cp(text, start, end, this->interval.end, buf);
    -
    3265 const wchar_t* chr_end = chr + stdex::strlen(chr);
    -
    3266 if (((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'$' ||
    -
    3274 chr[0] == L'&' ||
    -
    3275 chr[0] == L'\'' ||
    -
    3276 chr[0] == L'(' ||
    -
    3277 chr[0] == L')' ||
    -
    3278 chr[0] == L'*' ||
    -
    3279 chr[0] == L'+' ||
    -
    3280 chr[0] == L',' ||
    -
    3281 chr[0] == L';' ||
    -
    3282 chr[0] == L'=' ||
    -
    3283 chr[0] == L':' ||
    -
    3284 chr[0] == L'@' ||
    -
    3285 chr[0] == L'?' ||
    -
    3286 chr[0] == L'#') && chr[1] == 0) ||
    -
    3287 std::use_facet<std::ctype<wchar_t>>(m_locale).scan_not(std::ctype_base::alnum, chr, chr_end) == chr_end)
    -
    3288 {
    -
    3289 this->interval.start = start;
    -
    3290 return true;
    -
    3291 }
    -
    3292 }
    -
    3293 this->interval.start = (this->interval.end = start) + 1;
    -
    3294 return false;
    -
    3295 }
    -
    3296 };
    +
    3235
    + + +
    3238#ifdef _UNICODE
    + +
    3240#else
    + +
    3242#endif
    +
    3243
    +
    + +
    3248 {
    +
    3249 public:
    +
    3250 sgml_url_path_char(_In_ const std::locale& locale = std::locale()) : basic_url_path_char<char>(locale) {}
    +
    3251
    +
    3252 virtual bool match(
    +
    3253 _In_reads_or_z_(end) const char* text,
    +
    3254 _In_ size_t start = 0,
    +
    3255 _In_ size_t end = (size_t)-1,
    +
    3256 _In_ int flags = match_default)
    +
    3257 {
    +
    3258 _Assume_(text || start >= end);
    +
    3259 if (start < end && text[start]) {
    +
    3260 wchar_t buf[3];
    +
    3261 const wchar_t* chr = next_sgml_cp(text, start, end, this->interval.end, buf);
    +
    3262 const wchar_t* chr_end = chr + stdex::strlen(chr);
    +
    3263 if (((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'(' ||
    +
    3274 chr[0] == L')' ||
    +
    3275 chr[0] == L'*' ||
    +
    3276 chr[0] == L'+' ||
    +
    3277 chr[0] == L',' ||
    +
    3278 chr[0] == L';' ||
    +
    3279 chr[0] == L'=' ||
    +
    3280 chr[0] == L':' ||
    +
    3281 chr[0] == L'@' ||
    +
    3282 chr[0] == L'?' ||
    +
    3283 chr[0] == L'#') && chr[1] == 0) ||
    +
    3284 std::use_facet<std::ctype<wchar_t>>(m_locale).scan_not(std::ctype_base::alnum, chr, chr_end) == chr_end)
    +
    3285 {
    +
    3286 this->interval.start = start;
    +
    3287 return true;
    +
    3288 }
    +
    3289 }
    +
    3290 this->interval.start = (this->interval.end = start) + 1;
    +
    3291 return false;
    +
    3292 }
    +
    3293 };
    -
    3297
    -
    3301 template <class T>
    -
    - -
    3303 {
    -
    3304 public:
    - -
    3306 _In_ const std::shared_ptr<basic_parser<T>>& path_char,
    -
    3307 _In_ const std::shared_ptr<basic_parser<T>>& query_start,
    -
    3308 _In_ const std::shared_ptr<basic_parser<T>>& bookmark_start,
    -
    3309 _In_ const std::locale& locale = std::locale()) :
    -
    3310 basic_parser<T>(locale),
    -
    3311 m_path_char(path_char),
    -
    3312 m_query_start(query_start),
    -
    3313 m_bookmark_start(bookmark_start)
    -
    3314 {}
    -
    3315
    -
    3316 virtual bool match(
    -
    3317 _In_reads_or_z_(end) const T* text,
    -
    3318 _In_ size_t start = 0,
    -
    3319 _In_ size_t end = (size_t)-1,
    -
    3320 _In_ int flags = match_default)
    -
    3321 {
    -
    3322 _Assume_(text || start >= end);
    -
    3323
    -
    3324 this->interval.end = start;
    -
    3325 path.start = start;
    -
    3326 query.start = 1;
    -
    3327 query.end = 0;
    -
    3328 bookmark.start = 1;
    -
    3329 bookmark.end = 0;
    -
    3330
    -
    3331 for (;;) {
    -
    3332 if (this->interval.end >= end || !text[this->interval.end])
    -
    3333 break;
    -
    3334 if (m_query_start->match(text, this->interval.end, end, flags)) {
    -
    3335 path.end = this->interval.end;
    -
    3336 query.start = this->interval.end = m_query_start->interval.end;
    -
    3337 for (;;) {
    -
    3338 if (this->interval.end >= end || !text[this->interval.end]) {
    -
    3339 query.end = this->interval.end;
    -
    3340 break;
    -
    3341 }
    -
    3342 if (m_bookmark_start->match(text, this->interval.end, end, flags)) {
    -
    3343 query.end = this->interval.end;
    -
    3344 bookmark.start = this->interval.end = m_bookmark_start->interval.end;
    -
    3345 for (;;) {
    -
    3346 if (this->interval.end >= end || !text[this->interval.end]) {
    -
    3347 bookmark.end = this->interval.end;
    -
    3348 break;
    -
    3349 }
    -
    3350 if (m_path_char->match(text, this->interval.end, end, flags))
    -
    3351 this->interval.end = m_path_char->interval.end;
    -
    3352 else {
    -
    3353 bookmark.end = this->interval.end;
    -
    3354 break;
    -
    3355 }
    -
    3356 }
    -
    3357 this->interval.start = start;
    -
    3358 return true;
    -
    3359 }
    -
    3360 if (m_path_char->match(text, this->interval.end, end, flags))
    -
    3361 this->interval.end = m_path_char->interval.end;
    -
    3362 else {
    -
    3363 query.end = this->interval.end;
    -
    3364 break;
    -
    3365 }
    -
    3366 }
    -
    3367 this->interval.start = start;
    -
    3368 return true;
    -
    3369 }
    -
    3370 if (m_bookmark_start->match(text, this->interval.end, end, flags)) {
    -
    3371 path.end = this->interval.end;
    -
    3372 bookmark.start = this->interval.end = m_bookmark_start->interval.end;
    -
    3373 for (;;) {
    -
    3374 if (this->interval.end >= end || !text[this->interval.end]) {
    -
    3375 bookmark.end = this->interval.end;
    -
    3376 break;
    -
    3377 }
    -
    3378 if (m_path_char->match(text, this->interval.end, end, flags))
    -
    3379 this->interval.end = m_path_char->interval.end;
    -
    3380 else {
    -
    3381 bookmark.end = this->interval.end;
    -
    3382 break;
    -
    3383 }
    -
    3384 }
    -
    3385 this->interval.start = start;
    -
    3386 return true;
    -
    3387 }
    -
    3388 if (m_path_char->match(text, this->interval.end, end, flags))
    -
    3389 this->interval.end = m_path_char->interval.end;
    -
    3390 else
    -
    3391 break;
    -
    3392 }
    -
    3393
    - -
    3395 path.end = this->interval.end;
    -
    3396 this->interval.start = start;
    -
    3397 return true;
    -
    3398 }
    -
    3399
    -
    3400 path.start = 1;
    -
    3401 path.end = 0;
    -
    3402 bookmark.start = 1;
    -
    3403 bookmark.end = 0;
    -
    3404 this->interval.start = (this->interval.end = start) + 1;
    -
    3405 return false;
    -
    3406 }
    -
    3407
    -
    3408 virtual void invalidate()
    -
    3409 {
    -
    3410 path.start = 1;
    -
    3411 path.end = 0;
    -
    3412 query.start = 1;
    -
    3413 query.end = 0;
    -
    3414 bookmark.start = 1;
    -
    3415 bookmark.end = 0;
    - -
    3417 }
    -
    3418
    -
    3419 public:
    - - -
    3422 stdex::interval<size_t> bookmark;
    -
    3423
    -
    3424 protected:
    -
    3425 std::shared_ptr<basic_parser<T>> m_path_char;
    -
    3426 std::shared_ptr<basic_parser<T>> m_query_start;
    -
    3427 std::shared_ptr<basic_parser<T>> m_bookmark_start;
    -
    3428 };
    +
    3294
    +
    3298 template <class T>
    +
    + +
    3300 {
    +
    3301 public:
    + +
    3303 _In_ const std::shared_ptr<basic_parser<T>>& path_char,
    +
    3304 _In_ const std::shared_ptr<basic_parser<T>>& query_start,
    +
    3305 _In_ const std::shared_ptr<basic_parser<T>>& bookmark_start,
    +
    3306 _In_ const std::locale& locale = std::locale()) :
    +
    3307 basic_parser<T>(locale),
    +
    3308 m_path_char(path_char),
    +
    3309 m_query_start(query_start),
    +
    3310 m_bookmark_start(bookmark_start)
    +
    3311 {}
    +
    3312
    +
    3313 virtual bool match(
    +
    3314 _In_reads_or_z_(end) const T* text,
    +
    3315 _In_ size_t start = 0,
    +
    3316 _In_ size_t end = (size_t)-1,
    +
    3317 _In_ int flags = match_default)
    +
    3318 {
    +
    3319 _Assume_(text || start >= end);
    +
    3320
    +
    3321 this->interval.end = start;
    +
    3322 path.start = start;
    +
    3323 query.start = 1;
    +
    3324 query.end = 0;
    +
    3325 bookmark.start = 1;
    +
    3326 bookmark.end = 0;
    +
    3327
    +
    3328 for (;;) {
    +
    3329 if (this->interval.end >= end || !text[this->interval.end])
    +
    3330 break;
    +
    3331 if (m_query_start->match(text, this->interval.end, end, flags)) {
    +
    3332 path.end = this->interval.end;
    +
    3333 query.start = this->interval.end = m_query_start->interval.end;
    +
    3334 for (;;) {
    +
    3335 if (this->interval.end >= end || !text[this->interval.end]) {
    +
    3336 query.end = this->interval.end;
    +
    3337 break;
    +
    3338 }
    +
    3339 if (m_bookmark_start->match(text, this->interval.end, end, flags)) {
    +
    3340 query.end = this->interval.end;
    +
    3341 bookmark.start = this->interval.end = m_bookmark_start->interval.end;
    +
    3342 for (;;) {
    +
    3343 if (this->interval.end >= end || !text[this->interval.end]) {
    +
    3344 bookmark.end = this->interval.end;
    +
    3345 break;
    +
    3346 }
    +
    3347 if (m_path_char->match(text, this->interval.end, end, flags))
    +
    3348 this->interval.end = m_path_char->interval.end;
    +
    3349 else {
    +
    3350 bookmark.end = this->interval.end;
    +
    3351 break;
    +
    3352 }
    +
    3353 }
    +
    3354 this->interval.start = start;
    +
    3355 return true;
    +
    3356 }
    +
    3357 if (m_path_char->match(text, this->interval.end, end, flags))
    +
    3358 this->interval.end = m_path_char->interval.end;
    +
    3359 else {
    +
    3360 query.end = this->interval.end;
    +
    3361 break;
    +
    3362 }
    +
    3363 }
    +
    3364 this->interval.start = start;
    +
    3365 return true;
    +
    3366 }
    +
    3367 if (m_bookmark_start->match(text, this->interval.end, end, flags)) {
    +
    3368 path.end = this->interval.end;
    +
    3369 bookmark.start = this->interval.end = m_bookmark_start->interval.end;
    +
    3370 for (;;) {
    +
    3371 if (this->interval.end >= end || !text[this->interval.end]) {
    +
    3372 bookmark.end = this->interval.end;
    +
    3373 break;
    +
    3374 }
    +
    3375 if (m_path_char->match(text, this->interval.end, end, flags))
    +
    3376 this->interval.end = m_path_char->interval.end;
    +
    3377 else {
    +
    3378 bookmark.end = this->interval.end;
    +
    3379 break;
    +
    3380 }
    +
    3381 }
    +
    3382 this->interval.start = start;
    +
    3383 return true;
    +
    3384 }
    +
    3385 if (m_path_char->match(text, this->interval.end, end, flags))
    +
    3386 this->interval.end = m_path_char->interval.end;
    +
    3387 else
    +
    3388 break;
    +
    3389 }
    +
    3390
    + +
    3392 path.end = this->interval.end;
    +
    3393 this->interval.start = start;
    +
    3394 return true;
    +
    3395 }
    +
    3396
    +
    3397 path.start = 1;
    +
    3398 path.end = 0;
    +
    3399 bookmark.start = 1;
    +
    3400 bookmark.end = 0;
    +
    3401 this->interval.start = (this->interval.end = start) + 1;
    +
    3402 return false;
    +
    3403 }
    +
    3404
    +
    3405 virtual void invalidate()
    +
    3406 {
    +
    3407 path.start = 1;
    +
    3408 path.end = 0;
    +
    3409 query.start = 1;
    +
    3410 query.end = 0;
    +
    3411 bookmark.start = 1;
    +
    3412 bookmark.end = 0;
    + +
    3414 }
    +
    3415
    +
    3416 public:
    + + +
    3419 stdex::interval<size_t> bookmark;
    +
    3420
    +
    3421 protected:
    +
    3422 std::shared_ptr<basic_parser<T>> m_path_char;
    +
    3423 std::shared_ptr<basic_parser<T>> m_query_start;
    +
    3424 std::shared_ptr<basic_parser<T>> m_bookmark_start;
    +
    3425 };
    -
    3429
    - - -
    3432#ifdef _UNICODE
    -
    3433 using turl_path = wurl_path;
    -
    3434#else
    -
    3435 using turl_path = url_path;
    -
    3436#endif
    - -
    3438
    -
    3442 template <class T>
    -
    -
    3443 class basic_url : public basic_parser<T>
    -
    3444 {
    -
    3445 public:
    -
    3446 basic_url(
    -
    3447 _In_ const std::shared_ptr<basic_parser<T>>& _http_scheme,
    -
    3448 _In_ const std::shared_ptr<basic_parser<T>>& _ftp_scheme,
    -
    3449 _In_ const std::shared_ptr<basic_parser<T>>& _mailto_scheme,
    -
    3450 _In_ const std::shared_ptr<basic_parser<T>>& _file_scheme,
    -
    3451 _In_ const std::shared_ptr<basic_parser<T>>& colon,
    -
    3452 _In_ const std::shared_ptr<basic_parser<T>>& slash,
    -
    3453 _In_ const std::shared_ptr<basic_parser<T>>& _username,
    -
    3454 _In_ const std::shared_ptr<basic_parser<T>>& _password,
    -
    3455 _In_ const std::shared_ptr<basic_parser<T>>& at,
    -
    3456 _In_ const std::shared_ptr<basic_parser<T>>& ip_lbracket,
    -
    3457 _In_ const std::shared_ptr<basic_parser<T>>& ip_rbracket,
    -
    3458 _In_ const std::shared_ptr<basic_parser<T>>& _ipv4_host,
    -
    3459 _In_ const std::shared_ptr<basic_parser<T>>& _ipv6_host,
    -
    3460 _In_ const std::shared_ptr<basic_parser<T>>& _dns_host,
    -
    3461 _In_ const std::shared_ptr<basic_parser<T>>& _port,
    -
    3462 _In_ const std::shared_ptr<basic_parser<T>>& _path,
    -
    3463 _In_ const std::locale& locale = std::locale()) :
    -
    3464 basic_parser<T>(locale),
    -
    3465 http_scheme(_http_scheme),
    -
    3466 ftp_scheme(_ftp_scheme),
    -
    3467 mailto_scheme(_mailto_scheme),
    -
    3468 file_scheme(_file_scheme),
    -
    3469 m_colon(colon),
    -
    3470 m_slash(slash),
    -
    3471 username(_username),
    -
    3472 password(_password),
    -
    3473 m_at(at),
    -
    3474 m_ip_lbracket(ip_lbracket),
    -
    3475 m_ip_rbracket(ip_rbracket),
    -
    3476 ipv4_host(_ipv4_host),
    -
    3477 ipv6_host(_ipv6_host),
    -
    3478 dns_host(_dns_host),
    -
    3479 port(_port),
    -
    3480 path(_path)
    -
    3481 {}
    -
    3482
    -
    3483 virtual bool match(
    -
    3484 _In_reads_or_z_(end) const T* text,
    -
    3485 _In_ size_t start = 0,
    -
    3486 _In_ size_t end = (size_t)-1,
    -
    3487 _In_ int flags = match_default)
    -
    3488 {
    -
    3489 _Assume_(text || start >= end);
    -
    3490
    -
    3491 this->interval.end = start;
    -
    3492
    -
    3493 if (http_scheme->match(text, this->interval.end, end, flags) &&
    -
    3494 m_colon->match(text, http_scheme->interval.end, end, flags) &&
    -
    3495 m_slash->match(text, m_colon->interval.end, end, flags) &&
    -
    3496 m_slash->match(text, m_slash->interval.end, end, flags))
    -
    3497 {
    -
    3498 // http://
    -
    3499 this->interval.end = m_slash->interval.end;
    -
    3500 ftp_scheme->invalidate();
    -
    3501 mailto_scheme->invalidate();
    -
    3502 file_scheme->invalidate();
    -
    3503 }
    -
    3504 else if (ftp_scheme->match(text, this->interval.end, end, flags) &&
    -
    3505 m_colon->match(text, ftp_scheme->interval.end, end, flags) &&
    -
    3506 m_slash->match(text, m_colon->interval.end, end, flags) &&
    -
    3507 m_slash->match(text, m_slash->interval.end, end, flags))
    -
    3508 {
    -
    3509 // ftp://
    -
    3510 this->interval.end = m_slash->interval.end;
    -
    3511 http_scheme->invalidate();
    -
    3512 mailto_scheme->invalidate();
    -
    3513 file_scheme->invalidate();
    -
    3514 }
    -
    3515 else if (mailto_scheme->match(text, this->interval.end, end, flags) &&
    -
    3516 m_colon->match(text, mailto_scheme->interval.end, end, flags))
    -
    3517 {
    -
    3518 // mailto:
    -
    3519 this->interval.end = m_colon->interval.end;
    -
    3520 http_scheme->invalidate();
    -
    3521 ftp_scheme->invalidate();
    -
    3522 file_scheme->invalidate();
    -
    3523 }
    -
    3524 else if (file_scheme->match(text, this->interval.end, end, flags) &&
    -
    3525 m_colon->match(text, file_scheme->interval.end, end, flags) &&
    -
    3526 m_slash->match(text, m_colon->interval.end, end, flags) &&
    -
    3527 m_slash->match(text, m_slash->interval.end, end, flags))
    -
    3528 {
    -
    3529 // file://
    -
    3530 this->interval.end = m_slash->interval.end;
    -
    3531 http_scheme->invalidate();
    -
    3532 ftp_scheme->invalidate();
    -
    3533 mailto_scheme->invalidate();
    -
    3534 }
    -
    3535 else {
    -
    3536 // Default to http:
    -
    3537 http_scheme->invalidate();
    -
    3538 ftp_scheme->invalidate();
    -
    3539 mailto_scheme->invalidate();
    -
    3540 file_scheme->invalidate();
    -
    3541 }
    -
    3542
    -
    3543 if (ftp_scheme->interval) {
    -
    3544 if (username->match(text, this->interval.end, end, flags)) {
    -
    3545 if (m_colon->match(text, username->interval.end, end, flags) &&
    -
    3546 password->match(text, m_colon->interval.end, end, flags) &&
    -
    3547 m_at->match(text, password->interval.end, end, flags))
    -
    3548 {
    -
    3549 // Username and password
    -
    3550 this->interval.end = m_at->interval.end;
    -
    3551 }
    -
    3552 else if (m_at->match(text, this->interval.end, end, flags)) {
    -
    3553 // Username only
    -
    3554 this->interval.end = m_at->interval.end;
    -
    3555 password->invalidate();
    -
    3556 }
    -
    3557 else {
    -
    3558 username->invalidate();
    -
    3559 password->invalidate();
    -
    3560 }
    -
    3561 }
    -
    3562 else {
    -
    3563 username->invalidate();
    -
    3564 password->invalidate();
    -
    3565 }
    -
    3566
    -
    3567 if (ipv4_host->match(text, this->interval.end, end, flags)) {
    -
    3568 // Host is IPv4
    -
    3569 this->interval.end = ipv4_host->interval.end;
    -
    3570 ipv6_host->invalidate();
    -
    3571 dns_host->invalidate();
    -
    3572 }
    -
    3573 else if (
    -
    3574 m_ip_lbracket->match(text, this->interval.end, end, flags) &&
    -
    3575 ipv6_host->match(text, m_ip_lbracket->interval.end, end, flags) &&
    -
    3576 m_ip_rbracket->match(text, ipv6_host->interval.end, end, flags))
    -
    3577 {
    -
    3578 // Host is IPv6
    -
    3579 this->interval.end = m_ip_rbracket->interval.end;
    -
    3580 ipv4_host->invalidate();
    -
    3581 dns_host->invalidate();
    -
    3582 }
    -
    3583 else if (dns_host->match(text, this->interval.end, end, flags)) {
    -
    3584 // Host is hostname
    -
    3585 this->interval.end = dns_host->interval.end;
    -
    3586 ipv4_host->invalidate();
    -
    3587 ipv6_host->invalidate();
    -
    3588 }
    -
    3589 else {
    -
    3590 invalidate();
    -
    3591 return false;
    -
    3592 }
    -
    3593
    -
    3594 if (m_colon->match(text, this->interval.end, end, flags) &&
    -
    3595 port->match(text, m_colon->interval.end, end, flags))
    -
    3596 {
    -
    3597 // Port
    -
    3598 this->interval.end = port->interval.end;
    -
    3599 }
    -
    3600 else
    -
    3601 port->invalidate();
    -
    3602
    -
    3603 if (path->match(text, this->interval.end, end, flags)) {
    -
    3604 // Path
    -
    3605 this->interval.end = path->interval.end;
    -
    3606 }
    -
    3607
    -
    3608 this->interval.start = start;
    -
    3609 return true;
    -
    3610 }
    -
    3611
    -
    3612 if (mailto_scheme->interval) {
    -
    3613 if (username->match(text, this->interval.end, end, flags) &&
    -
    3614 m_at->match(text, username->interval.end, end, flags))
    -
    3615 {
    -
    3616 // Username
    -
    3617 this->interval.end = m_at->interval.end;
    -
    3618 }
    -
    3619 else {
    -
    3620 invalidate();
    -
    3621 return false;
    -
    3622 }
    -
    3623
    -
    3624 if (m_ip_lbracket->match(text, this->interval.end, end, flags) &&
    -
    3625 ipv4_host->match(text, m_ip_lbracket->interval.end, end, flags) &&
    -
    3626 m_ip_rbracket->match(text, ipv4_host->interval.end, end, flags))
    -
    3627 {
    -
    3628 // Host is IPv4
    -
    3629 this->interval.end = m_ip_rbracket->interval.end;
    -
    3630 ipv6_host->invalidate();
    -
    3631 dns_host->invalidate();
    -
    3632 }
    -
    3633 else if (
    -
    3634 m_ip_lbracket->match(text, this->interval.end, end, flags) &&
    -
    3635 ipv6_host->match(text, m_ip_lbracket->interval.end, end, flags) &&
    -
    3636 m_ip_rbracket->match(text, ipv6_host->interval.end, end, flags))
    -
    3637 {
    -
    3638 // Host is IPv6
    -
    3639 this->interval.end = m_ip_rbracket->interval.end;
    -
    3640 ipv4_host->invalidate();
    -
    3641 dns_host->invalidate();
    -
    3642 }
    -
    3643 else if (dns_host->match(text, this->interval.end, end, flags)) {
    -
    3644 // Host is hostname
    -
    3645 this->interval.end = dns_host->interval.end;
    -
    3646 ipv4_host->invalidate();
    -
    3647 ipv6_host->invalidate();
    -
    3648 }
    -
    3649 else {
    -
    3650 invalidate();
    -
    3651 return false;
    -
    3652 }
    -
    3653
    -
    3654 password->invalidate();
    -
    3655 port->invalidate();
    -
    3656 path->invalidate();
    -
    3657 this->interval.start = start;
    -
    3658 return true;
    -
    3659 }
    -
    3660
    -
    3661 if (file_scheme->interval) {
    -
    3662 if (path->match(text, this->interval.end, end, flags)) {
    -
    3663 // Path
    -
    3664 this->interval.end = path->interval.end;
    -
    3665 }
    -
    3666
    -
    3667 username->invalidate();
    -
    3668 password->invalidate();
    -
    3669 ipv4_host->invalidate();
    -
    3670 ipv6_host->invalidate();
    -
    3671 dns_host->invalidate();
    -
    3672 port->invalidate();
    -
    3673 this->interval.start = start;
    -
    3674 return true;
    -
    3675 }
    -
    3676
    -
    3677 // "http://" found or defaulted to
    -
    3678
    -
    3679 // If "http://" explicit, test for username&password.
    -
    3680 if (http_scheme->interval &&
    -
    3681 username->match(text, this->interval.end, end, flags))
    -
    3682 {
    -
    3683 if (m_colon->match(text, username->interval.end, end, flags) &&
    -
    3684 password->match(text, m_colon->interval.end, end, flags) &&
    -
    3685 m_at->match(text, password->interval.end, end, flags))
    -
    3686 {
    -
    3687 // Username and password
    -
    3688 this->interval.end = m_at->interval.end;
    -
    3689 }
    -
    3690 else if (m_at->match(text, username->interval.end, end, flags)) {
    -
    3691 // Username only
    -
    3692 this->interval.end = m_at->interval.end;
    -
    3693 password->invalidate();
    -
    3694 }
    -
    3695 else {
    -
    3696 username->invalidate();
    -
    3697 password->invalidate();
    -
    3698 }
    -
    3699 }
    -
    3700 else {
    -
    3701 username->invalidate();
    -
    3702 password->invalidate();
    -
    3703 }
    -
    3704
    -
    3705 if (ipv4_host->match(text, this->interval.end, end, flags)) {
    -
    3706 // Host is IPv4
    -
    3707 this->interval.end = ipv4_host->interval.end;
    -
    3708 ipv6_host->invalidate();
    -
    3709 dns_host->invalidate();
    -
    3710 }
    -
    3711 else if (
    -
    3712 m_ip_lbracket->match(text, this->interval.end, end, flags) &&
    -
    3713 ipv6_host->match(text, m_ip_lbracket->interval.end, end, flags) &&
    -
    3714 m_ip_rbracket->match(text, ipv6_host->interval.end, end, flags))
    -
    3715 {
    -
    3716 // Host is IPv6
    -
    3717 this->interval.end = m_ip_rbracket->interval.end;
    -
    3718 ipv4_host->invalidate();
    -
    3719 dns_host->invalidate();
    -
    3720 }
    -
    3721 else if (dns_host->match(text, this->interval.end, end, flags)) {
    -
    3722 // Host is hostname
    -
    3723 this->interval.end = dns_host->interval.end;
    -
    3724 ipv4_host->invalidate();
    -
    3725 ipv6_host->invalidate();
    -
    3726 }
    -
    3727 else {
    -
    3728 invalidate();
    -
    3729 return false;
    -
    3730 }
    -
    3731
    -
    3732 if (m_colon->match(text, this->interval.end, end, flags) &&
    -
    3733 port->match(text, m_colon->interval.end, end, flags))
    -
    3734 {
    -
    3735 // Port
    -
    3736 this->interval.end = port->interval.end;
    -
    3737 }
    -
    3738 else
    -
    3739 port->invalidate();
    -
    3740
    -
    3741 if (path->match(text, this->interval.end, end, flags)) {
    -
    3742 // Path
    -
    3743 this->interval.end = path->interval.end;
    -
    3744 }
    -
    3745
    -
    3746 this->interval.start = start;
    -
    3747 return true;
    -
    3748 }
    -
    3749
    -
    3750 virtual void invalidate()
    -
    3751 {
    -
    3752 http_scheme->invalidate();
    -
    3753 ftp_scheme->invalidate();
    -
    3754 mailto_scheme->invalidate();
    -
    3755 file_scheme->invalidate();
    -
    3756 username->invalidate();
    -
    3757 password->invalidate();
    -
    3758 ipv4_host->invalidate();
    -
    3759 ipv6_host->invalidate();
    -
    3760 dns_host->invalidate();
    -
    3761 port->invalidate();
    -
    3762 path->invalidate();
    - -
    3764 }
    -
    3765
    -
    3766 public:
    -
    3767 std::shared_ptr<basic_parser<T>> http_scheme;
    -
    3768 std::shared_ptr<basic_parser<T>> ftp_scheme;
    -
    3769 std::shared_ptr<basic_parser<T>> mailto_scheme;
    -
    3770 std::shared_ptr<basic_parser<T>> file_scheme;
    -
    3771 std::shared_ptr<basic_parser<T>> username;
    -
    3772 std::shared_ptr<basic_parser<T>> password;
    -
    3773 std::shared_ptr<basic_parser<T>> ipv4_host;
    -
    3774 std::shared_ptr<basic_parser<T>> ipv6_host;
    -
    3775 std::shared_ptr<basic_parser<T>> dns_host;
    -
    3776 std::shared_ptr<basic_parser<T>> port;
    -
    3777 std::shared_ptr<basic_parser<T>> path;
    -
    3778
    -
    3779 protected:
    -
    3780 std::shared_ptr<basic_parser<T>> m_colon;
    -
    3781 std::shared_ptr<basic_parser<T>> m_slash;
    -
    3782 std::shared_ptr<basic_parser<T>> m_at;
    -
    3783 std::shared_ptr<basic_parser<T>> m_ip_lbracket;
    -
    3784 std::shared_ptr<basic_parser<T>> m_ip_rbracket;
    -
    3785 };
    +
    3426
    + + +
    3429#ifdef _UNICODE
    +
    3430 using turl_path = wurl_path;
    +
    3431#else
    +
    3432 using turl_path = url_path;
    +
    3433#endif
    + +
    3435
    +
    3439 template <class T>
    +
    +
    3440 class basic_url : public basic_parser<T>
    +
    3441 {
    +
    3442 public:
    +
    3443 basic_url(
    +
    3444 _In_ const std::shared_ptr<basic_parser<T>>& _http_scheme,
    +
    3445 _In_ const std::shared_ptr<basic_parser<T>>& _ftp_scheme,
    +
    3446 _In_ const std::shared_ptr<basic_parser<T>>& _mailto_scheme,
    +
    3447 _In_ const std::shared_ptr<basic_parser<T>>& _file_scheme,
    +
    3448 _In_ const std::shared_ptr<basic_parser<T>>& colon,
    +
    3449 _In_ const std::shared_ptr<basic_parser<T>>& slash,
    +
    3450 _In_ const std::shared_ptr<basic_parser<T>>& _username,
    +
    3451 _In_ const std::shared_ptr<basic_parser<T>>& _password,
    +
    3452 _In_ const std::shared_ptr<basic_parser<T>>& at,
    +
    3453 _In_ const std::shared_ptr<basic_parser<T>>& ip_lbracket,
    +
    3454 _In_ const std::shared_ptr<basic_parser<T>>& ip_rbracket,
    +
    3455 _In_ const std::shared_ptr<basic_parser<T>>& _ipv4_host,
    +
    3456 _In_ const std::shared_ptr<basic_parser<T>>& _ipv6_host,
    +
    3457 _In_ const std::shared_ptr<basic_parser<T>>& _dns_host,
    +
    3458 _In_ const std::shared_ptr<basic_parser<T>>& _port,
    +
    3459 _In_ const std::shared_ptr<basic_parser<T>>& _path,
    +
    3460 _In_ const std::locale& locale = std::locale()) :
    +
    3461 basic_parser<T>(locale),
    +
    3462 http_scheme(_http_scheme),
    +
    3463 ftp_scheme(_ftp_scheme),
    +
    3464 mailto_scheme(_mailto_scheme),
    +
    3465 file_scheme(_file_scheme),
    +
    3466 m_colon(colon),
    +
    3467 m_slash(slash),
    +
    3468 username(_username),
    +
    3469 password(_password),
    +
    3470 m_at(at),
    +
    3471 m_ip_lbracket(ip_lbracket),
    +
    3472 m_ip_rbracket(ip_rbracket),
    +
    3473 ipv4_host(_ipv4_host),
    +
    3474 ipv6_host(_ipv6_host),
    +
    3475 dns_host(_dns_host),
    +
    3476 port(_port),
    +
    3477 path(_path)
    +
    3478 {}
    +
    3479
    +
    3480 virtual bool match(
    +
    3481 _In_reads_or_z_(end) const T* text,
    +
    3482 _In_ size_t start = 0,
    +
    3483 _In_ size_t end = (size_t)-1,
    +
    3484 _In_ int flags = match_default)
    +
    3485 {
    +
    3486 _Assume_(text || start >= end);
    +
    3487
    +
    3488 this->interval.end = start;
    +
    3489
    +
    3490 if (http_scheme->match(text, this->interval.end, end, flags) &&
    +
    3491 m_colon->match(text, http_scheme->interval.end, end, flags) &&
    +
    3492 m_slash->match(text, m_colon->interval.end, end, flags) &&
    +
    3493 m_slash->match(text, m_slash->interval.end, end, flags))
    +
    3494 {
    +
    3495 // http://
    +
    3496 this->interval.end = m_slash->interval.end;
    +
    3497 ftp_scheme->invalidate();
    +
    3498 mailto_scheme->invalidate();
    +
    3499 file_scheme->invalidate();
    +
    3500 }
    +
    3501 else if (ftp_scheme->match(text, this->interval.end, end, flags) &&
    +
    3502 m_colon->match(text, ftp_scheme->interval.end, end, flags) &&
    +
    3503 m_slash->match(text, m_colon->interval.end, end, flags) &&
    +
    3504 m_slash->match(text, m_slash->interval.end, end, flags))
    +
    3505 {
    +
    3506 // ftp://
    +
    3507 this->interval.end = m_slash->interval.end;
    +
    3508 http_scheme->invalidate();
    +
    3509 mailto_scheme->invalidate();
    +
    3510 file_scheme->invalidate();
    +
    3511 }
    +
    3512 else if (mailto_scheme->match(text, this->interval.end, end, flags) &&
    +
    3513 m_colon->match(text, mailto_scheme->interval.end, end, flags))
    +
    3514 {
    +
    3515 // mailto:
    +
    3516 this->interval.end = m_colon->interval.end;
    +
    3517 http_scheme->invalidate();
    +
    3518 ftp_scheme->invalidate();
    +
    3519 file_scheme->invalidate();
    +
    3520 }
    +
    3521 else if (file_scheme->match(text, this->interval.end, end, flags) &&
    +
    3522 m_colon->match(text, file_scheme->interval.end, end, flags) &&
    +
    3523 m_slash->match(text, m_colon->interval.end, end, flags) &&
    +
    3524 m_slash->match(text, m_slash->interval.end, end, flags))
    +
    3525 {
    +
    3526 // file://
    +
    3527 this->interval.end = m_slash->interval.end;
    +
    3528 http_scheme->invalidate();
    +
    3529 ftp_scheme->invalidate();
    +
    3530 mailto_scheme->invalidate();
    +
    3531 }
    +
    3532 else {
    +
    3533 // Default to http:
    +
    3534 http_scheme->invalidate();
    +
    3535 ftp_scheme->invalidate();
    +
    3536 mailto_scheme->invalidate();
    +
    3537 file_scheme->invalidate();
    +
    3538 }
    +
    3539
    +
    3540 if (ftp_scheme->interval) {
    +
    3541 if (username->match(text, this->interval.end, end, flags)) {
    +
    3542 if (m_colon->match(text, username->interval.end, end, flags) &&
    +
    3543 password->match(text, m_colon->interval.end, end, flags) &&
    +
    3544 m_at->match(text, password->interval.end, end, flags))
    +
    3545 {
    +
    3546 // Username and password
    +
    3547 this->interval.end = m_at->interval.end;
    +
    3548 }
    +
    3549 else if (m_at->match(text, this->interval.end, end, flags)) {
    +
    3550 // Username only
    +
    3551 this->interval.end = m_at->interval.end;
    +
    3552 password->invalidate();
    +
    3553 }
    +
    3554 else {
    +
    3555 username->invalidate();
    +
    3556 password->invalidate();
    +
    3557 }
    +
    3558 }
    +
    3559 else {
    +
    3560 username->invalidate();
    +
    3561 password->invalidate();
    +
    3562 }
    +
    3563
    +
    3564 if (ipv4_host->match(text, this->interval.end, end, flags)) {
    +
    3565 // Host is IPv4
    +
    3566 this->interval.end = ipv4_host->interval.end;
    +
    3567 ipv6_host->invalidate();
    +
    3568 dns_host->invalidate();
    +
    3569 }
    +
    3570 else if (
    +
    3571 m_ip_lbracket->match(text, this->interval.end, end, flags) &&
    +
    3572 ipv6_host->match(text, m_ip_lbracket->interval.end, end, flags) &&
    +
    3573 m_ip_rbracket->match(text, ipv6_host->interval.end, end, flags))
    +
    3574 {
    +
    3575 // Host is IPv6
    +
    3576 this->interval.end = m_ip_rbracket->interval.end;
    +
    3577 ipv4_host->invalidate();
    +
    3578 dns_host->invalidate();
    +
    3579 }
    +
    3580 else if (dns_host->match(text, this->interval.end, end, flags)) {
    +
    3581 // Host is hostname
    +
    3582 this->interval.end = dns_host->interval.end;
    +
    3583 ipv4_host->invalidate();
    +
    3584 ipv6_host->invalidate();
    +
    3585 }
    +
    3586 else {
    +
    3587 invalidate();
    +
    3588 return false;
    +
    3589 }
    +
    3590
    +
    3591 if (m_colon->match(text, this->interval.end, end, flags) &&
    +
    3592 port->match(text, m_colon->interval.end, end, flags))
    +
    3593 {
    +
    3594 // Port
    +
    3595 this->interval.end = port->interval.end;
    +
    3596 }
    +
    3597 else
    +
    3598 port->invalidate();
    +
    3599
    +
    3600 if (path->match(text, this->interval.end, end, flags)) {
    +
    3601 // Path
    +
    3602 this->interval.end = path->interval.end;
    +
    3603 }
    +
    3604
    +
    3605 this->interval.start = start;
    +
    3606 return true;
    +
    3607 }
    +
    3608
    +
    3609 if (mailto_scheme->interval) {
    +
    3610 if (username->match(text, this->interval.end, end, flags) &&
    +
    3611 m_at->match(text, username->interval.end, end, flags))
    +
    3612 {
    +
    3613 // Username
    +
    3614 this->interval.end = m_at->interval.end;
    +
    3615 }
    +
    3616 else {
    +
    3617 invalidate();
    +
    3618 return false;
    +
    3619 }
    +
    3620
    +
    3621 if (m_ip_lbracket->match(text, this->interval.end, end, flags) &&
    +
    3622 ipv4_host->match(text, m_ip_lbracket->interval.end, end, flags) &&
    +
    3623 m_ip_rbracket->match(text, ipv4_host->interval.end, end, flags))
    +
    3624 {
    +
    3625 // Host is IPv4
    +
    3626 this->interval.end = m_ip_rbracket->interval.end;
    +
    3627 ipv6_host->invalidate();
    +
    3628 dns_host->invalidate();
    +
    3629 }
    +
    3630 else if (
    +
    3631 m_ip_lbracket->match(text, this->interval.end, end, flags) &&
    +
    3632 ipv6_host->match(text, m_ip_lbracket->interval.end, end, flags) &&
    +
    3633 m_ip_rbracket->match(text, ipv6_host->interval.end, end, flags))
    +
    3634 {
    +
    3635 // Host is IPv6
    +
    3636 this->interval.end = m_ip_rbracket->interval.end;
    +
    3637 ipv4_host->invalidate();
    +
    3638 dns_host->invalidate();
    +
    3639 }
    +
    3640 else if (dns_host->match(text, this->interval.end, end, flags)) {
    +
    3641 // Host is hostname
    +
    3642 this->interval.end = dns_host->interval.end;
    +
    3643 ipv4_host->invalidate();
    +
    3644 ipv6_host->invalidate();
    +
    3645 }
    +
    3646 else {
    +
    3647 invalidate();
    +
    3648 return false;
    +
    3649 }
    +
    3650
    +
    3651 password->invalidate();
    +
    3652 port->invalidate();
    +
    3653 path->invalidate();
    +
    3654 this->interval.start = start;
    +
    3655 return true;
    +
    3656 }
    +
    3657
    +
    3658 if (file_scheme->interval) {
    +
    3659 if (path->match(text, this->interval.end, end, flags)) {
    +
    3660 // Path
    +
    3661 this->interval.end = path->interval.end;
    +
    3662 }
    +
    3663
    +
    3664 username->invalidate();
    +
    3665 password->invalidate();
    +
    3666 ipv4_host->invalidate();
    +
    3667 ipv6_host->invalidate();
    +
    3668 dns_host->invalidate();
    +
    3669 port->invalidate();
    +
    3670 this->interval.start = start;
    +
    3671 return true;
    +
    3672 }
    +
    3673
    +
    3674 // "http://" found or defaulted to
    +
    3675
    +
    3676 // If "http://" explicit, test for username&password.
    +
    3677 if (http_scheme->interval &&
    +
    3678 username->match(text, this->interval.end, end, flags))
    +
    3679 {
    +
    3680 if (m_colon->match(text, username->interval.end, end, flags) &&
    +
    3681 password->match(text, m_colon->interval.end, end, flags) &&
    +
    3682 m_at->match(text, password->interval.end, end, flags))
    +
    3683 {
    +
    3684 // Username and password
    +
    3685 this->interval.end = m_at->interval.end;
    +
    3686 }
    +
    3687 else if (m_at->match(text, username->interval.end, end, flags)) {
    +
    3688 // Username only
    +
    3689 this->interval.end = m_at->interval.end;
    +
    3690 password->invalidate();
    +
    3691 }
    +
    3692 else {
    +
    3693 username->invalidate();
    +
    3694 password->invalidate();
    +
    3695 }
    +
    3696 }
    +
    3697 else {
    +
    3698 username->invalidate();
    +
    3699 password->invalidate();
    +
    3700 }
    +
    3701
    +
    3702 if (ipv4_host->match(text, this->interval.end, end, flags)) {
    +
    3703 // Host is IPv4
    +
    3704 this->interval.end = ipv4_host->interval.end;
    +
    3705 ipv6_host->invalidate();
    +
    3706 dns_host->invalidate();
    +
    3707 }
    +
    3708 else if (
    +
    3709 m_ip_lbracket->match(text, this->interval.end, end, flags) &&
    +
    3710 ipv6_host->match(text, m_ip_lbracket->interval.end, end, flags) &&
    +
    3711 m_ip_rbracket->match(text, ipv6_host->interval.end, end, flags))
    +
    3712 {
    +
    3713 // Host is IPv6
    +
    3714 this->interval.end = m_ip_rbracket->interval.end;
    +
    3715 ipv4_host->invalidate();
    +
    3716 dns_host->invalidate();
    +
    3717 }
    +
    3718 else if (dns_host->match(text, this->interval.end, end, flags)) {
    +
    3719 // Host is hostname
    +
    3720 this->interval.end = dns_host->interval.end;
    +
    3721 ipv4_host->invalidate();
    +
    3722 ipv6_host->invalidate();
    +
    3723 }
    +
    3724 else {
    +
    3725 invalidate();
    +
    3726 return false;
    +
    3727 }
    +
    3728
    +
    3729 if (m_colon->match(text, this->interval.end, end, flags) &&
    +
    3730 port->match(text, m_colon->interval.end, end, flags))
    +
    3731 {
    +
    3732 // Port
    +
    3733 this->interval.end = port->interval.end;
    +
    3734 }
    +
    3735 else
    +
    3736 port->invalidate();
    +
    3737
    +
    3738 if (path->match(text, this->interval.end, end, flags)) {
    +
    3739 // Path
    +
    3740 this->interval.end = path->interval.end;
    +
    3741 }
    +
    3742
    +
    3743 this->interval.start = start;
    +
    3744 return true;
    +
    3745 }
    +
    3746
    +
    3747 virtual void invalidate()
    +
    3748 {
    +
    3749 http_scheme->invalidate();
    +
    3750 ftp_scheme->invalidate();
    +
    3751 mailto_scheme->invalidate();
    +
    3752 file_scheme->invalidate();
    +
    3753 username->invalidate();
    +
    3754 password->invalidate();
    +
    3755 ipv4_host->invalidate();
    +
    3756 ipv6_host->invalidate();
    +
    3757 dns_host->invalidate();
    +
    3758 port->invalidate();
    +
    3759 path->invalidate();
    + +
    3761 }
    +
    3762
    +
    3763 public:
    +
    3764 std::shared_ptr<basic_parser<T>> http_scheme;
    +
    3765 std::shared_ptr<basic_parser<T>> ftp_scheme;
    +
    3766 std::shared_ptr<basic_parser<T>> mailto_scheme;
    +
    3767 std::shared_ptr<basic_parser<T>> file_scheme;
    +
    3768 std::shared_ptr<basic_parser<T>> username;
    +
    3769 std::shared_ptr<basic_parser<T>> password;
    +
    3770 std::shared_ptr<basic_parser<T>> ipv4_host;
    +
    3771 std::shared_ptr<basic_parser<T>> ipv6_host;
    +
    3772 std::shared_ptr<basic_parser<T>> dns_host;
    +
    3773 std::shared_ptr<basic_parser<T>> port;
    +
    3774 std::shared_ptr<basic_parser<T>> path;
    +
    3775
    +
    3776 protected:
    +
    3777 std::shared_ptr<basic_parser<T>> m_colon;
    +
    3778 std::shared_ptr<basic_parser<T>> m_slash;
    +
    3779 std::shared_ptr<basic_parser<T>> m_at;
    +
    3780 std::shared_ptr<basic_parser<T>> m_ip_lbracket;
    +
    3781 std::shared_ptr<basic_parser<T>> m_ip_rbracket;
    +
    3782 };
    -
    3786
    -
    3787 using url = basic_url<char>;
    -
    3788 using wurl = basic_url<wchar_t>;
    -
    3789#ifdef _UNICODE
    -
    3790 using turl = wurl;
    -
    3791#else
    -
    3792 using turl = url;
    -
    3793#endif
    -
    3794 using sgml_url = basic_url<char>;
    -
    3795
    -
    3799 template <class T>
    -
    - -
    3801 {
    -
    3802 public:
    - -
    3804 _In_ const std::shared_ptr<basic_parser<T>>& _username,
    -
    3805 _In_ const std::shared_ptr<basic_parser<T>>& at,
    -
    3806 _In_ const std::shared_ptr<basic_parser<T>>& ip_lbracket,
    -
    3807 _In_ const std::shared_ptr<basic_parser<T>>& ip_rbracket,
    -
    3808 _In_ const std::shared_ptr<basic_parser<T>>& _ipv4_host,
    -
    3809 _In_ const std::shared_ptr<basic_parser<T>>& _ipv6_host,
    -
    3810 _In_ const std::shared_ptr<basic_parser<T>>& _dns_host,
    -
    3811 _In_ const std::locale& locale = std::locale()) :
    -
    3812 basic_parser<T>(locale),
    -
    3813 username(_username),
    -
    3814 m_at(at),
    -
    3815 m_ip_lbracket(ip_lbracket),
    -
    3816 m_ip_rbracket(ip_rbracket),
    -
    3817 ipv4_host(_ipv4_host),
    -
    3818 ipv6_host(_ipv6_host),
    -
    3819 dns_host(_dns_host)
    -
    3820 {}
    -
    3821
    -
    3822 virtual bool match(
    -
    3823 _In_reads_or_z_(end) const T* text,
    -
    3824 _In_ size_t start = 0,
    -
    3825 _In_ size_t end = (size_t)-1,
    -
    3826 _In_ int flags = match_default)
    -
    3827 {
    -
    3828 _Assume_(text || start >= end);
    -
    3829
    -
    3830 if (username->match(text, start, end, flags) &&
    -
    3831 m_at->match(text, username->interval.end, end, flags))
    -
    3832 {
    -
    3833 // Username@
    -
    3834 if (m_ip_lbracket->match(text, m_at->interval.end, end, flags) &&
    -
    3835 ipv4_host->match(text, m_ip_lbracket->interval.end, end, flags) &&
    -
    3836 m_ip_rbracket->match(text, ipv4_host->interval.end, end, flags))
    -
    3837 {
    -
    3838 // Host is IPv4
    -
    3839 this->interval.end = m_ip_rbracket->interval.end;
    -
    3840 ipv6_host->invalidate();
    -
    3841 dns_host->invalidate();
    -
    3842 }
    -
    3843 else if (
    -
    3844 m_ip_lbracket->match(text, m_at->interval.end, end, flags) &&
    -
    3845 ipv6_host->match(text, m_ip_lbracket->interval.end, end, flags) &&
    -
    3846 m_ip_rbracket->match(text, ipv6_host->interval.end, end, flags))
    -
    3847 {
    -
    3848 // Host is IPv6
    -
    3849 this->interval.end = m_ip_rbracket->interval.end;
    -
    3850 ipv4_host->invalidate();
    -
    3851 dns_host->invalidate();
    -
    3852 }
    -
    3853 else if (dns_host->match(text, m_at->interval.end, end, flags)) {
    -
    3854 // Host is hostname
    -
    3855 this->interval.end = dns_host->interval.end;
    -
    3856 ipv4_host->invalidate();
    -
    3857 ipv6_host->invalidate();
    -
    3858 }
    -
    3859 else
    -
    3860 goto error;
    -
    3861 this->interval.start = start;
    -
    3862 return true;
    -
    3863 }
    -
    3864
    -
    3865 error:
    -
    3866 username->invalidate();
    -
    3867 ipv4_host->invalidate();
    -
    3868 ipv6_host->invalidate();
    -
    3869 dns_host->invalidate();
    -
    3870 this->interval.start = (this->interval.end = start) + 1;
    -
    3871 return false;
    -
    3872 }
    -
    3873
    -
    3874 virtual void invalidate()
    -
    3875 {
    -
    3876 username->invalidate();
    -
    3877 ipv4_host->invalidate();
    -
    3878 ipv6_host->invalidate();
    -
    3879 dns_host->invalidate();
    - -
    3881 }
    -
    3882
    -
    3883 public:
    -
    3884 std::shared_ptr<basic_parser<T>> username;
    -
    3885 std::shared_ptr<basic_parser<T>> ipv4_host;
    -
    3886 std::shared_ptr<basic_parser<T>> ipv6_host;
    -
    3887 std::shared_ptr<basic_parser<T>> dns_host;
    -
    3888
    -
    3889 protected:
    -
    3890 std::shared_ptr<basic_parser<T>> m_at;
    -
    3891 std::shared_ptr<basic_parser<T>> m_ip_lbracket;
    -
    3892 std::shared_ptr<basic_parser<T>> m_ip_rbracket;
    -
    3893 };
    +
    3783
    +
    3784 using url = basic_url<char>;
    +
    3785 using wurl = basic_url<wchar_t>;
    +
    3786#ifdef _UNICODE
    +
    3787 using turl = wurl;
    +
    3788#else
    +
    3789 using turl = url;
    +
    3790#endif
    +
    3791 using sgml_url = basic_url<char>;
    +
    3792
    +
    3796 template <class T>
    +
    + +
    3798 {
    +
    3799 public:
    + +
    3801 _In_ const std::shared_ptr<basic_parser<T>>& _username,
    +
    3802 _In_ const std::shared_ptr<basic_parser<T>>& at,
    +
    3803 _In_ const std::shared_ptr<basic_parser<T>>& ip_lbracket,
    +
    3804 _In_ const std::shared_ptr<basic_parser<T>>& ip_rbracket,
    +
    3805 _In_ const std::shared_ptr<basic_parser<T>>& _ipv4_host,
    +
    3806 _In_ const std::shared_ptr<basic_parser<T>>& _ipv6_host,
    +
    3807 _In_ const std::shared_ptr<basic_parser<T>>& _dns_host,
    +
    3808 _In_ const std::locale& locale = std::locale()) :
    +
    3809 basic_parser<T>(locale),
    +
    3810 username(_username),
    +
    3811 m_at(at),
    +
    3812 m_ip_lbracket(ip_lbracket),
    +
    3813 m_ip_rbracket(ip_rbracket),
    +
    3814 ipv4_host(_ipv4_host),
    +
    3815 ipv6_host(_ipv6_host),
    +
    3816 dns_host(_dns_host)
    +
    3817 {}
    +
    3818
    +
    3819 virtual bool match(
    +
    3820 _In_reads_or_z_(end) const T* text,
    +
    3821 _In_ size_t start = 0,
    +
    3822 _In_ size_t end = (size_t)-1,
    +
    3823 _In_ int flags = match_default)
    +
    3824 {
    +
    3825 _Assume_(text || start >= end);
    +
    3826
    +
    3827 if (username->match(text, start, end, flags) &&
    +
    3828 m_at->match(text, username->interval.end, end, flags))
    +
    3829 {
    +
    3830 // Username@
    +
    3831 if (m_ip_lbracket->match(text, m_at->interval.end, end, flags) &&
    +
    3832 ipv4_host->match(text, m_ip_lbracket->interval.end, end, flags) &&
    +
    3833 m_ip_rbracket->match(text, ipv4_host->interval.end, end, flags))
    +
    3834 {
    +
    3835 // Host is IPv4
    +
    3836 this->interval.end = m_ip_rbracket->interval.end;
    +
    3837 ipv6_host->invalidate();
    +
    3838 dns_host->invalidate();
    +
    3839 }
    +
    3840 else if (
    +
    3841 m_ip_lbracket->match(text, m_at->interval.end, end, flags) &&
    +
    3842 ipv6_host->match(text, m_ip_lbracket->interval.end, end, flags) &&
    +
    3843 m_ip_rbracket->match(text, ipv6_host->interval.end, end, flags))
    +
    3844 {
    +
    3845 // Host is IPv6
    +
    3846 this->interval.end = m_ip_rbracket->interval.end;
    +
    3847 ipv4_host->invalidate();
    +
    3848 dns_host->invalidate();
    +
    3849 }
    +
    3850 else if (dns_host->match(text, m_at->interval.end, end, flags)) {
    +
    3851 // Host is hostname
    +
    3852 this->interval.end = dns_host->interval.end;
    +
    3853 ipv4_host->invalidate();
    +
    3854 ipv6_host->invalidate();
    +
    3855 }
    +
    3856 else
    +
    3857 goto error;
    +
    3858 this->interval.start = start;
    +
    3859 return true;
    +
    3860 }
    +
    3861
    +
    3862 error:
    +
    3863 username->invalidate();
    +
    3864 ipv4_host->invalidate();
    +
    3865 ipv6_host->invalidate();
    +
    3866 dns_host->invalidate();
    +
    3867 this->interval.start = (this->interval.end = start) + 1;
    +
    3868 return false;
    +
    3869 }
    +
    3870
    +
    3871 virtual void invalidate()
    +
    3872 {
    +
    3873 username->invalidate();
    +
    3874 ipv4_host->invalidate();
    +
    3875 ipv6_host->invalidate();
    +
    3876 dns_host->invalidate();
    + +
    3878 }
    +
    3879
    +
    3880 public:
    +
    3881 std::shared_ptr<basic_parser<T>> username;
    +
    3882 std::shared_ptr<basic_parser<T>> ipv4_host;
    +
    3883 std::shared_ptr<basic_parser<T>> ipv6_host;
    +
    3884 std::shared_ptr<basic_parser<T>> dns_host;
    +
    3885
    +
    3886 protected:
    +
    3887 std::shared_ptr<basic_parser<T>> m_at;
    +
    3888 std::shared_ptr<basic_parser<T>> m_ip_lbracket;
    +
    3889 std::shared_ptr<basic_parser<T>> m_ip_rbracket;
    +
    3890 };
    -
    3894
    - - -
    3897#ifdef _UNICODE
    - -
    3899#else
    - -
    3901#endif
    - -
    3903
    -
    3907 template <class T>
    -
    - -
    3909 {
    -
    3910 public:
    - -
    3912 _In_ const std::shared_ptr<basic_parser<T>>& _emoticon,
    -
    3913 _In_ const std::shared_ptr<basic_parser<T>>& _apex,
    -
    3914 _In_ const std::shared_ptr<basic_parser<T>>& _eyes,
    -
    3915 _In_ const std::shared_ptr<basic_parser<T>>& _nose,
    -
    3916 _In_ const std::shared_ptr<basic_set<T>>& _mouth,
    -
    3917 _In_ const std::locale& locale = std::locale()) :
    -
    3918 basic_parser<T>(locale),
    - -
    3920 apex(_apex),
    -
    3921 eyes(_eyes),
    -
    3922 nose(_nose),
    -
    3923 mouth(_mouth)
    -
    3924 {}
    -
    3925
    -
    3926 virtual bool match(
    -
    3927 _In_reads_or_z_(end) const T* text,
    -
    3928 _In_ size_t start = 0,
    -
    3929 _In_ size_t end = (size_t)-1,
    -
    3930 _In_ int flags = match_default)
    -
    3931 {
    -
    3932 _Assume_(text || start >= end);
    -
    3933
    -
    3934 if (emoticon && emoticon->match(text, start, end, flags)) {
    -
    3935 if (apex) apex->invalidate();
    -
    3936 eyes->invalidate();
    -
    3937 if (nose) nose->invalidate();
    -
    3938 mouth->invalidate();
    -
    3939 this->interval.start = start;
    -
    3940 this->interval.end = emoticon->interval.end;
    -
    3941 return true;
    -
    3942 }
    -
    3943
    -
    3944 this->interval.end = start;
    +
    3891
    + + +
    3894#ifdef _UNICODE
    + +
    3896#else
    + +
    3898#endif
    + +
    3900
    +
    3904 template <class T>
    +
    + +
    3906 {
    +
    3907 public:
    + +
    3909 _In_ const std::shared_ptr<basic_parser<T>>& _emoticon,
    +
    3910 _In_ const std::shared_ptr<basic_parser<T>>& _apex,
    +
    3911 _In_ const std::shared_ptr<basic_parser<T>>& _eyes,
    +
    3912 _In_ const std::shared_ptr<basic_parser<T>>& _nose,
    +
    3913 _In_ const std::shared_ptr<basic_set<T>>& _mouth,
    +
    3914 _In_ const std::locale& locale = std::locale()) :
    +
    3915 basic_parser<T>(locale),
    + +
    3917 apex(_apex),
    +
    3918 eyes(_eyes),
    +
    3919 nose(_nose),
    +
    3920 mouth(_mouth)
    +
    3921 {}
    +
    3922
    +
    3923 virtual bool match(
    +
    3924 _In_reads_or_z_(end) const T* text,
    +
    3925 _In_ size_t start = 0,
    +
    3926 _In_ size_t end = (size_t)-1,
    +
    3927 _In_ int flags = match_default)
    +
    3928 {
    +
    3929 _Assume_(text || start >= end);
    +
    3930
    +
    3931 if (emoticon && emoticon->match(text, start, end, flags)) {
    +
    3932 if (apex) apex->invalidate();
    +
    3933 eyes->invalidate();
    +
    3934 if (nose) nose->invalidate();
    +
    3935 mouth->invalidate();
    +
    3936 this->interval.start = start;
    +
    3937 this->interval.end = emoticon->interval.end;
    +
    3938 return true;
    +
    3939 }
    +
    3940
    +
    3941 this->interval.end = start;
    +
    3942
    +
    3943 if (apex && apex->match(text, this->interval.end, end, flags))
    +
    3944 this->interval.end = apex->interval.end;
    3945
    -
    3946 if (apex && apex->match(text, this->interval.end, end, flags))
    -
    3947 this->interval.end = apex->interval.end;
    -
    3948
    -
    3949 if (eyes->match(text, this->interval.end, end, flags)) {
    -
    3950 if (nose && nose->match(text, eyes->interval.end, end, flags) &&
    -
    3951 mouth->match(text, nose->interval.end, end, flags))
    -
    3952 {
    -
    3953 size_t
    - -
    3955 hit_offset = mouth->hit_offset;
    -
    3956 // Mouth may repeat :-)))))))
    -
    3957 for (this->interval.end = mouth->interval.end; mouth->match(text, this->interval.end, end, flags) && mouth->hit_offset == hit_offset; this->interval.end = mouth->interval.end);
    -
    3958 mouth->interval.start = start_mouth;
    -
    3959 mouth->interval.end = this->interval.end;
    -
    3960 this->interval.start = start;
    -
    3961 return true;
    -
    3962 }
    -
    3963 if (mouth->match(text, eyes->interval.end, end, flags)) {
    -
    3964 size_t
    - -
    3966 hit_offset = mouth->hit_offset;
    -
    3967 // Mouth may repeat :-)))))))
    -
    3968 for (this->interval.end = mouth->interval.end; mouth->match(text, this->interval.end, end, flags) && mouth->hit_offset == hit_offset; this->interval.end = mouth->interval.end);
    -
    3969 if (nose) nose->invalidate();
    -
    3970 mouth->interval.start = start_mouth;
    -
    3971 mouth->interval.end = this->interval.end;
    -
    3972 this->interval.start = start;
    -
    3973 return true;
    -
    3974 }
    -
    3975 }
    -
    3976
    -
    3977 if (emoticon) emoticon->invalidate();
    -
    3978 if (apex) apex->invalidate();
    -
    3979 eyes->invalidate();
    -
    3980 if (nose) nose->invalidate();
    -
    3981 mouth->invalidate();
    -
    3982 this->interval.start = (this->interval.end = start) + 1;
    -
    3983 return false;
    -
    3984 }
    -
    3985
    -
    3986 virtual void invalidate()
    -
    3987 {
    -
    3988 if (emoticon) emoticon->invalidate();
    -
    3989 if (apex) apex->invalidate();
    -
    3990 eyes->invalidate();
    -
    3991 if (nose) nose->invalidate();
    -
    3992 mouth->invalidate();
    - -
    3994 }
    -
    3995
    -
    3996 public:
    -
    3997 std::shared_ptr<basic_parser<T>> emoticon;
    -
    3998 std::shared_ptr<basic_parser<T>> apex;
    -
    3999 std::shared_ptr<basic_parser<T>> eyes;
    -
    4000 std::shared_ptr<basic_parser<T>> nose;
    -
    4001 std::shared_ptr<basic_set<T>> mouth;
    -
    4002 };
    +
    3946 if (eyes->match(text, this->interval.end, end, flags)) {
    +
    3947 if (nose && nose->match(text, eyes->interval.end, end, flags) &&
    +
    3948 mouth->match(text, nose->interval.end, end, flags))
    +
    3949 {
    +
    3950 size_t
    + +
    3952 hit_offset = mouth->hit_offset;
    +
    3953 // Mouth may repeat :-)))))))
    +
    3954 for (this->interval.end = mouth->interval.end; mouth->match(text, this->interval.end, end, flags) && mouth->hit_offset == hit_offset; this->interval.end = mouth->interval.end);
    +
    3955 mouth->interval.start = start_mouth;
    +
    3956 mouth->interval.end = this->interval.end;
    +
    3957 this->interval.start = start;
    +
    3958 return true;
    +
    3959 }
    +
    3960 if (mouth->match(text, eyes->interval.end, end, flags)) {
    +
    3961 size_t
    + +
    3963 hit_offset = mouth->hit_offset;
    +
    3964 // Mouth may repeat :-)))))))
    +
    3965 for (this->interval.end = mouth->interval.end; mouth->match(text, this->interval.end, end, flags) && mouth->hit_offset == hit_offset; this->interval.end = mouth->interval.end);
    +
    3966 if (nose) nose->invalidate();
    +
    3967 mouth->interval.start = start_mouth;
    +
    3968 mouth->interval.end = this->interval.end;
    +
    3969 this->interval.start = start;
    +
    3970 return true;
    +
    3971 }
    +
    3972 }
    +
    3973
    +
    3974 if (emoticon) emoticon->invalidate();
    +
    3975 if (apex) apex->invalidate();
    +
    3976 eyes->invalidate();
    +
    3977 if (nose) nose->invalidate();
    +
    3978 mouth->invalidate();
    +
    3979 this->interval.start = (this->interval.end = start) + 1;
    +
    3980 return false;
    +
    3981 }
    +
    3982
    +
    3983 virtual void invalidate()
    +
    3984 {
    +
    3985 if (emoticon) emoticon->invalidate();
    +
    3986 if (apex) apex->invalidate();
    +
    3987 eyes->invalidate();
    +
    3988 if (nose) nose->invalidate();
    +
    3989 mouth->invalidate();
    + +
    3991 }
    +
    3992
    +
    3993 public:
    +
    3994 std::shared_ptr<basic_parser<T>> emoticon;
    +
    3995 std::shared_ptr<basic_parser<T>> apex;
    +
    3996 std::shared_ptr<basic_parser<T>> eyes;
    +
    3997 std::shared_ptr<basic_parser<T>> nose;
    +
    3998 std::shared_ptr<basic_set<T>> mouth;
    +
    3999 };
    -
    4003
    - - -
    4006#ifdef _UNICODE
    -
    4007 using temoticon = wemoticon;
    -
    4008#else
    -
    4009 using temoticon = emoticon;
    -
    4010#endif
    - -
    4012
    -
    4016 enum date_format_t {
    -
    4017 date_format_none = 0,
    -
    4018 date_format_dmy = 0x1,
    -
    4019 date_format_mdy = 0x2,
    -
    4020 date_format_ymd = 0x4,
    -
    4021 date_format_ym = 0x8,
    -
    4022 date_format_my = 0x10,
    -
    4023 date_format_dm = 0x20,
    -
    4024 date_format_md = 0x40,
    -
    4025 };
    -
    4026
    -
    4030 template <class T>
    -
    -
    4031 class basic_date : public basic_parser<T>
    -
    4032 {
    -
    4033 public:
    -
    4034 basic_date(
    -
    4035 _In_ int format_mask,
    -
    4036 _In_ const std::shared_ptr<basic_integer<T>>& _day,
    -
    4037 _In_ const std::shared_ptr<basic_integer<T>>& _month,
    -
    4038 _In_ const std::shared_ptr<basic_integer<T>>& _year,
    -
    4039 _In_ const std::shared_ptr<basic_set<T>>& separator,
    -
    4040 _In_ const std::shared_ptr<basic_parser<T>>& space,
    -
    4041 _In_ const std::locale& locale = std::locale()) :
    -
    4042 basic_parser<T>(locale),
    -
    4043 format(date_format_none),
    -
    4044 m_format_mask(format_mask),
    -
    4045 day(_day),
    -
    4046 month(_month),
    -
    4047 year(_year),
    -
    4048 m_separator(separator),
    -
    4049 m_space(space)
    -
    4050 {}
    -
    4051
    -
    4052 virtual bool match(
    -
    4053 _In_reads_or_z_(end) const T* text,
    -
    4054 _In_ size_t start = 0,
    -
    4055 _In_ size_t end = (size_t)-1,
    -
    4056 _In_ int flags = match_default)
    -
    4057 {
    -
    4058 _Assume_(text || start >= end);
    -
    4059
    -
    4060 const int space_match_flags = flags & ~match_multiline; // Spaces in dates must never be broken in new line.
    -
    4061 if ((m_format_mask & date_format_dmy) == date_format_dmy) {
    -
    4062 if (day->match(text, start, end, flags)) {
    -
    4063 for (this->interval.end = day->interval.end; m_space->match(text, this->interval.end, end, space_match_flags); this->interval.end = m_space->interval.end);
    -
    4064 if (m_separator->match(text, this->interval.end, end, flags)) {
    -
    4065 size_t hit_offset = m_separator->hit_offset;
    -
    4066 for (this->interval.end = m_separator->interval.end; m_space->match(text, this->interval.end, end, space_match_flags); this->interval.end = m_space->interval.end);
    -
    4067 if (month->match(text, this->interval.end, end, flags)) {
    -
    4068 for (this->interval.end = month->interval.end; m_space->match(text, this->interval.end, end, space_match_flags); this->interval.end = m_space->interval.end);
    -
    4069 if (m_separator->match(text, this->interval.end, end, flags) &&
    -
    4070 m_separator->hit_offset == hit_offset) // Both separators must match.
    -
    4071 {
    -
    4072 for (this->interval.end = m_separator->interval.end; m_space->match(text, this->interval.end, end, space_match_flags); this->interval.end = m_space->interval.end);
    -
    4073 if (year->match(text, this->interval.end, end, flags) &&
    -
    4074 is_valid(day->value, month->value))
    -
    4075 {
    -
    4076 this->interval.start = start;
    -
    4077 this->interval.end = year->interval.end;
    -
    4078 format = date_format_dmy;
    -
    4079 return true;
    -
    4080 }
    -
    4081 }
    -
    4082 }
    -
    4083 }
    -
    4084 }
    -
    4085 }
    -
    4086
    -
    4087 if ((m_format_mask & date_format_mdy) == date_format_mdy) {
    -
    4088 if (month->match(text, start, end, flags)) {
    -
    4089 for (this->interval.end = month->interval.end; m_space->match(text, this->interval.end, end, space_match_flags); this->interval.end = m_space->interval.end);
    -
    4090 if (m_separator->match(text, this->interval.end, end, flags)) {
    -
    4091 size_t hit_offset = m_separator->hit_offset;
    -
    4092 for (this->interval.end = m_separator->interval.end; m_space->match(text, this->interval.end, end, space_match_flags); this->interval.end = m_space->interval.end);
    -
    4093 if (day->match(text, this->interval.end, end, flags)) {
    -
    4094 for (this->interval.end = day->interval.end; m_space->match(text, this->interval.end, end, space_match_flags); this->interval.end = m_space->interval.end);
    -
    4095 if (m_separator->match(text, this->interval.end, end, flags) &&
    -
    4096 m_separator->hit_offset == hit_offset) // Both separators must match.
    -
    4097 {
    -
    4098 for (this->interval.end = m_separator->interval.end; m_space->match(text, this->interval.end, end, space_match_flags); this->interval.end = m_space->interval.end);
    -
    4099 if (year->match(text, this->interval.end, end, flags) &&
    -
    4100 is_valid(day->value, month->value))
    -
    4101 {
    -
    4102 this->interval.start = start;
    -
    4103 this->interval.end = year->interval.end;
    -
    4104 format = date_format_mdy;
    -
    4105 return true;
    -
    4106 }
    -
    4107 }
    -
    4108 }
    -
    4109 }
    -
    4110 }
    -
    4111 }
    -
    4112
    -
    4113 if ((m_format_mask & date_format_ymd) == date_format_ymd) {
    -
    4114 if (year->match(text, start, end, flags)) {
    -
    4115 for (this->interval.end = year->interval.end; m_space->match(text, this->interval.end, end, space_match_flags); this->interval.end = m_space->interval.end);
    -
    4116 if (m_separator->match(text, this->interval.end, end, flags)) {
    -
    4117 size_t hit_offset = m_separator->hit_offset;
    -
    4118 for (this->interval.end = m_separator->interval.end; m_space->match(text, this->interval.end, end, space_match_flags); this->interval.end = m_space->interval.end);
    -
    4119 if (month->match(text, this->interval.end, end, flags)) {
    -
    4120 for (this->interval.end = month->interval.end; m_space->match(text, this->interval.end, end, space_match_flags); this->interval.end = m_space->interval.end);
    -
    4121 if (m_separator->match(text, this->interval.end, end, flags) &&
    -
    4122 m_separator->hit_offset == hit_offset) // Both separators must match.
    -
    4123 {
    -
    4124 for (this->interval.end = m_separator->interval.end; m_space->match(text, this->interval.end, end, space_match_flags); this->interval.end = m_space->interval.end);
    -
    4125 if (day->match(text, this->interval.end, end, flags) &&
    -
    4126 is_valid(day->value, month->value))
    -
    4127 {
    -
    4128 this->interval.start = start;
    -
    4129 this->interval.end = day->interval.end;
    -
    4130 format = date_format_ymd;
    -
    4131 return true;
    -
    4132 }
    -
    4133 }
    -
    4134 }
    -
    4135 }
    -
    4136 }
    -
    4137 }
    -
    4138
    -
    4139 if ((m_format_mask & date_format_ym) == date_format_ym) {
    -
    4140 if (year->match(text, start, end, flags)) {
    -
    4141 for (this->interval.end = year->interval.end; m_space->match(text, this->interval.end, end, space_match_flags); this->interval.end = m_space->interval.end);
    -
    4142 if (m_separator->match(text, this->interval.end, end, flags)) {
    -
    4143 for (this->interval.end = m_separator->interval.end; m_space->match(text, this->interval.end, end, space_match_flags); this->interval.end = m_space->interval.end);
    -
    4144 if (month->match(text, this->interval.end, end, flags) &&
    -
    4145 is_valid((size_t)-1, month->value))
    -
    4146 {
    -
    4147 if (day) day->invalidate();
    -
    4148 this->interval.start = start;
    -
    4149 this->interval.end = month->interval.end;
    -
    4150 format = date_format_ym;
    -
    4151 return true;
    -
    4152 }
    -
    4153 }
    -
    4154 }
    -
    4155 }
    -
    4156
    -
    4157 if ((m_format_mask & date_format_my) == date_format_my) {
    -
    4158 if (month->match(text, start, end, flags)) {
    -
    4159 for (this->interval.end = month->interval.end; m_space->match(text, this->interval.end, end, space_match_flags); this->interval.end = m_space->interval.end);
    -
    4160 if (m_separator->match(text, this->interval.end, end, flags)) {
    -
    4161 for (this->interval.end = m_separator->interval.end; m_space->match(text, this->interval.end, end, space_match_flags); this->interval.end = m_space->interval.end);
    -
    4162 if (year->match(text, this->interval.end, end, flags) &&
    -
    4163 is_valid((size_t)-1, month->value))
    -
    4164 {
    -
    4165 if (day) day->invalidate();
    -
    4166 this->interval.start = start;
    -
    4167 this->interval.end = year->interval.end;
    -
    4168 format = date_format_my;
    -
    4169 return true;
    -
    4170 }
    -
    4171 }
    -
    4172 }
    -
    4173 }
    -
    4174
    -
    4175 if ((m_format_mask & date_format_dm) == date_format_dm) {
    -
    4176 if (day->match(text, start, end, flags)) {
    -
    4177 for (this->interval.end = day->interval.end; m_space->match(text, this->interval.end, end, space_match_flags); this->interval.end = m_space->interval.end);
    -
    4178 if (m_separator->match(text, this->interval.end, end, flags)) {
    -
    4179 size_t hit_offset = m_separator->hit_offset;
    -
    4180 for (this->interval.end = m_separator->interval.end; m_space->match(text, this->interval.end, end, space_match_flags); this->interval.end = m_space->interval.end);
    -
    4181 if (month->match(text, this->interval.end, end, flags) &&
    -
    4182 is_valid(day->value, month->value))
    -
    4183 {
    -
    4184 if (year) year->invalidate();
    -
    4185 this->interval.start = start;
    -
    4186 for (this->interval.end = month->interval.end; m_space->match(text, this->interval.end, end, space_match_flags); this->interval.end = m_space->interval.end);
    -
    4187 if (m_separator->match(text, this->interval.end, end, flags) &&
    -
    4188 m_separator->hit_offset == hit_offset) // Both separators must match.
    -
    4189 this->interval.end = m_separator->interval.end;
    -
    4190 else
    -
    4191 this->interval.end = month->interval.end;
    -
    4192 format = date_format_dm;
    -
    4193 return true;
    -
    4194 }
    -
    4195 }
    -
    4196 }
    -
    4197 }
    -
    4198
    -
    4199 if ((m_format_mask & date_format_md) == date_format_md) {
    -
    4200 if (month->match(text, start, end, flags)) {
    -
    4201 for (this->interval.end = month->interval.end; m_space->match(text, this->interval.end, end, space_match_flags); this->interval.end = m_space->interval.end);
    -
    4202 if (m_separator->match(text, this->interval.end, end, flags)) {
    -
    4203 size_t hit_offset = m_separator->hit_offset;
    -
    4204 for (this->interval.end = m_separator->interval.end; m_space->match(text, this->interval.end, end, space_match_flags); this->interval.end = m_space->interval.end);
    -
    4205 if (day->match(text, this->interval.end, end, flags) &&
    -
    4206 is_valid(day->value, month->value))
    -
    4207 {
    -
    4208 if (year) year->invalidate();
    -
    4209 this->interval.start = start;
    -
    4210 for (this->interval.end = day->interval.end; m_space->match(text, this->interval.end, end, space_match_flags); this->interval.end = m_space->interval.end);
    -
    4211 if (m_separator->match(text, this->interval.end, end, flags) &&
    -
    4212 m_separator->hit_offset == hit_offset) // Both separators must match.
    -
    4213 this->interval.end = m_separator->interval.end;
    -
    4214 else
    -
    4215 this->interval.end = day->interval.end;
    -
    4216 format = date_format_md;
    -
    4217 return true;
    -
    4218 }
    -
    4219 }
    -
    4220 }
    -
    4221 }
    -
    4222
    -
    4223 if (day) day->invalidate();
    -
    4224 if (month) month->invalidate();
    -
    4225 if (year) year->invalidate();
    -
    4226 format = date_format_none;
    -
    4227 this->interval.start = (this->interval.end = start) + 1;
    -
    4228 return false;
    -
    4229 }
    -
    4230
    -
    4231 virtual void invalidate()
    -
    4232 {
    -
    4233 if (day) day->invalidate();
    -
    4234 if (month) month->invalidate();
    -
    4235 if (year) year->invalidate();
    -
    4236 format = date_format_none;
    - -
    4238 }
    -
    4239
    -
    4240 protected:
    -
    4241 static inline bool is_valid(size_t day, size_t month)
    -
    4242 {
    -
    4243 if (month == (size_t)-1) {
    -
    4244 // Default to January. This allows validating day only, as January has all 31 days.
    -
    4245 month = 1;
    -
    4246 }
    -
    4247 if (day == (size_t)-1) {
    -
    4248 // Default to 1st day in month. This allows validating month only, as each month has 1st day.
    -
    4249 day = 1;
    -
    4250 }
    -
    4251
    -
    4252 switch (month) {
    -
    4253 case 1:
    -
    4254 case 3:
    -
    4255 case 5:
    -
    4256 case 7:
    -
    4257 case 8:
    -
    4258 case 10:
    -
    4259 case 12:
    -
    4260 return 1 <= day && day <= 31;
    -
    4261 case 2:
    -
    4262 return 1 <= day && day <= 29;
    -
    4263 case 4:
    -
    4264 case 6:
    -
    4265 case 9:
    -
    4266 case 11:
    -
    4267 return 1 <= day && day <= 30;
    -
    4268 default:
    -
    4269 return false;
    -
    4270 }
    -
    4271 }
    -
    4272
    -
    4273 public:
    -
    4274 date_format_t format;
    -
    4275 std::shared_ptr<basic_integer<T>> day;
    -
    4276 std::shared_ptr<basic_integer<T>> month;
    -
    4277 std::shared_ptr<basic_integer<T>> year;
    -
    4278
    -
    4279 protected:
    -
    4280 int m_format_mask;
    -
    4281 std::shared_ptr<basic_set<T>> m_separator;
    -
    4282 std::shared_ptr<basic_parser<T>> m_space;
    -
    4283 };
    +
    4000
    + + +
    4003#ifdef _UNICODE
    +
    4004 using temoticon = wemoticon;
    +
    4005#else
    +
    4006 using temoticon = emoticon;
    +
    4007#endif
    + +
    4009
    +
    4013 enum date_format_t {
    +
    4014 date_format_none = 0,
    +
    4015 date_format_dmy = 0x1,
    +
    4016 date_format_mdy = 0x2,
    +
    4017 date_format_ymd = 0x4,
    +
    4018 date_format_ym = 0x8,
    +
    4019 date_format_my = 0x10,
    +
    4020 date_format_dm = 0x20,
    +
    4021 date_format_md = 0x40,
    +
    4022 };
    +
    4023
    +
    4027 template <class T>
    +
    +
    4028 class basic_date : public basic_parser<T>
    +
    4029 {
    +
    4030 public:
    +
    4031 basic_date(
    +
    4032 _In_ int format_mask,
    +
    4033 _In_ const std::shared_ptr<basic_integer<T>>& _day,
    +
    4034 _In_ const std::shared_ptr<basic_integer<T>>& _month,
    +
    4035 _In_ const std::shared_ptr<basic_integer<T>>& _year,
    +
    4036 _In_ const std::shared_ptr<basic_set<T>>& separator,
    +
    4037 _In_ const std::shared_ptr<basic_parser<T>>& space,
    +
    4038 _In_ const std::locale& locale = std::locale()) :
    +
    4039 basic_parser<T>(locale),
    +
    4040 format(date_format_none),
    +
    4041 m_format_mask(format_mask),
    +
    4042 day(_day),
    +
    4043 month(_month),
    +
    4044 year(_year),
    +
    4045 m_separator(separator),
    +
    4046 m_space(space)
    +
    4047 {}
    +
    4048
    +
    4049 virtual bool match(
    +
    4050 _In_reads_or_z_(end) const T* text,
    +
    4051 _In_ size_t start = 0,
    +
    4052 _In_ size_t end = (size_t)-1,
    +
    4053 _In_ int flags = match_default)
    +
    4054 {
    +
    4055 _Assume_(text || start >= end);
    +
    4056
    +
    4057 const int space_match_flags = flags & ~match_multiline; // Spaces in dates must never be broken in new line.
    +
    4058 if ((m_format_mask & date_format_dmy) == date_format_dmy) {
    +
    4059 if (day->match(text, start, end, flags)) {
    +
    4060 for (this->interval.end = day->interval.end; m_space->match(text, this->interval.end, end, space_match_flags); this->interval.end = m_space->interval.end);
    +
    4061 if (m_separator->match(text, this->interval.end, end, flags)) {
    +
    4062 size_t hit_offset = m_separator->hit_offset;
    +
    4063 for (this->interval.end = m_separator->interval.end; m_space->match(text, this->interval.end, end, space_match_flags); this->interval.end = m_space->interval.end);
    +
    4064 if (month->match(text, this->interval.end, end, flags)) {
    +
    4065 for (this->interval.end = month->interval.end; m_space->match(text, this->interval.end, end, space_match_flags); this->interval.end = m_space->interval.end);
    +
    4066 if (m_separator->match(text, this->interval.end, end, flags) &&
    +
    4067 m_separator->hit_offset == hit_offset) // Both separators must match.
    +
    4068 {
    +
    4069 for (this->interval.end = m_separator->interval.end; m_space->match(text, this->interval.end, end, space_match_flags); this->interval.end = m_space->interval.end);
    +
    4070 if (year->match(text, this->interval.end, end, flags) &&
    +
    4071 is_valid(day->value, month->value))
    +
    4072 {
    +
    4073 this->interval.start = start;
    +
    4074 this->interval.end = year->interval.end;
    +
    4075 format = date_format_dmy;
    +
    4076 return true;
    +
    4077 }
    +
    4078 }
    +
    4079 }
    +
    4080 }
    +
    4081 }
    +
    4082 }
    +
    4083
    +
    4084 if ((m_format_mask & date_format_mdy) == date_format_mdy) {
    +
    4085 if (month->match(text, start, end, flags)) {
    +
    4086 for (this->interval.end = month->interval.end; m_space->match(text, this->interval.end, end, space_match_flags); this->interval.end = m_space->interval.end);
    +
    4087 if (m_separator->match(text, this->interval.end, end, flags)) {
    +
    4088 size_t hit_offset = m_separator->hit_offset;
    +
    4089 for (this->interval.end = m_separator->interval.end; m_space->match(text, this->interval.end, end, space_match_flags); this->interval.end = m_space->interval.end);
    +
    4090 if (day->match(text, this->interval.end, end, flags)) {
    +
    4091 for (this->interval.end = day->interval.end; m_space->match(text, this->interval.end, end, space_match_flags); this->interval.end = m_space->interval.end);
    +
    4092 if (m_separator->match(text, this->interval.end, end, flags) &&
    +
    4093 m_separator->hit_offset == hit_offset) // Both separators must match.
    +
    4094 {
    +
    4095 for (this->interval.end = m_separator->interval.end; m_space->match(text, this->interval.end, end, space_match_flags); this->interval.end = m_space->interval.end);
    +
    4096 if (year->match(text, this->interval.end, end, flags) &&
    +
    4097 is_valid(day->value, month->value))
    +
    4098 {
    +
    4099 this->interval.start = start;
    +
    4100 this->interval.end = year->interval.end;
    +
    4101 format = date_format_mdy;
    +
    4102 return true;
    +
    4103 }
    +
    4104 }
    +
    4105 }
    +
    4106 }
    +
    4107 }
    +
    4108 }
    +
    4109
    +
    4110 if ((m_format_mask & date_format_ymd) == date_format_ymd) {
    +
    4111 if (year->match(text, start, end, flags)) {
    +
    4112 for (this->interval.end = year->interval.end; m_space->match(text, this->interval.end, end, space_match_flags); this->interval.end = m_space->interval.end);
    +
    4113 if (m_separator->match(text, this->interval.end, end, flags)) {
    +
    4114 size_t hit_offset = m_separator->hit_offset;
    +
    4115 for (this->interval.end = m_separator->interval.end; m_space->match(text, this->interval.end, end, space_match_flags); this->interval.end = m_space->interval.end);
    +
    4116 if (month->match(text, this->interval.end, end, flags)) {
    +
    4117 for (this->interval.end = month->interval.end; m_space->match(text, this->interval.end, end, space_match_flags); this->interval.end = m_space->interval.end);
    +
    4118 if (m_separator->match(text, this->interval.end, end, flags) &&
    +
    4119 m_separator->hit_offset == hit_offset) // Both separators must match.
    +
    4120 {
    +
    4121 for (this->interval.end = m_separator->interval.end; m_space->match(text, this->interval.end, end, space_match_flags); this->interval.end = m_space->interval.end);
    +
    4122 if (day->match(text, this->interval.end, end, flags) &&
    +
    4123 is_valid(day->value, month->value))
    +
    4124 {
    +
    4125 this->interval.start = start;
    +
    4126 this->interval.end = day->interval.end;
    +
    4127 format = date_format_ymd;
    +
    4128 return true;
    +
    4129 }
    +
    4130 }
    +
    4131 }
    +
    4132 }
    +
    4133 }
    +
    4134 }
    +
    4135
    +
    4136 if ((m_format_mask & date_format_ym) == date_format_ym) {
    +
    4137 if (year->match(text, start, end, flags)) {
    +
    4138 for (this->interval.end = year->interval.end; m_space->match(text, this->interval.end, end, space_match_flags); this->interval.end = m_space->interval.end);
    +
    4139 if (m_separator->match(text, this->interval.end, end, flags)) {
    +
    4140 for (this->interval.end = m_separator->interval.end; m_space->match(text, this->interval.end, end, space_match_flags); this->interval.end = m_space->interval.end);
    +
    4141 if (month->match(text, this->interval.end, end, flags) &&
    +
    4142 is_valid((size_t)-1, month->value))
    +
    4143 {
    +
    4144 if (day) day->invalidate();
    +
    4145 this->interval.start = start;
    +
    4146 this->interval.end = month->interval.end;
    +
    4147 format = date_format_ym;
    +
    4148 return true;
    +
    4149 }
    +
    4150 }
    +
    4151 }
    +
    4152 }
    +
    4153
    +
    4154 if ((m_format_mask & date_format_my) == date_format_my) {
    +
    4155 if (month->match(text, start, end, flags)) {
    +
    4156 for (this->interval.end = month->interval.end; m_space->match(text, this->interval.end, end, space_match_flags); this->interval.end = m_space->interval.end);
    +
    4157 if (m_separator->match(text, this->interval.end, end, flags)) {
    +
    4158 for (this->interval.end = m_separator->interval.end; m_space->match(text, this->interval.end, end, space_match_flags); this->interval.end = m_space->interval.end);
    +
    4159 if (year->match(text, this->interval.end, end, flags) &&
    +
    4160 is_valid((size_t)-1, month->value))
    +
    4161 {
    +
    4162 if (day) day->invalidate();
    +
    4163 this->interval.start = start;
    +
    4164 this->interval.end = year->interval.end;
    +
    4165 format = date_format_my;
    +
    4166 return true;
    +
    4167 }
    +
    4168 }
    +
    4169 }
    +
    4170 }
    +
    4171
    +
    4172 if ((m_format_mask & date_format_dm) == date_format_dm) {
    +
    4173 if (day->match(text, start, end, flags)) {
    +
    4174 for (this->interval.end = day->interval.end; m_space->match(text, this->interval.end, end, space_match_flags); this->interval.end = m_space->interval.end);
    +
    4175 if (m_separator->match(text, this->interval.end, end, flags)) {
    +
    4176 size_t hit_offset = m_separator->hit_offset;
    +
    4177 for (this->interval.end = m_separator->interval.end; m_space->match(text, this->interval.end, end, space_match_flags); this->interval.end = m_space->interval.end);
    +
    4178 if (month->match(text, this->interval.end, end, flags) &&
    +
    4179 is_valid(day->value, month->value))
    +
    4180 {
    +
    4181 if (year) year->invalidate();
    +
    4182 this->interval.start = start;
    +
    4183 for (this->interval.end = month->interval.end; m_space->match(text, this->interval.end, end, space_match_flags); this->interval.end = m_space->interval.end);
    +
    4184 if (m_separator->match(text, this->interval.end, end, flags) &&
    +
    4185 m_separator->hit_offset == hit_offset) // Both separators must match.
    +
    4186 this->interval.end = m_separator->interval.end;
    +
    4187 else
    +
    4188 this->interval.end = month->interval.end;
    +
    4189 format = date_format_dm;
    +
    4190 return true;
    +
    4191 }
    +
    4192 }
    +
    4193 }
    +
    4194 }
    +
    4195
    +
    4196 if ((m_format_mask & date_format_md) == date_format_md) {
    +
    4197 if (month->match(text, start, end, flags)) {
    +
    4198 for (this->interval.end = month->interval.end; m_space->match(text, this->interval.end, end, space_match_flags); this->interval.end = m_space->interval.end);
    +
    4199 if (m_separator->match(text, this->interval.end, end, flags)) {
    +
    4200 size_t hit_offset = m_separator->hit_offset;
    +
    4201 for (this->interval.end = m_separator->interval.end; m_space->match(text, this->interval.end, end, space_match_flags); this->interval.end = m_space->interval.end);
    +
    4202 if (day->match(text, this->interval.end, end, flags) &&
    +
    4203 is_valid(day->value, month->value))
    +
    4204 {
    +
    4205 if (year) year->invalidate();
    +
    4206 this->interval.start = start;
    +
    4207 for (this->interval.end = day->interval.end; m_space->match(text, this->interval.end, end, space_match_flags); this->interval.end = m_space->interval.end);
    +
    4208 if (m_separator->match(text, this->interval.end, end, flags) &&
    +
    4209 m_separator->hit_offset == hit_offset) // Both separators must match.
    +
    4210 this->interval.end = m_separator->interval.end;
    +
    4211 else
    +
    4212 this->interval.end = day->interval.end;
    +
    4213 format = date_format_md;
    +
    4214 return true;
    +
    4215 }
    +
    4216 }
    +
    4217 }
    +
    4218 }
    +
    4219
    +
    4220 if (day) day->invalidate();
    +
    4221 if (month) month->invalidate();
    +
    4222 if (year) year->invalidate();
    +
    4223 format = date_format_none;
    +
    4224 this->interval.start = (this->interval.end = start) + 1;
    +
    4225 return false;
    +
    4226 }
    +
    4227
    +
    4228 virtual void invalidate()
    +
    4229 {
    +
    4230 if (day) day->invalidate();
    +
    4231 if (month) month->invalidate();
    +
    4232 if (year) year->invalidate();
    +
    4233 format = date_format_none;
    + +
    4235 }
    +
    4236
    +
    4237 protected:
    +
    4238 static inline bool is_valid(size_t day, size_t month)
    +
    4239 {
    +
    4240 if (month == (size_t)-1) {
    +
    4241 // Default to January. This allows validating day only, as January has all 31 days.
    +
    4242 month = 1;
    +
    4243 }
    +
    4244 if (day == (size_t)-1) {
    +
    4245 // Default to 1st day in month. This allows validating month only, as each month has 1st day.
    +
    4246 day = 1;
    +
    4247 }
    +
    4248
    +
    4249 switch (month) {
    +
    4250 case 1:
    +
    4251 case 3:
    +
    4252 case 5:
    +
    4253 case 7:
    +
    4254 case 8:
    +
    4255 case 10:
    +
    4256 case 12:
    +
    4257 return 1 <= day && day <= 31;
    +
    4258 case 2:
    +
    4259 return 1 <= day && day <= 29;
    +
    4260 case 4:
    +
    4261 case 6:
    +
    4262 case 9:
    +
    4263 case 11:
    +
    4264 return 1 <= day && day <= 30;
    +
    4265 default:
    +
    4266 return false;
    +
    4267 }
    +
    4268 }
    +
    4269
    +
    4270 public:
    +
    4271 date_format_t format;
    +
    4272 std::shared_ptr<basic_integer<T>> day;
    +
    4273 std::shared_ptr<basic_integer<T>> month;
    +
    4274 std::shared_ptr<basic_integer<T>> year;
    +
    4275
    +
    4276 protected:
    +
    4277 int m_format_mask;
    +
    4278 std::shared_ptr<basic_set<T>> m_separator;
    +
    4279 std::shared_ptr<basic_parser<T>> m_space;
    +
    4280 };
    -
    4284
    -
    4285 using date = basic_date<char>;
    -
    4286 using wdate = basic_date<wchar_t>;
    -
    4287#ifdef _UNICODE
    -
    4288 using tdate = wdate;
    -
    4289#else
    -
    4290 using tdate = date;
    -
    4291#endif
    - -
    4293
    -
    4297 template <class T>
    -
    -
    4298 class basic_time : public basic_parser<T>
    -
    4299 {
    -
    4300 public:
    -
    4301 basic_time(
    -
    4302 _In_ const std::shared_ptr<basic_integer10<T>>& _hour,
    -
    4303 _In_ const std::shared_ptr<basic_integer10<T>>& _minute,
    -
    4304 _In_ const std::shared_ptr<basic_integer10<T>>& _second,
    -
    4305 _In_ const std::shared_ptr<basic_integer10<T>>& _millisecond,
    -
    4306 _In_ const std::shared_ptr<basic_set<T>>& separator,
    -
    4307 _In_ const std::shared_ptr<basic_parser<T>>& millisecond_separator,
    -
    4308 _In_ const std::locale& locale = std::locale()) :
    -
    4309 basic_parser<T>(locale),
    -
    4310 hour(_hour),
    -
    4311 minute(_minute),
    -
    4312 second(_second),
    -
    4313 millisecond(_millisecond),
    -
    4314 m_separator(separator),
    -
    4315 m_millisecond_separator(millisecond_separator)
    -
    4316 {}
    -
    4317
    -
    4318 virtual bool match(
    -
    4319 _In_reads_or_z_(end) const T* text,
    -
    4320 _In_ size_t start = 0,
    -
    4321 _In_ size_t end = (size_t)-1,
    -
    4322 _In_ int flags = match_default)
    -
    4323 {
    -
    4324 _Assume_(text || start >= end);
    -
    4325
    -
    4326 if (hour->match(text, start, end, flags) &&
    -
    4327 m_separator->match(text, hour->interval.end, end, flags) &&
    -
    4328 minute->match(text, m_separator->interval.end, end, flags) &&
    -
    4329 minute->value < 60)
    -
    4330 {
    -
    4331 // hh::mm
    -
    4332 size_t hit_offset = m_separator->hit_offset;
    -
    4333 if (m_separator->match(text, minute->interval.end, end, flags) &&
    -
    4334 m_separator->hit_offset == hit_offset && // Both separators must match.
    -
    4335 second && second->match(text, m_separator->interval.end, end, flags) &&
    -
    4336 second->value < 60)
    -
    4337 {
    -
    4338 // hh::mm:ss
    -
    4339 if (m_millisecond_separator && m_millisecond_separator->match(text, second->interval.end, end, flags) &&
    -
    4340 millisecond && millisecond->match(text, m_millisecond_separator->interval.end, end, flags) &&
    -
    4341 millisecond->value < 1000)
    -
    4342 {
    -
    4343 // hh::mm:ss.mmmm
    -
    4344 this->interval.end = millisecond->interval.end;
    -
    4345 }
    -
    4346 else {
    -
    4347 if (millisecond) millisecond->invalidate();
    -
    4348 this->interval.end = second->interval.end;
    -
    4349 }
    -
    4350 }
    -
    4351 else {
    -
    4352 if (second) second->invalidate();
    -
    4353 if (millisecond) millisecond->invalidate();
    -
    4354 this->interval.end = minute->interval.end;
    -
    4355 }
    -
    4356 this->interval.start = start;
    -
    4357 return true;
    -
    4358 }
    -
    4359
    -
    4360 hour->invalidate();
    -
    4361 minute->invalidate();
    -
    4362 if (second) second->invalidate();
    -
    4363 if (millisecond) millisecond->invalidate();
    -
    4364 this->interval.start = (this->interval.end = start) + 1;
    -
    4365 return false;
    -
    4366 }
    -
    4367
    -
    4368 virtual void invalidate()
    -
    4369 {
    -
    4370 hour->invalidate();
    -
    4371 minute->invalidate();
    -
    4372 if (second) second->invalidate();
    -
    4373 if (millisecond) millisecond->invalidate();
    - -
    4375 }
    -
    4376
    -
    4377 public:
    -
    4378 std::shared_ptr<basic_integer10<T>> hour;
    -
    4379 std::shared_ptr<basic_integer10<T>> minute;
    -
    4380 std::shared_ptr<basic_integer10<T>> second;
    -
    4381 std::shared_ptr<basic_integer10<T>> millisecond;
    -
    4382
    -
    4383 protected:
    -
    4384 std::shared_ptr<basic_set<T>> m_separator;
    -
    4385 std::shared_ptr<basic_parser<T>> m_millisecond_separator;
    -
    4386 };
    +
    4281
    +
    4282 using date = basic_date<char>;
    +
    4283 using wdate = basic_date<wchar_t>;
    +
    4284#ifdef _UNICODE
    +
    4285 using tdate = wdate;
    +
    4286#else
    +
    4287 using tdate = date;
    +
    4288#endif
    + +
    4290
    +
    4294 template <class T>
    +
    +
    4295 class basic_time : public basic_parser<T>
    +
    4296 {
    +
    4297 public:
    +
    4298 basic_time(
    +
    4299 _In_ const std::shared_ptr<basic_integer10<T>>& _hour,
    +
    4300 _In_ const std::shared_ptr<basic_integer10<T>>& _minute,
    +
    4301 _In_ const std::shared_ptr<basic_integer10<T>>& _second,
    +
    4302 _In_ const std::shared_ptr<basic_integer10<T>>& _millisecond,
    +
    4303 _In_ const std::shared_ptr<basic_set<T>>& separator,
    +
    4304 _In_ const std::shared_ptr<basic_parser<T>>& millisecond_separator,
    +
    4305 _In_ const std::locale& locale = std::locale()) :
    +
    4306 basic_parser<T>(locale),
    +
    4307 hour(_hour),
    +
    4308 minute(_minute),
    +
    4309 second(_second),
    +
    4310 millisecond(_millisecond),
    +
    4311 m_separator(separator),
    +
    4312 m_millisecond_separator(millisecond_separator)
    +
    4313 {}
    +
    4314
    +
    4315 virtual bool match(
    +
    4316 _In_reads_or_z_(end) const T* text,
    +
    4317 _In_ size_t start = 0,
    +
    4318 _In_ size_t end = (size_t)-1,
    +
    4319 _In_ int flags = match_default)
    +
    4320 {
    +
    4321 _Assume_(text || start >= end);
    +
    4322
    +
    4323 if (hour->match(text, start, end, flags) &&
    +
    4324 m_separator->match(text, hour->interval.end, end, flags) &&
    +
    4325 minute->match(text, m_separator->interval.end, end, flags) &&
    +
    4326 minute->value < 60)
    +
    4327 {
    +
    4328 // hh::mm
    +
    4329 size_t hit_offset = m_separator->hit_offset;
    +
    4330 if (m_separator->match(text, minute->interval.end, end, flags) &&
    +
    4331 m_separator->hit_offset == hit_offset && // Both separators must match.
    +
    4332 second && second->match(text, m_separator->interval.end, end, flags) &&
    +
    4333 second->value < 60)
    +
    4334 {
    +
    4335 // hh::mm:ss
    +
    4336 if (m_millisecond_separator && m_millisecond_separator->match(text, second->interval.end, end, flags) &&
    +
    4337 millisecond && millisecond->match(text, m_millisecond_separator->interval.end, end, flags) &&
    +
    4338 millisecond->value < 1000)
    +
    4339 {
    +
    4340 // hh::mm:ss.mmmm
    +
    4341 this->interval.end = millisecond->interval.end;
    +
    4342 }
    +
    4343 else {
    +
    4344 if (millisecond) millisecond->invalidate();
    +
    4345 this->interval.end = second->interval.end;
    +
    4346 }
    +
    4347 }
    +
    4348 else {
    +
    4349 if (second) second->invalidate();
    +
    4350 if (millisecond) millisecond->invalidate();
    +
    4351 this->interval.end = minute->interval.end;
    +
    4352 }
    +
    4353 this->interval.start = start;
    +
    4354 return true;
    +
    4355 }
    +
    4356
    +
    4357 hour->invalidate();
    +
    4358 minute->invalidate();
    +
    4359 if (second) second->invalidate();
    +
    4360 if (millisecond) millisecond->invalidate();
    +
    4361 this->interval.start = (this->interval.end = start) + 1;
    +
    4362 return false;
    +
    4363 }
    +
    4364
    +
    4365 virtual void invalidate()
    +
    4366 {
    +
    4367 hour->invalidate();
    +
    4368 minute->invalidate();
    +
    4369 if (second) second->invalidate();
    +
    4370 if (millisecond) millisecond->invalidate();
    + +
    4372 }
    +
    4373
    +
    4374 public:
    +
    4375 std::shared_ptr<basic_integer10<T>> hour;
    +
    4376 std::shared_ptr<basic_integer10<T>> minute;
    +
    4377 std::shared_ptr<basic_integer10<T>> second;
    +
    4378 std::shared_ptr<basic_integer10<T>> millisecond;
    +
    4379
    +
    4380 protected:
    +
    4381 std::shared_ptr<basic_set<T>> m_separator;
    +
    4382 std::shared_ptr<basic_parser<T>> m_millisecond_separator;
    +
    4383 };
    -
    4387
    -
    4388 using time = basic_time<char>;
    -
    4389 using wtime = basic_time<wchar_t>;
    -
    4390#ifdef _UNICODE
    -
    4391 using ttime = wtime;
    -
    4392#else
    -
    4393 using ttime = time;
    -
    4394#endif
    - -
    4396
    -
    4400 template <class T>
    -
    -
    4401 class basic_angle : public basic_parser<T>
    -
    4402 {
    -
    4403 public:
    - -
    4405 _In_ const std::shared_ptr<basic_integer10<T>>& _degree,
    -
    4406 _In_ const std::shared_ptr<basic_parser<T>>& _degree_separator,
    -
    4407 _In_ const std::shared_ptr<basic_integer10<T>>& _minute,
    -
    4408 _In_ const std::shared_ptr<basic_parser<T>>& _minute_separator,
    -
    4409 _In_ const std::shared_ptr<basic_integer10<T>>& _second,
    -
    4410 _In_ const std::shared_ptr<basic_parser<T>>& _second_separator,
    -
    4411 _In_ const std::shared_ptr<basic_parser<T>>& _decimal,
    -
    4412 _In_ const std::locale& locale = std::locale()) :
    -
    4413 basic_parser<T>(locale),
    -
    4414 degree(_degree),
    -
    4415 degree_separator(_degree_separator),
    -
    4416 minute(_minute),
    -
    4417 minute_separator(_minute_separator),
    -
    4418 second(_second),
    -
    4419 second_separator(_second_separator),
    -
    4420 decimal(_decimal)
    -
    4421 {}
    -
    4422
    -
    4423 virtual bool match(
    -
    4424 _In_reads_or_z_(end) const T* text,
    -
    4425 _In_ size_t start = 0,
    -
    4426 _In_ size_t end = (size_t)-1,
    -
    4427 _In_ int flags = match_default)
    -
    4428 {
    -
    4429 _Assume_(text || start >= end);
    -
    4430
    -
    4431 this->interval.end = start;
    -
    4432
    -
    4433 if (degree->match(text, this->interval.end, end, flags) &&
    -
    4434 degree_separator->match(text, degree->interval.end, end, flags))
    -
    4435 {
    -
    4436 // Degrees
    -
    4437 this->interval.end = degree_separator->interval.end;
    -
    4438 }
    -
    4439 else {
    -
    4440 degree->invalidate();
    -
    4441 degree_separator->invalidate();
    -
    4442 }
    -
    4443
    -
    4444 if (minute->match(text, this->interval.end, end, flags) &&
    -
    4445 minute->value < 60 &&
    -
    4446 minute_separator->match(text, minute->interval.end, end, flags))
    -
    4447 {
    -
    4448 // Minutes
    -
    4449 this->interval.end = minute_separator->interval.end;
    -
    4450 }
    -
    4451 else {
    -
    4452 minute->invalidate();
    -
    4453 minute_separator->invalidate();
    -
    4454 }
    -
    4455
    -
    4456 if (second && second->match(text, this->interval.end, end, flags) &&
    -
    4457 second->value < 60)
    -
    4458 {
    -
    4459 // Seconds
    -
    4460 this->interval.end = second->interval.end;
    -
    4461 if (second_separator && second_separator->match(text, this->interval.end, end, flags))
    -
    4462 this->interval.end = second_separator->interval.end;
    -
    4463 else
    -
    4464 if (second_separator) second_separator->invalidate();
    -
    4465 }
    -
    4466 else {
    -
    4467 if (second) second->invalidate();
    -
    4468 if (second_separator) second_separator->invalidate();
    -
    4469 }
    -
    4470
    -
    4471 if (degree->interval.start < degree->interval.end ||
    -
    4472 minute->interval.start < minute->interval.end ||
    -
    4473 (second && second->interval.start < second->interval.end))
    -
    4474 {
    -
    4475 if (decimal && decimal->match(text, this->interval.end, end, flags)) {
    -
    4476 // Decimals
    -
    4477 this->interval.end = decimal->interval.end;
    -
    4478 }
    -
    4479 else if (decimal)
    -
    4480 decimal->invalidate();
    -
    4481 this->interval.start = start;
    -
    4482 return true;
    -
    4483 }
    -
    4484 if (decimal) decimal->invalidate();
    -
    4485 this->interval.start = (this->interval.end = start) + 1;
    -
    4486 return false;
    -
    4487 }
    -
    4488
    -
    4489 virtual void invalidate()
    -
    4490 {
    -
    4491 degree->invalidate();
    -
    4492 degree_separator->invalidate();
    -
    4493 minute->invalidate();
    -
    4494 minute_separator->invalidate();
    -
    4495 if (second) second->invalidate();
    -
    4496 if (second_separator) second_separator->invalidate();
    -
    4497 if (decimal) decimal->invalidate();
    - -
    4499 }
    -
    4500
    -
    4501 public:
    -
    4502 std::shared_ptr<basic_integer10<T>> degree;
    -
    4503 std::shared_ptr<basic_parser<T>> degree_separator;
    -
    4504 std::shared_ptr<basic_integer10<T>> minute;
    -
    4505 std::shared_ptr<basic_parser<T>> minute_separator;
    -
    4506 std::shared_ptr<basic_integer10<T>> second;
    -
    4507 std::shared_ptr<basic_parser<T>> second_separator;
    -
    4508 std::shared_ptr<basic_parser<T>> decimal;
    -
    4509 };
    +
    4384
    +
    4385 using time = basic_time<char>;
    +
    4386 using wtime = basic_time<wchar_t>;
    +
    4387#ifdef _UNICODE
    +
    4388 using ttime = wtime;
    +
    4389#else
    +
    4390 using ttime = time;
    +
    4391#endif
    + +
    4393
    +
    4397 template <class T>
    +
    +
    4398 class basic_angle : public basic_parser<T>
    +
    4399 {
    +
    4400 public:
    + +
    4402 _In_ const std::shared_ptr<basic_integer10<T>>& _degree,
    +
    4403 _In_ const std::shared_ptr<basic_parser<T>>& _degree_separator,
    +
    4404 _In_ const std::shared_ptr<basic_integer10<T>>& _minute,
    +
    4405 _In_ const std::shared_ptr<basic_parser<T>>& _minute_separator,
    +
    4406 _In_ const std::shared_ptr<basic_integer10<T>>& _second,
    +
    4407 _In_ const std::shared_ptr<basic_parser<T>>& _second_separator,
    +
    4408 _In_ const std::shared_ptr<basic_parser<T>>& _decimal,
    +
    4409 _In_ const std::locale& locale = std::locale()) :
    +
    4410 basic_parser<T>(locale),
    +
    4411 degree(_degree),
    +
    4412 degree_separator(_degree_separator),
    +
    4413 minute(_minute),
    +
    4414 minute_separator(_minute_separator),
    +
    4415 second(_second),
    +
    4416 second_separator(_second_separator),
    +
    4417 decimal(_decimal)
    +
    4418 {}
    +
    4419
    +
    4420 virtual bool match(
    +
    4421 _In_reads_or_z_(end) const T* text,
    +
    4422 _In_ size_t start = 0,
    +
    4423 _In_ size_t end = (size_t)-1,
    +
    4424 _In_ int flags = match_default)
    +
    4425 {
    +
    4426 _Assume_(text || start >= end);
    +
    4427
    +
    4428 this->interval.end = start;
    +
    4429
    +
    4430 if (degree->match(text, this->interval.end, end, flags) &&
    +
    4431 degree_separator->match(text, degree->interval.end, end, flags))
    +
    4432 {
    +
    4433 // Degrees
    +
    4434 this->interval.end = degree_separator->interval.end;
    +
    4435 }
    +
    4436 else {
    +
    4437 degree->invalidate();
    +
    4438 degree_separator->invalidate();
    +
    4439 }
    +
    4440
    +
    4441 if (minute->match(text, this->interval.end, end, flags) &&
    +
    4442 minute->value < 60 &&
    +
    4443 minute_separator->match(text, minute->interval.end, end, flags))
    +
    4444 {
    +
    4445 // Minutes
    +
    4446 this->interval.end = minute_separator->interval.end;
    +
    4447 }
    +
    4448 else {
    +
    4449 minute->invalidate();
    +
    4450 minute_separator->invalidate();
    +
    4451 }
    +
    4452
    +
    4453 if (second && second->match(text, this->interval.end, end, flags) &&
    +
    4454 second->value < 60)
    +
    4455 {
    +
    4456 // Seconds
    +
    4457 this->interval.end = second->interval.end;
    +
    4458 if (second_separator && second_separator->match(text, this->interval.end, end, flags))
    +
    4459 this->interval.end = second_separator->interval.end;
    +
    4460 else
    +
    4461 if (second_separator) second_separator->invalidate();
    +
    4462 }
    +
    4463 else {
    +
    4464 if (second) second->invalidate();
    +
    4465 if (second_separator) second_separator->invalidate();
    +
    4466 }
    +
    4467
    +
    4468 if (degree->interval.start < degree->interval.end ||
    +
    4469 minute->interval.start < minute->interval.end ||
    +
    4470 (second && second->interval.start < second->interval.end))
    +
    4471 {
    +
    4472 if (decimal && decimal->match(text, this->interval.end, end, flags)) {
    +
    4473 // Decimals
    +
    4474 this->interval.end = decimal->interval.end;
    +
    4475 }
    +
    4476 else if (decimal)
    +
    4477 decimal->invalidate();
    +
    4478 this->interval.start = start;
    +
    4479 return true;
    +
    4480 }
    +
    4481 if (decimal) decimal->invalidate();
    +
    4482 this->interval.start = (this->interval.end = start) + 1;
    +
    4483 return false;
    +
    4484 }
    +
    4485
    +
    4486 virtual void invalidate()
    +
    4487 {
    +
    4488 degree->invalidate();
    +
    4489 degree_separator->invalidate();
    +
    4490 minute->invalidate();
    +
    4491 minute_separator->invalidate();
    +
    4492 if (second) second->invalidate();
    +
    4493 if (second_separator) second_separator->invalidate();
    +
    4494 if (decimal) decimal->invalidate();
    + +
    4496 }
    +
    4497
    +
    4498 public:
    +
    4499 std::shared_ptr<basic_integer10<T>> degree;
    +
    4500 std::shared_ptr<basic_parser<T>> degree_separator;
    +
    4501 std::shared_ptr<basic_integer10<T>> minute;
    +
    4502 std::shared_ptr<basic_parser<T>> minute_separator;
    +
    4503 std::shared_ptr<basic_integer10<T>> second;
    +
    4504 std::shared_ptr<basic_parser<T>> second_separator;
    +
    4505 std::shared_ptr<basic_parser<T>> decimal;
    +
    4506 };
    -
    4510
    -
    4511 using angle = basic_angle<char>;
    - -
    4513#ifdef _UNICODE
    -
    4514 using RRegElKot = wangle;
    -
    4515#else
    -
    4516 using RRegElKot = angle;
    -
    4517#endif
    - -
    4519
    -
    4523 template <class T>
    -
    - -
    4525 {
    -
    4526 public:
    - -
    4528 _In_ const std::shared_ptr<basic_parser<T>>& digit,
    -
    4529 _In_ const std::shared_ptr<basic_parser<T>>& plus_sign,
    -
    4530 _In_ const std::shared_ptr<basic_set<T>>& lparenthesis,
    -
    4531 _In_ const std::shared_ptr<basic_set<T>>& rparenthesis,
    -
    4532 _In_ const std::shared_ptr<basic_parser<T>>& separator,
    -
    4533 _In_ const std::shared_ptr<basic_parser<T>>& space,
    -
    4534 _In_ const std::locale& locale = std::locale()) :
    -
    4535 basic_parser<T>(locale),
    -
    4536 m_digit(digit),
    -
    4537 m_plus_sign(plus_sign),
    -
    4538 m_lparenthesis(lparenthesis),
    -
    4539 m_rparenthesis(rparenthesis),
    -
    4540 m_separator(separator),
    -
    4541 m_space(space)
    -
    4542 {}
    -
    4543
    -
    4544 virtual bool match(
    -
    4545 _In_reads_or_z_(end) const T* text,
    -
    4546 _In_ size_t start = 0,
    -
    4547 _In_ size_t end = (size_t)-1,
    -
    4548 _In_ int flags = match_default)
    -
    4549 {
    -
    4550 _Assume_(text || start >= end);
    -
    4551
    -
    4552 size_t safe_digit_end = start, safe_value_size = 0;
    -
    4553 bool has_digits = false, after_digit = false, in_parentheses = false, after_parentheses = false;
    -
    4554 const int space_match_flags = flags & ~match_multiline; // Spaces in phone numbers must never be broken in new line.
    -
    4555
    -
    4556 this->interval.end = start;
    -
    4557 value.clear();
    -
    4558 m_lparenthesis->invalidate();
    -
    4559 m_rparenthesis->invalidate();
    -
    4560
    -
    4561 if (m_plus_sign && m_plus_sign->match(text, this->interval.end, end, flags)) {
    -
    4562 value.append(text + m_plus_sign->interval.start, text + m_plus_sign->interval.end);
    -
    4563 safe_value_size = value.size();
    -
    4564 this->interval.end = m_plus_sign->interval.end;
    -
    4565 }
    -
    4566
    -
    4567 for (;;) {
    -
    4568 _Assume_(text || this->interval.end >= end);
    -
    4569 if (this->interval.end >= end || !text[this->interval.end])
    -
    4570 break;
    -
    4571 if (m_digit->match(text, this->interval.end, end, flags)) {
    -
    4572 // Digit
    -
    4573 value.append(text + m_digit->interval.start, text + m_digit->interval.end);
    -
    4574 this->interval.end = m_digit->interval.end;
    -
    4575 if (!in_parentheses) {
    -
    4576 safe_digit_end = this->interval.end;
    -
    4577 safe_value_size = value.size();
    -
    4578 has_digits = true;
    -
    4579 }
    -
    4580 after_digit = true;
    -
    4581 after_parentheses = false;
    -
    4582 }
    -
    4583 else if (
    -
    4584 m_lparenthesis && !m_lparenthesis->interval && // No left parenthesis yet
    -
    4585 m_rparenthesis && !m_rparenthesis->interval && // Right parenthesis after left
    -
    4586 m_lparenthesis->match(text, this->interval.end, end, flags))
    -
    4587 {
    -
    4588 // Left parenthesis
    -
    4589 value.append(text + m_lparenthesis->interval.start, m_lparenthesis->interval.size());
    -
    4590 this->interval.end = m_lparenthesis->interval.end;
    -
    4591 in_parentheses = true;
    -
    4592 after_digit = false;
    -
    4593 after_parentheses = false;
    -
    4594 }
    -
    4595 else if (
    -
    4596 in_parentheses && // After left parenthesis
    -
    4597 m_rparenthesis && !m_rparenthesis->interval && // No right parenthesis yet
    -
    4598 m_rparenthesis->match(text, this->interval.end, end, flags) &&
    -
    4599 m_lparenthesis->hit_offset == m_rparenthesis->hit_offset) // Left and right parentheses must match
    -
    4600 {
    -
    4601 // Right parenthesis
    -
    4602 value.append(text + m_rparenthesis->interval.start, text + m_rparenthesis->interval.end);
    -
    4603 this->interval.end = m_rparenthesis->interval.end;
    -
    4604 safe_digit_end = this->interval.end;
    -
    4605 safe_value_size = value.size();
    -
    4606 in_parentheses = false;
    -
    4607 after_digit = false;
    -
    4608 after_parentheses = true;
    -
    4609 }
    -
    4610 else if (
    -
    4611 after_digit &&
    -
    4612 !in_parentheses && // No separators inside parentheses
    -
    4613 !after_parentheses && // No separators following right parenthesis
    -
    4614 m_separator && m_separator->match(text, this->interval.end, end, flags))
    -
    4615 {
    -
    4616 // Separator
    -
    4617 this->interval.end = m_separator->interval.end;
    -
    4618 after_digit = false;
    -
    4619 after_parentheses = false;
    -
    4620 }
    -
    4621 else if (
    - -
    4623 m_space && m_space->match(text, this->interval.end, end, space_match_flags))
    -
    4624 {
    -
    4625 // Space
    -
    4626 this->interval.end = m_space->interval.end;
    -
    4627 after_digit = false;
    -
    4628 after_parentheses = false;
    -
    4629 }
    -
    4630 else
    -
    4631 break;
    -
    4632 }
    -
    4633 if (has_digits) {
    -
    4634 value.erase(safe_value_size);
    -
    4635 this->interval.start = start;
    -
    4636 this->interval.end = safe_digit_end;
    -
    4637 return true;
    -
    4638 }
    -
    4639 value.clear();
    -
    4640 this->interval.start = (this->interval.end = start) + 1;
    -
    4641 return false;
    -
    4642 }
    -
    4643
    -
    4644 virtual void invalidate()
    -
    4645 {
    -
    4646 value.clear();
    - -
    4648 }
    +
    4507
    +
    4508 using angle = basic_angle<char>;
    + +
    4510#ifdef _UNICODE
    +
    4511 using RRegElKot = wangle;
    +
    4512#else
    +
    4513 using RRegElKot = angle;
    +
    4514#endif
    + +
    4516
    +
    4520 template <class T>
    +
    + +
    4522 {
    +
    4523 public:
    + +
    4525 _In_ const std::shared_ptr<basic_parser<T>>& digit,
    +
    4526 _In_ const std::shared_ptr<basic_parser<T>>& plus_sign,
    +
    4527 _In_ const std::shared_ptr<basic_set<T>>& lparenthesis,
    +
    4528 _In_ const std::shared_ptr<basic_set<T>>& rparenthesis,
    +
    4529 _In_ const std::shared_ptr<basic_parser<T>>& separator,
    +
    4530 _In_ const std::shared_ptr<basic_parser<T>>& space,
    +
    4531 _In_ const std::locale& locale = std::locale()) :
    +
    4532 basic_parser<T>(locale),
    +
    4533 m_digit(digit),
    +
    4534 m_plus_sign(plus_sign),
    +
    4535 m_lparenthesis(lparenthesis),
    +
    4536 m_rparenthesis(rparenthesis),
    +
    4537 m_separator(separator),
    +
    4538 m_space(space)
    +
    4539 {}
    +
    4540
    +
    4541 virtual bool match(
    +
    4542 _In_reads_or_z_(end) const T* text,
    +
    4543 _In_ size_t start = 0,
    +
    4544 _In_ size_t end = (size_t)-1,
    +
    4545 _In_ int flags = match_default)
    +
    4546 {
    +
    4547 _Assume_(text || start >= end);
    +
    4548
    +
    4549 size_t safe_digit_end = start, safe_value_size = 0;
    +
    4550 bool has_digits = false, after_digit = false, in_parentheses = false, after_parentheses = false;
    +
    4551 const int space_match_flags = flags & ~match_multiline; // Spaces in phone numbers must never be broken in new line.
    +
    4552
    +
    4553 this->interval.end = start;
    +
    4554 value.clear();
    +
    4555 m_lparenthesis->invalidate();
    +
    4556 m_rparenthesis->invalidate();
    +
    4557
    +
    4558 if (m_plus_sign && m_plus_sign->match(text, this->interval.end, end, flags)) {
    +
    4559 value.append(text + m_plus_sign->interval.start, text + m_plus_sign->interval.end);
    +
    4560 safe_value_size = value.size();
    +
    4561 this->interval.end = m_plus_sign->interval.end;
    +
    4562 }
    +
    4563
    +
    4564 for (;;) {
    +
    4565 _Assume_(text || this->interval.end >= end);
    +
    4566 if (this->interval.end >= end || !text[this->interval.end])
    +
    4567 break;
    +
    4568 if (m_digit->match(text, this->interval.end, end, flags)) {
    +
    4569 // Digit
    +
    4570 value.append(text + m_digit->interval.start, text + m_digit->interval.end);
    +
    4571 this->interval.end = m_digit->interval.end;
    +
    4572 if (!in_parentheses) {
    +
    4573 safe_digit_end = this->interval.end;
    +
    4574 safe_value_size = value.size();
    +
    4575 has_digits = true;
    +
    4576 }
    +
    4577 after_digit = true;
    +
    4578 after_parentheses = false;
    +
    4579 }
    +
    4580 else if (
    +
    4581 m_lparenthesis && !m_lparenthesis->interval && // No left parenthesis yet
    +
    4582 m_rparenthesis && !m_rparenthesis->interval && // Right parenthesis after left
    +
    4583 m_lparenthesis->match(text, this->interval.end, end, flags))
    +
    4584 {
    +
    4585 // Left parenthesis
    +
    4586 value.append(text + m_lparenthesis->interval.start, m_lparenthesis->interval.size());
    +
    4587 this->interval.end = m_lparenthesis->interval.end;
    +
    4588 in_parentheses = true;
    +
    4589 after_digit = false;
    +
    4590 after_parentheses = false;
    +
    4591 }
    +
    4592 else if (
    +
    4593 in_parentheses && // After left parenthesis
    +
    4594 m_rparenthesis && !m_rparenthesis->interval && // No right parenthesis yet
    +
    4595 m_rparenthesis->match(text, this->interval.end, end, flags) &&
    +
    4596 m_lparenthesis->hit_offset == m_rparenthesis->hit_offset) // Left and right parentheses must match
    +
    4597 {
    +
    4598 // Right parenthesis
    +
    4599 value.append(text + m_rparenthesis->interval.start, text + m_rparenthesis->interval.end);
    +
    4600 this->interval.end = m_rparenthesis->interval.end;
    +
    4601 safe_digit_end = this->interval.end;
    +
    4602 safe_value_size = value.size();
    +
    4603 in_parentheses = false;
    +
    4604 after_digit = false;
    +
    4605 after_parentheses = true;
    +
    4606 }
    +
    4607 else if (
    +
    4608 after_digit &&
    +
    4609 !in_parentheses && // No separators inside parentheses
    +
    4610 !after_parentheses && // No separators following right parenthesis
    +
    4611 m_separator && m_separator->match(text, this->interval.end, end, flags))
    +
    4612 {
    +
    4613 // Separator
    +
    4614 this->interval.end = m_separator->interval.end;
    +
    4615 after_digit = false;
    +
    4616 after_parentheses = false;
    +
    4617 }
    +
    4618 else if (
    + +
    4620 m_space && m_space->match(text, this->interval.end, end, space_match_flags))
    +
    4621 {
    +
    4622 // Space
    +
    4623 this->interval.end = m_space->interval.end;
    +
    4624 after_digit = false;
    +
    4625 after_parentheses = false;
    +
    4626 }
    +
    4627 else
    +
    4628 break;
    +
    4629 }
    +
    4630 if (has_digits) {
    +
    4631 value.erase(safe_value_size);
    +
    4632 this->interval.start = start;
    +
    4633 this->interval.end = safe_digit_end;
    +
    4634 return true;
    +
    4635 }
    +
    4636 value.clear();
    +
    4637 this->interval.start = (this->interval.end = start) + 1;
    +
    4638 return false;
    +
    4639 }
    +
    4640
    +
    4641 virtual void invalidate()
    +
    4642 {
    +
    4643 value.clear();
    + +
    4645 }
    +
    4646
    +
    4647 public:
    +
    4648 std::basic_string<T> value;
    4649
    -
    4650 public:
    -
    4651 std::basic_string<T> value;
    -
    4652
    -
    4653 protected:
    -
    4654 std::shared_ptr<basic_parser<T>> m_digit;
    -
    4655 std::shared_ptr<basic_parser<T>> m_plus_sign;
    -
    4656 std::shared_ptr<basic_set<T>> m_lparenthesis;
    -
    4657 std::shared_ptr<basic_set<T>> m_rparenthesis;
    -
    4658 std::shared_ptr<basic_parser<T>> m_separator;
    -
    4659 std::shared_ptr<basic_parser<T>> m_space;
    -
    4660 };
    +
    4650 protected:
    +
    4651 std::shared_ptr<basic_parser<T>> m_digit;
    +
    4652 std::shared_ptr<basic_parser<T>> m_plus_sign;
    +
    4653 std::shared_ptr<basic_set<T>> m_lparenthesis;
    +
    4654 std::shared_ptr<basic_set<T>> m_rparenthesis;
    +
    4655 std::shared_ptr<basic_parser<T>> m_separator;
    +
    4656 std::shared_ptr<basic_parser<T>> m_space;
    +
    4657 };
    -
    4661
    - - -
    4664#ifdef _UNICODE
    - -
    4666#else
    - -
    4668#endif
    - -
    4670
    -
    4676 template <class T>
    -
    -
    4677 class basic_iban : public basic_parser<T>
    -
    4678 {
    -
    4679 public:
    -
    4680 basic_iban(
    -
    4681 _In_ const std::shared_ptr<basic_parser<T>>& space,
    -
    4682 _In_ const std::locale& locale = std::locale()) :
    -
    4683 basic_parser<T>(locale),
    -
    4684 m_space(space)
    -
    4685 {
    -
    4686 this->country[0] = 0;
    -
    4687 this->check_digits[0] = 0;
    -
    4688 this->bban[0] = 0;
    -
    4689 this->is_valid = false;
    -
    4690 }
    -
    4691
    -
    4692 virtual bool match(
    -
    4693 _In_reads_or_z_(end) const T* text,
    -
    4694 _In_ size_t start = 0,
    -
    4695 _In_ size_t end = (size_t)-1,
    -
    4696 _In_ int flags = match_default)
    -
    4697 {
    -
    4698 _Assume_(text || start >= end);
    -
    4699 const auto& ctype = std::use_facet<std::ctype<T>>(this->m_locale);
    -
    4700 const bool case_insensitive = flags & match_case_insensitive ? true : false;
    -
    4701 struct country_t {
    -
    4702 T country[2];
    -
    4703 T check_digits[2];
    -
    4704 size_t length;
    -
    4705 };
    -
    4706 static const country_t s_countries[] = {
    -
    4707 { { 'A', 'D' }, {}, 24 }, // Andorra
    -
    4708 { { 'A', 'E' }, {}, 23 }, // United Arab Emirates
    -
    4709 { { 'A', 'L' }, {}, 28 }, // Albania
    -
    4710 { { 'A', 'O' }, {}, 25 }, // Angola
    -
    4711 { { 'A', 'T' }, {}, 20 }, // Austria
    -
    4712 { { 'A', 'Z' }, {}, 28 }, // Azerbaijan
    -
    4713 { { 'B', 'A' }, { '3', '9' }, 20}, // Bosnia and Herzegovina
    -
    4714 { { 'B', 'E' }, {}, 16 }, // Belgium
    -
    4715 { { 'B', 'F' }, {}, 28 }, // Burkina Faso
    -
    4716 { { 'B', 'G' }, {}, 22 }, // Bulgaria
    -
    4717 { { 'B', 'H' }, {}, 22 }, // Bahrain
    -
    4718 { { 'B', 'I' }, {}, 27 }, // Burundi
    -
    4719 { { 'B', 'J' }, {}, 28 }, // Benin
    -
    4720 { { 'B', 'R' }, {}, 29 }, // Brazil
    -
    4721 { { 'B', 'Y' }, {}, 28 }, // Belarus
    -
    4722 { { 'C', 'F' }, {}, 27 }, // Central African Republic
    -
    4723 { { 'C', 'G' }, {}, 27 }, // Congo, Republic of the
    -
    4724 { { 'C', 'H' }, {}, 21 }, // Switzerland
    -
    4725 { { 'C', 'I' }, {}, 28 }, // Côte d'Ivoire
    -
    4726 { { 'C', 'M' }, {}, 27 }, // Cameroon
    -
    4727 { { 'C', 'R' }, {}, 22 }, // Costa Rica
    -
    4728 { { 'C', 'V' }, {}, 25 }, // Cabo Verde
    -
    4729 { { 'C', 'Y' }, {}, 28 }, // Cyprus
    -
    4730 { { 'C', 'Z' }, {}, 24 }, // Czech Republic
    -
    4731 { { 'D', 'E' }, {}, 22 }, // Germany
    -
    4732 { { 'D', 'J' }, {}, 27 }, // Djibouti
    -
    4733 { { 'D', 'K' }, {}, 18 }, // Denmark
    -
    4734 { { 'D', 'O' }, {}, 28 }, // Dominican Republic
    -
    4735 { { 'D', 'Z' }, {}, 26 }, // Algeria
    -
    4736 { { 'E', 'E' }, {}, 20 }, // Estonia
    -
    4737 { { 'E', 'G' }, {}, 29 }, // Egypt
    -
    4738 { { 'E', 'S' }, {}, 24 }, // Spain
    -
    4739 { { 'F', 'I' }, {}, 18 }, // Finland
    -
    4740 { { 'F', 'O' }, {}, 18 }, // Faroe Islands
    -
    4741 { { 'F', 'R' }, {}, 27 }, // France
    -
    4742 { { 'G', 'A' }, {}, 27 }, // Gabon
    -
    4743 { { 'G', 'B' }, {}, 22 }, // United Kingdom
    -
    4744 { { 'G', 'E' }, {}, 22 }, // Georgia
    -
    4745 { { 'G', 'I' }, {}, 23 }, // Gibraltar
    -
    4746 { { 'G', 'L' }, {}, 18 }, // Greenland
    -
    4747 { { 'G', 'Q' }, {}, 27 }, // Equatorial Guinea
    -
    4748 { { 'G', 'R' }, {}, 27 }, // Greece
    -
    4749 { { 'G', 'T' }, {}, 28 }, // Guatemala
    -
    4750 { { 'G', 'W' }, {}, 25 }, // Guinea-Bissau
    -
    4751 { { 'H', 'N' }, {}, 28 }, // Honduras
    -
    4752 { { 'H', 'R' }, {}, 21 }, // Croatia
    -
    4753 { { 'H', 'U' }, {}, 28 }, // Hungary
    -
    4754 { { 'I', 'E' }, {}, 22 }, // Ireland
    -
    4755 { { 'I', 'L' }, {}, 23 }, // Israel
    -
    4756 { { 'I', 'Q' }, {}, 23 }, // Iraq
    -
    4757 { { 'I', 'R' }, {}, 26 }, // Iran
    -
    4758 { { 'I', 'S' }, {}, 26 }, // Iceland
    -
    4759 { { 'I', 'T' }, {}, 27 }, // Italy
    -
    4760 { { 'J', 'O' }, {}, 30 }, // Jordan
    -
    4761 { { 'K', 'M' }, {}, 27 }, // Comoros
    -
    4762 { { 'K', 'W' }, {}, 30 }, // Kuwait
    -
    4763 { { 'K', 'Z' }, {}, 20 }, // Kazakhstan
    -
    4764 { { 'L', 'B' }, {}, 28 }, // Lebanon
    -
    4765 { { 'L', 'C' }, {}, 32 }, // Saint Lucia
    -
    4766 { { 'L', 'I' }, {}, 21 }, // Liechtenstein
    -
    4767 { { 'L', 'T' }, {}, 20 }, // Lithuania
    -
    4768 { { 'L', 'U' }, {}, 20 }, // Luxembourg
    -
    4769 { { 'L', 'V' }, {}, 21 }, // Latvia
    -
    4770 { { 'L', 'Y' }, {}, 25 }, // Libya
    -
    4771 { { 'M', 'A' }, {}, 28 }, // Morocco
    -
    4772 { { 'M', 'C' }, {}, 27 }, // Monaco
    -
    4773 { { 'M', 'D' }, {}, 24 }, // Moldova
    -
    4774 { { 'M', 'E' }, { '2', '5' }, 22 }, // Montenegro
    -
    4775 { { 'M', 'G' }, {}, 27 }, // Madagascar
    -
    4776 { { 'M', 'K' }, { '0', '7' }, 19 }, // North Macedonia
    -
    4777 { { 'M', 'L' }, {}, 28 }, // Mali
    -
    4778 { { 'M', 'R' }, { '1', '3' }, 27}, // Mauritania
    -
    4779 { { 'M', 'T' }, {}, 31 }, // Malta
    -
    4780 { { 'M', 'U' }, {}, 30 }, // Mauritius
    -
    4781 { { 'M', 'Z' }, {}, 25 }, // Mozambique
    -
    4782 { { 'N', 'E' }, {}, 28 }, // Niger
    -
    4783 { { 'N', 'I' }, {}, 32 }, // Nicaragua
    -
    4784 { { 'N', 'L' }, {}, 18 }, // Netherlands
    -
    4785 { { 'N', 'O' }, {}, 15 }, // Norway
    -
    4786 { { 'P', 'K' }, {}, 24 }, // Pakistan
    -
    4787 { { 'P', 'L' }, {}, 28 }, // Poland
    -
    4788 { { 'P', 'S' }, {}, 29 }, // Palestinian territories
    -
    4789 { { 'P', 'T' }, { '5', '0' }, 25 }, // Portugal
    -
    4790 { { 'Q', 'A' }, {}, 29 }, // Qatar
    -
    4791 { { 'R', 'O' }, {}, 24 }, // Romania
    -
    4792 { { 'R', 'S' }, { '3', '5' }, 22 }, // Serbia
    -
    4793 { { 'R', 'U' }, {}, 33 }, // Russia
    -
    4794 { { 'S', 'A' }, {}, 24 }, // Saudi Arabia
    -
    4795 { { 'S', 'C' }, {}, 31 }, // Seychelles
    -
    4796 { { 'S', 'D' }, {}, 18 }, // Sudan
    -
    4797 { { 'S', 'E' }, {}, 24 }, // Sweden
    -
    4798 { { 'S', 'I' }, { '5', '6' }, 19 }, // Slovenia
    -
    4799 { { 'S', 'K' }, {}, 24 }, // Slovakia
    -
    4800 { { 'S', 'M' }, {}, 27 }, // San Marino
    -
    4801 { { 'S', 'N' }, {}, 28 }, // Senegal
    -
    4802 { { 'S', 'T' }, {}, 25 }, // São Tomé and Príncipe
    -
    4803 { { 'S', 'V' }, {}, 28 }, // El Salvador
    -
    4804 { { 'T', 'D' }, {}, 27 }, // Chad
    -
    4805 { { 'T', 'G' }, {}, 28 }, // Togo
    -
    4806 { { 'T', 'L' }, { '3', '8' }, 23}, // East Timor
    -
    4807 { { 'T', 'N' }, { '5', '9' }, 24 }, // Tunisia
    -
    4808 { { 'T', 'R' }, {}, 26 }, // Turkey
    -
    4809 { { 'U', 'A' }, {}, 29 }, // Ukraine
    -
    4810 { { 'V', 'A' }, {}, 22 }, // Vatican City
    -
    4811 { { 'V', 'G' }, {}, 24 }, // Virgin Islands, British
    -
    4812 { { 'X', 'K' }, {}, 20 }, // Kosovo
    -
    4813 };
    -
    4814 const country_t* country_desc = nullptr;
    -
    4815 size_t n, available, next, bban_length;
    - -
    4817
    -
    4818 this->interval.end = start;
    -
    4819 for (size_t i = 0; i < 2; ++i, ++this->interval.end) {
    -
    4820 if (this->interval.end >= end || !text[this->interval.end])
    -
    4821 goto error; // incomplete country code
    -
    4822 T chr = case_insensitive ? ctype.toupper(text[this->interval.end]) : text[this->interval.end];
    -
    4823 if (chr < 'A' || 'Z' < chr)
    -
    4824 goto error; // invalid country code
    -
    4825 this->country[i] = chr;
    -
    4826 }
    -
    4827 for (size_t l = 0, r = _countof(s_countries);;) {
    -
    4828 if (l >= r)
    -
    4829 goto error; // unknown country
    -
    4830 size_t m = (l + r) / 2;
    -
    4831 const country_t& c = s_countries[m];
    -
    4832 if (c.country[0] < this->country[0] || (c.country[0] == this->country[0] && c.country[1] < this->country[1]))
    -
    4833 l = m + 1;
    -
    4834 else if (this->country[0] < c.country[0] || (this->country[0] == c.country[0] && this->country[1] < c.country[1]))
    -
    4835 r = m;
    -
    4836 else {
    -
    4837 country_desc = &c;
    -
    4838 break;
    -
    4839 }
    -
    4840 }
    -
    4841 this->country[2] = 0;
    -
    4842
    -
    4843 for (size_t i = 0; i < 2; ++i, ++this->interval.end) {
    -
    4844 if (this->interval.end >= end || text[this->interval.end] < '0' || '9' < text[this->interval.end])
    -
    4845 goto error; // incomplete or invalid check digits
    -
    4846 this->check_digits[i] = text[this->interval.end];
    -
    4847 }
    -
    4848 this->check_digits[2] = 0;
    -
    4849
    -
    4850 if ((country_desc->check_digits[0] && this->check_digits[0] != country_desc->check_digits[0]) ||
    -
    4851 (country_desc->check_digits[1] && this->check_digits[1] != country_desc->check_digits[1]))
    -
    4852 goto error; // unexpected check digits
    -
    4853
    -
    4854 bban_length = country_desc->length - 4;
    -
    4855 for (n = 0; n < bban_length;) {
    -
    4856 if (this->interval.end >= end || !text[this->interval.end])
    -
    4857 goto error; // bban too short
    -
    4858 if (m_space && m_space->match(text, this->interval.end, end, flags)) {
    -
    4859 this->interval.end = m_space->interval.end;
    -
    4860 continue;
    -
    4861 }
    -
    4862 T chr = case_insensitive ? ctype.toupper(text[this->interval.end]) : text[this->interval.end];
    -
    4863 if (('0' <= chr && chr <= '9') || ('A' <= chr && chr <= 'Z')) {
    -
    4864 this->bban[n++] = chr;
    -
    4865 this->interval.end++;
    -
    4866 }
    -
    4867 else
    -
    4868 goto error; // invalid bban
    -
    4869 }
    -
    4870 this->bban[n] = 0;
    -
    4871
    -
    4872 // Normalize IBAN.
    -
    4873 T normalized[69];
    -
    4874 available = 0;
    -
    4875 for (size_t i = 0; ; ++i) {
    -
    4876 if (!this->bban[i]) {
    -
    4877 for (i = 0; i < 2; ++i) {
    -
    4878 if ('A' <= this->country[i] && this->country[i] <= 'J') {
    -
    4879 normalized[available++] = '1';
    -
    4880 normalized[available++] = '0' + this->country[i] - 'A';
    -
    4881 }
    -
    4882 else if ('K' <= this->country[i] && this->country[i] <= 'T') {
    -
    4883 normalized[available++] = '2';
    -
    4884 normalized[available++] = '0' + this->country[i] - 'K';
    -
    4885 }
    -
    4886 else if ('U' <= this->country[i] && this->country[i] <= 'Z') {
    -
    4887 normalized[available++] = '3';
    -
    4888 normalized[available++] = '0' + this->country[i] - 'U';
    -
    4889 }
    -
    4890 }
    -
    4891 normalized[available++] = this->check_digits[0];
    -
    4892 normalized[available++] = this->check_digits[1];
    -
    4893 normalized[available] = 0;
    -
    4894 break;
    -
    4895 }
    -
    4896 if ('0' <= this->bban[i] && this->bban[i] <= '9')
    -
    4897 normalized[available++] = this->bban[i];
    -
    4898 else if ('A' <= this->bban[i] && this->bban[i] <= 'J') {
    -
    4899 normalized[available++] = '1';
    -
    4900 normalized[available++] = '0' + this->bban[i] - 'A';
    -
    4901 }
    -
    4902 else if ('K' <= this->bban[i] && this->bban[i] <= 'T') {
    -
    4903 normalized[available++] = '2';
    -
    4904 normalized[available++] = '0' + this->bban[i] - 'K';
    -
    4905 }
    -
    4906 else if ('U' <= this->bban[i] && this->bban[i] <= 'Z') {
    -
    4907 normalized[available++] = '3';
    -
    4908 normalized[available++] = '0' + this->bban[i] - 'U';
    -
    4909 }
    -
    4910 }
    -
    4911
    -
    4912 // Calculate modulo 97.
    -
    4913 nominator = stdex::strtou32(normalized, 9, &next, 10);
    -
    4914 for (;;) {
    -
    4915 nominator %= 97;
    -
    4916 if (!normalized[next]) {
    -
    4917 this->is_valid = nominator == 1;
    -
    4918 break;
    -
    4919 }
    -
    4920 size_t digit_count = nominator == 0 ? 0 : nominator < 10 ? 1 : 2;
    -
    4921 for (; digit_count < 9 && normalized[next]; ++next, ++digit_count)
    -
    4922 nominator = nominator * 10 + (normalized[next] - '0');
    -
    4923 }
    +
    4658
    + + +
    4661#ifdef _UNICODE
    + +
    4663#else
    + +
    4665#endif
    + +
    4667
    +
    4673 template <class T>
    +
    +
    4674 class basic_iban : public basic_parser<T>
    +
    4675 {
    +
    4676 public:
    +
    4677 basic_iban(
    +
    4678 _In_ const std::shared_ptr<basic_parser<T>>& space,
    +
    4679 _In_ const std::locale& locale = std::locale()) :
    +
    4680 basic_parser<T>(locale),
    +
    4681 m_space(space)
    +
    4682 {
    +
    4683 this->country[0] = 0;
    +
    4684 this->check_digits[0] = 0;
    +
    4685 this->bban[0] = 0;
    +
    4686 this->is_valid = false;
    +
    4687 }
    +
    4688
    +
    4689 virtual bool match(
    +
    4690 _In_reads_or_z_(end) const T* text,
    +
    4691 _In_ size_t start = 0,
    +
    4692 _In_ size_t end = (size_t)-1,
    +
    4693 _In_ int flags = match_default)
    +
    4694 {
    +
    4695 _Assume_(text || start >= end);
    +
    4696 const auto& ctype = std::use_facet<std::ctype<T>>(this->m_locale);
    +
    4697 const bool case_insensitive = flags & match_case_insensitive ? true : false;
    +
    4698 struct country_t {
    +
    4699 T country[2];
    +
    4700 T check_digits[2];
    +
    4701 size_t length;
    +
    4702 };
    +
    4703 static const country_t s_countries[] = {
    +
    4704 { { 'A', 'D' }, {}, 24 }, // Andorra
    +
    4705 { { 'A', 'E' }, {}, 23 }, // United Arab Emirates
    +
    4706 { { 'A', 'L' }, {}, 28 }, // Albania
    +
    4707 { { 'A', 'O' }, {}, 25 }, // Angola
    +
    4708 { { 'A', 'T' }, {}, 20 }, // Austria
    +
    4709 { { 'A', 'Z' }, {}, 28 }, // Azerbaijan
    +
    4710 { { 'B', 'A' }, { '3', '9' }, 20}, // Bosnia and Herzegovina
    +
    4711 { { 'B', 'E' }, {}, 16 }, // Belgium
    +
    4712 { { 'B', 'F' }, {}, 28 }, // Burkina Faso
    +
    4713 { { 'B', 'G' }, {}, 22 }, // Bulgaria
    +
    4714 { { 'B', 'H' }, {}, 22 }, // Bahrain
    +
    4715 { { 'B', 'I' }, {}, 27 }, // Burundi
    +
    4716 { { 'B', 'J' }, {}, 28 }, // Benin
    +
    4717 { { 'B', 'R' }, {}, 29 }, // Brazil
    +
    4718 { { 'B', 'Y' }, {}, 28 }, // Belarus
    +
    4719 { { 'C', 'F' }, {}, 27 }, // Central African Republic
    +
    4720 { { 'C', 'G' }, {}, 27 }, // Congo, Republic of the
    +
    4721 { { 'C', 'H' }, {}, 21 }, // Switzerland
    +
    4722 { { 'C', 'I' }, {}, 28 }, // Côte d'Ivoire
    +
    4723 { { 'C', 'M' }, {}, 27 }, // Cameroon
    +
    4724 { { 'C', 'R' }, {}, 22 }, // Costa Rica
    +
    4725 { { 'C', 'V' }, {}, 25 }, // Cabo Verde
    +
    4726 { { 'C', 'Y' }, {}, 28 }, // Cyprus
    +
    4727 { { 'C', 'Z' }, {}, 24 }, // Czech Republic
    +
    4728 { { 'D', 'E' }, {}, 22 }, // Germany
    +
    4729 { { 'D', 'J' }, {}, 27 }, // Djibouti
    +
    4730 { { 'D', 'K' }, {}, 18 }, // Denmark
    +
    4731 { { 'D', 'O' }, {}, 28 }, // Dominican Republic
    +
    4732 { { 'D', 'Z' }, {}, 26 }, // Algeria
    +
    4733 { { 'E', 'E' }, {}, 20 }, // Estonia
    +
    4734 { { 'E', 'G' }, {}, 29 }, // Egypt
    +
    4735 { { 'E', 'S' }, {}, 24 }, // Spain
    +
    4736 { { 'F', 'I' }, {}, 18 }, // Finland
    +
    4737 { { 'F', 'O' }, {}, 18 }, // Faroe Islands
    +
    4738 { { 'F', 'R' }, {}, 27 }, // France
    +
    4739 { { 'G', 'A' }, {}, 27 }, // Gabon
    +
    4740 { { 'G', 'B' }, {}, 22 }, // United Kingdom
    +
    4741 { { 'G', 'E' }, {}, 22 }, // Georgia
    +
    4742 { { 'G', 'I' }, {}, 23 }, // Gibraltar
    +
    4743 { { 'G', 'L' }, {}, 18 }, // Greenland
    +
    4744 { { 'G', 'Q' }, {}, 27 }, // Equatorial Guinea
    +
    4745 { { 'G', 'R' }, {}, 27 }, // Greece
    +
    4746 { { 'G', 'T' }, {}, 28 }, // Guatemala
    +
    4747 { { 'G', 'W' }, {}, 25 }, // Guinea-Bissau
    +
    4748 { { 'H', 'N' }, {}, 28 }, // Honduras
    +
    4749 { { 'H', 'R' }, {}, 21 }, // Croatia
    +
    4750 { { 'H', 'U' }, {}, 28 }, // Hungary
    +
    4751 { { 'I', 'E' }, {}, 22 }, // Ireland
    +
    4752 { { 'I', 'L' }, {}, 23 }, // Israel
    +
    4753 { { 'I', 'Q' }, {}, 23 }, // Iraq
    +
    4754 { { 'I', 'R' }, {}, 26 }, // Iran
    +
    4755 { { 'I', 'S' }, {}, 26 }, // Iceland
    +
    4756 { { 'I', 'T' }, {}, 27 }, // Italy
    +
    4757 { { 'J', 'O' }, {}, 30 }, // Jordan
    +
    4758 { { 'K', 'M' }, {}, 27 }, // Comoros
    +
    4759 { { 'K', 'W' }, {}, 30 }, // Kuwait
    +
    4760 { { 'K', 'Z' }, {}, 20 }, // Kazakhstan
    +
    4761 { { 'L', 'B' }, {}, 28 }, // Lebanon
    +
    4762 { { 'L', 'C' }, {}, 32 }, // Saint Lucia
    +
    4763 { { 'L', 'I' }, {}, 21 }, // Liechtenstein
    +
    4764 { { 'L', 'T' }, {}, 20 }, // Lithuania
    +
    4765 { { 'L', 'U' }, {}, 20 }, // Luxembourg
    +
    4766 { { 'L', 'V' }, {}, 21 }, // Latvia
    +
    4767 { { 'L', 'Y' }, {}, 25 }, // Libya
    +
    4768 { { 'M', 'A' }, {}, 28 }, // Morocco
    +
    4769 { { 'M', 'C' }, {}, 27 }, // Monaco
    +
    4770 { { 'M', 'D' }, {}, 24 }, // Moldova
    +
    4771 { { 'M', 'E' }, { '2', '5' }, 22 }, // Montenegro
    +
    4772 { { 'M', 'G' }, {}, 27 }, // Madagascar
    +
    4773 { { 'M', 'K' }, { '0', '7' }, 19 }, // North Macedonia
    +
    4774 { { 'M', 'L' }, {}, 28 }, // Mali
    +
    4775 { { 'M', 'R' }, { '1', '3' }, 27}, // Mauritania
    +
    4776 { { 'M', 'T' }, {}, 31 }, // Malta
    +
    4777 { { 'M', 'U' }, {}, 30 }, // Mauritius
    +
    4778 { { 'M', 'Z' }, {}, 25 }, // Mozambique
    +
    4779 { { 'N', 'E' }, {}, 28 }, // Niger
    +
    4780 { { 'N', 'I' }, {}, 32 }, // Nicaragua
    +
    4781 { { 'N', 'L' }, {}, 18 }, // Netherlands
    +
    4782 { { 'N', 'O' }, {}, 15 }, // Norway
    +
    4783 { { 'P', 'K' }, {}, 24 }, // Pakistan
    +
    4784 { { 'P', 'L' }, {}, 28 }, // Poland
    +
    4785 { { 'P', 'S' }, {}, 29 }, // Palestinian territories
    +
    4786 { { 'P', 'T' }, { '5', '0' }, 25 }, // Portugal
    +
    4787 { { 'Q', 'A' }, {}, 29 }, // Qatar
    +
    4788 { { 'R', 'O' }, {}, 24 }, // Romania
    +
    4789 { { 'R', 'S' }, { '3', '5' }, 22 }, // Serbia
    +
    4790 { { 'R', 'U' }, {}, 33 }, // Russia
    +
    4791 { { 'S', 'A' }, {}, 24 }, // Saudi Arabia
    +
    4792 { { 'S', 'C' }, {}, 31 }, // Seychelles
    +
    4793 { { 'S', 'D' }, {}, 18 }, // Sudan
    +
    4794 { { 'S', 'E' }, {}, 24 }, // Sweden
    +
    4795 { { 'S', 'I' }, { '5', '6' }, 19 }, // Slovenia
    +
    4796 { { 'S', 'K' }, {}, 24 }, // Slovakia
    +
    4797 { { 'S', 'M' }, {}, 27 }, // San Marino
    +
    4798 { { 'S', 'N' }, {}, 28 }, // Senegal
    +
    4799 { { 'S', 'T' }, {}, 25 }, // São Tomé and Príncipe
    +
    4800 { { 'S', 'V' }, {}, 28 }, // El Salvador
    +
    4801 { { 'T', 'D' }, {}, 27 }, // Chad
    +
    4802 { { 'T', 'G' }, {}, 28 }, // Togo
    +
    4803 { { 'T', 'L' }, { '3', '8' }, 23}, // East Timor
    +
    4804 { { 'T', 'N' }, { '5', '9' }, 24 }, // Tunisia
    +
    4805 { { 'T', 'R' }, {}, 26 }, // Turkey
    +
    4806 { { 'U', 'A' }, {}, 29 }, // Ukraine
    +
    4807 { { 'V', 'A' }, {}, 22 }, // Vatican City
    +
    4808 { { 'V', 'G' }, {}, 24 }, // Virgin Islands, British
    +
    4809 { { 'X', 'K' }, {}, 20 }, // Kosovo
    +
    4810 };
    +
    4811 const country_t* country_desc = nullptr;
    +
    4812 size_t n, available, next, bban_length;
    + +
    4814
    +
    4815 this->interval.end = start;
    +
    4816 for (size_t i = 0; i < 2; ++i, ++this->interval.end) {
    +
    4817 if (this->interval.end >= end || !text[this->interval.end])
    +
    4818 goto error; // incomplete country code
    +
    4819 T chr = case_insensitive ? ctype.toupper(text[this->interval.end]) : text[this->interval.end];
    +
    4820 if (chr < 'A' || 'Z' < chr)
    +
    4821 goto error; // invalid country code
    +
    4822 this->country[i] = chr;
    +
    4823 }
    +
    4824 for (size_t l = 0, r = _countof(s_countries);;) {
    +
    4825 if (l >= r)
    +
    4826 goto error; // unknown country
    +
    4827 size_t m = (l + r) / 2;
    +
    4828 const country_t& c = s_countries[m];
    +
    4829 if (c.country[0] < this->country[0] || (c.country[0] == this->country[0] && c.country[1] < this->country[1]))
    +
    4830 l = m + 1;
    +
    4831 else if (this->country[0] < c.country[0] || (this->country[0] == c.country[0] && this->country[1] < c.country[1]))
    +
    4832 r = m;
    +
    4833 else {
    +
    4834 country_desc = &c;
    +
    4835 break;
    +
    4836 }
    +
    4837 }
    +
    4838 this->country[2] = 0;
    +
    4839
    +
    4840 for (size_t i = 0; i < 2; ++i, ++this->interval.end) {
    +
    4841 if (this->interval.end >= end || text[this->interval.end] < '0' || '9' < text[this->interval.end])
    +
    4842 goto error; // incomplete or invalid check digits
    +
    4843 this->check_digits[i] = text[this->interval.end];
    +
    4844 }
    +
    4845 this->check_digits[2] = 0;
    +
    4846
    +
    4847 if ((country_desc->check_digits[0] && this->check_digits[0] != country_desc->check_digits[0]) ||
    +
    4848 (country_desc->check_digits[1] && this->check_digits[1] != country_desc->check_digits[1]))
    +
    4849 goto error; // unexpected check digits
    +
    4850
    +
    4851 bban_length = country_desc->length - 4;
    +
    4852 for (n = 0; n < bban_length;) {
    +
    4853 if (this->interval.end >= end || !text[this->interval.end])
    +
    4854 goto error; // bban too short
    +
    4855 if (m_space && m_space->match(text, this->interval.end, end, flags)) {
    +
    4856 this->interval.end = m_space->interval.end;
    +
    4857 continue;
    +
    4858 }
    +
    4859 T chr = case_insensitive ? ctype.toupper(text[this->interval.end]) : text[this->interval.end];
    +
    4860 if (('0' <= chr && chr <= '9') || ('A' <= chr && chr <= 'Z')) {
    +
    4861 this->bban[n++] = chr;
    +
    4862 this->interval.end++;
    +
    4863 }
    +
    4864 else
    +
    4865 goto error; // invalid bban
    +
    4866 }
    +
    4867 this->bban[n] = 0;
    +
    4868
    +
    4869 // Normalize IBAN.
    +
    4870 T normalized[69];
    +
    4871 available = 0;
    +
    4872 for (size_t i = 0; ; ++i) {
    +
    4873 if (!this->bban[i]) {
    +
    4874 for (i = 0; i < 2; ++i) {
    +
    4875 if ('A' <= this->country[i] && this->country[i] <= 'J') {
    +
    4876 normalized[available++] = '1';
    +
    4877 normalized[available++] = '0' + this->country[i] - 'A';
    +
    4878 }
    +
    4879 else if ('K' <= this->country[i] && this->country[i] <= 'T') {
    +
    4880 normalized[available++] = '2';
    +
    4881 normalized[available++] = '0' + this->country[i] - 'K';
    +
    4882 }
    +
    4883 else if ('U' <= this->country[i] && this->country[i] <= 'Z') {
    +
    4884 normalized[available++] = '3';
    +
    4885 normalized[available++] = '0' + this->country[i] - 'U';
    +
    4886 }
    +
    4887 }
    +
    4888 normalized[available++] = this->check_digits[0];
    +
    4889 normalized[available++] = this->check_digits[1];
    +
    4890 normalized[available] = 0;
    +
    4891 break;
    +
    4892 }
    +
    4893 if ('0' <= this->bban[i] && this->bban[i] <= '9')
    +
    4894 normalized[available++] = this->bban[i];
    +
    4895 else if ('A' <= this->bban[i] && this->bban[i] <= 'J') {
    +
    4896 normalized[available++] = '1';
    +
    4897 normalized[available++] = '0' + this->bban[i] - 'A';
    +
    4898 }
    +
    4899 else if ('K' <= this->bban[i] && this->bban[i] <= 'T') {
    +
    4900 normalized[available++] = '2';
    +
    4901 normalized[available++] = '0' + this->bban[i] - 'K';
    +
    4902 }
    +
    4903 else if ('U' <= this->bban[i] && this->bban[i] <= 'Z') {
    +
    4904 normalized[available++] = '3';
    +
    4905 normalized[available++] = '0' + this->bban[i] - 'U';
    +
    4906 }
    +
    4907 }
    +
    4908
    +
    4909 // Calculate modulo 97.
    +
    4910 nominator = stdex::strtou32(normalized, 9, &next, 10);
    +
    4911 for (;;) {
    +
    4912 nominator %= 97;
    +
    4913 if (!normalized[next]) {
    +
    4914 this->is_valid = nominator == 1;
    +
    4915 break;
    +
    4916 }
    +
    4917 size_t digit_count = nominator == 0 ? 0 : nominator < 10 ? 1 : 2;
    +
    4918 for (; digit_count < 9 && normalized[next]; ++next, ++digit_count)
    +
    4919 nominator = nominator * 10 + (normalized[next] - '0');
    +
    4920 }
    +
    4921
    +
    4922 this->interval.start = start;
    +
    4923 return true;
    4924
    -
    4925 this->interval.start = start;
    -
    4926 return true;
    -
    4927
    -
    4928 error:
    -
    4929 this->country[0] = 0;
    -
    4930 this->check_digits[0] = 0;
    -
    4931 this->bban[0] = 0;
    -
    4932 this->is_valid = false;
    -
    4933 this->interval.start = (this->interval.end = start) + 1;
    -
    4934 return false;
    -
    4935 }
    -
    4936
    -
    4937 virtual void invalidate()
    -
    4938 {
    -
    4939 this->country[0] = 0;
    -
    4940 this->check_digits[0] = 0;
    -
    4941 this->bban[0] = 0;
    -
    4942 this->is_valid = false;
    - -
    4944 }
    -
    4945
    -
    4946 public:
    -
    4947 T country[3];
    - -
    4949 T bban[31];
    - -
    4951
    -
    4952 protected:
    -
    4953 std::shared_ptr<basic_parser<T>> m_space;
    -
    4954 };
    +
    4925 error:
    +
    4926 this->country[0] = 0;
    +
    4927 this->check_digits[0] = 0;
    +
    4928 this->bban[0] = 0;
    +
    4929 this->is_valid = false;
    +
    4930 this->interval.start = (this->interval.end = start) + 1;
    +
    4931 return false;
    +
    4932 }
    +
    4933
    +
    4934 virtual void invalidate()
    +
    4935 {
    +
    4936 this->country[0] = 0;
    +
    4937 this->check_digits[0] = 0;
    +
    4938 this->bban[0] = 0;
    +
    4939 this->is_valid = false;
    + +
    4941 }
    +
    4942
    +
    4943 public:
    +
    4944 T country[3];
    + +
    4946 T bban[31];
    + +
    4948
    +
    4949 protected:
    +
    4950 std::shared_ptr<basic_parser<T>> m_space;
    +
    4951 };
    -
    4955
    -
    4956 using iban = basic_iban<char>;
    -
    4957 using wiban = basic_iban<wchar_t>;
    -
    4958#ifdef _UNICODE
    -
    4959 using tiban = wiban;
    -
    4960#else
    -
    4961 using tiban = iban;
    -
    4962#endif
    - -
    4964
    -
    4970 template <class T>
    -
    - -
    4972 {
    -
    4973 public:
    - -
    4975 _In_ const std::shared_ptr<basic_parser<T>>& space,
    -
    4976 _In_ const std::locale& locale = std::locale()) :
    -
    4977 basic_parser<T>(locale),
    -
    4978 m_space(space)
    -
    4979 {
    -
    4980 this->check_digits[0] = 0;
    -
    4981 this->reference[0] = 0;
    -
    4982 this->is_valid = false;
    -
    4983 }
    -
    4984
    -
    4985 virtual bool match(
    -
    4986 _In_reads_or_z_(end) const T* text,
    -
    4987 _In_ size_t start = 0,
    -
    4988 _In_ size_t end = (size_t)-1,
    -
    4989 _In_ int flags = match_default)
    -
    4990 {
    -
    4991 _Assume_(text || start >= end);
    -
    4992 const auto& ctype = std::use_facet<std::ctype<T>>(this->m_locale);
    -
    4993 const bool case_insensitive = flags & match_case_insensitive ? true : false;
    -
    4994 size_t n, available, next;
    - -
    4996
    -
    4997 this->interval.end = start;
    -
    4998 if (this->interval.end + 1 >= end ||
    -
    4999 (case_insensitive ? ctype.toupper(text[this->interval.end]) : text[this->interval.end]) != 'R' ||
    -
    5000 (case_insensitive ? ctype.toupper(text[this->interval.end + 1]) : text[this->interval.end + 1]) != 'F')
    -
    5001 goto error; // incomplete or wrong reference ID
    -
    5002 this->interval.end += 2;
    -
    5003
    -
    5004 for (size_t i = 0; i < 2; ++i, ++this->interval.end) {
    -
    5005 if (this->interval.end >= end || text[this->interval.end] < '0' || '9' < text[this->interval.end])
    -
    5006 goto error; // incomplete or invalid check digits
    -
    5007 this->check_digits[i] = text[this->interval.end];
    -
    5008 }
    -
    5009 this->check_digits[2] = 0;
    -
    5010
    -
    5011 for (n = 0;;) {
    -
    5012 if (m_space && m_space->match(text, this->interval.end, end, flags))
    -
    5013 this->interval.end = m_space->interval.end;
    -
    5014 for (size_t j = 0; j < 4; ++j) {
    -
    5015 if (this->interval.end >= end || !text[this->interval.end])
    -
    5016 goto out;
    -
    5017 T chr = case_insensitive ? ctype.toupper(text[this->interval.end]) : text[this->interval.end];
    -
    5018 if (('0' <= chr && chr <= '9') || ('A' <= chr && chr <= 'Z')) {
    -
    5019 if (n >= _countof(reference) - 1)
    -
    5020 goto error; // reference overflow
    -
    5021 this->reference[n++] = chr;
    -
    5022 this->interval.end++;
    -
    5023 }
    -
    5024 else
    -
    5025 goto out;
    -
    5026 }
    -
    5027 }
    -
    5028 out:
    -
    5029 if (!n)
    -
    5030 goto error; // reference too short
    -
    5031 this->reference[_countof(this->reference) - 1] = 0;
    -
    5032 for (size_t i = n, j = _countof(this->reference) - 1; i;)
    -
    5033 this->reference[--j] = this->reference[--i];
    -
    5034 for (size_t j = _countof(this->reference) - 1 - n; j;)
    -
    5035 this->reference[--j] = '0';
    -
    5036
    -
    5037 // Normalize creditor reference.
    -
    5038 T normalized[47];
    -
    5039 available = 0;
    -
    5040 for (size_t i = 0; ; ++i) {
    -
    5041 if (!this->reference[i]) {
    -
    5042 normalized[available++] = '2'; // R
    -
    5043 normalized[available++] = '7';
    -
    5044 normalized[available++] = '1'; // F
    -
    5045 normalized[available++] = '5';
    -
    5046 normalized[available++] = this->check_digits[0];
    -
    5047 normalized[available++] = this->check_digits[1];
    -
    5048 normalized[available] = 0;
    -
    5049 break;
    -
    5050 }
    -
    5051 if ('0' <= this->reference[i] && this->reference[i] <= '9')
    -
    5052 normalized[available++] = this->reference[i];
    -
    5053 else if ('A' <= this->reference[i] && this->reference[i] <= 'J') {
    -
    5054 normalized[available++] = '1';
    -
    5055 normalized[available++] = '0' + this->reference[i] - 'A';
    -
    5056 }
    -
    5057 else if ('K' <= this->reference[i] && this->reference[i] <= 'T') {
    -
    5058 normalized[available++] = '2';
    -
    5059 normalized[available++] = '0' + this->reference[i] - 'K';
    -
    5060 }
    -
    5061 else if ('U' <= this->reference[i] && this->reference[i] <= 'Z') {
    -
    5062 normalized[available++] = '3';
    -
    5063 normalized[available++] = '0' + this->reference[i] - 'U';
    -
    5064 }
    -
    5065 }
    -
    5066
    -
    5067 // Calculate modulo 97.
    -
    5068 nominator = stdex::strtou32(normalized, 9, &next, 10);
    -
    5069 for (;;) {
    -
    5070 nominator %= 97;
    -
    5071 if (!normalized[next]) {
    -
    5072 this->is_valid = nominator == 1;
    -
    5073 break;
    -
    5074 }
    -
    5075 size_t digit_count = nominator == 0 ? 0 : nominator < 10 ? 1 : 2;
    -
    5076 for (; digit_count < 9 && normalized[next]; ++next, ++digit_count)
    -
    5077 nominator = nominator * 10 + (normalized[next] - '0');
    -
    5078 }
    +
    4952
    +
    4953 using iban = basic_iban<char>;
    +
    4954 using wiban = basic_iban<wchar_t>;
    +
    4955#ifdef _UNICODE
    +
    4956 using tiban = wiban;
    +
    4957#else
    +
    4958 using tiban = iban;
    +
    4959#endif
    + +
    4961
    +
    4967 template <class T>
    +
    + +
    4969 {
    +
    4970 public:
    + +
    4972 _In_ const std::shared_ptr<basic_parser<T>>& space,
    +
    4973 _In_ const std::locale& locale = std::locale()) :
    +
    4974 basic_parser<T>(locale),
    +
    4975 m_space(space)
    +
    4976 {
    +
    4977 this->check_digits[0] = 0;
    +
    4978 this->reference[0] = 0;
    +
    4979 this->is_valid = false;
    +
    4980 }
    +
    4981
    +
    4982 virtual bool match(
    +
    4983 _In_reads_or_z_(end) const T* text,
    +
    4984 _In_ size_t start = 0,
    +
    4985 _In_ size_t end = (size_t)-1,
    +
    4986 _In_ int flags = match_default)
    +
    4987 {
    +
    4988 _Assume_(text || start >= end);
    +
    4989 const auto& ctype = std::use_facet<std::ctype<T>>(this->m_locale);
    +
    4990 const bool case_insensitive = flags & match_case_insensitive ? true : false;
    +
    4991 size_t n, available, next;
    + +
    4993
    +
    4994 this->interval.end = start;
    +
    4995 if (this->interval.end + 1 >= end ||
    +
    4996 (case_insensitive ? ctype.toupper(text[this->interval.end]) : text[this->interval.end]) != 'R' ||
    +
    4997 (case_insensitive ? ctype.toupper(text[this->interval.end + 1]) : text[this->interval.end + 1]) != 'F')
    +
    4998 goto error; // incomplete or wrong reference ID
    +
    4999 this->interval.end += 2;
    +
    5000
    +
    5001 for (size_t i = 0; i < 2; ++i, ++this->interval.end) {
    +
    5002 if (this->interval.end >= end || text[this->interval.end] < '0' || '9' < text[this->interval.end])
    +
    5003 goto error; // incomplete or invalid check digits
    +
    5004 this->check_digits[i] = text[this->interval.end];
    +
    5005 }
    +
    5006 this->check_digits[2] = 0;
    +
    5007
    +
    5008 for (n = 0;;) {
    +
    5009 if (m_space && m_space->match(text, this->interval.end, end, flags))
    +
    5010 this->interval.end = m_space->interval.end;
    +
    5011 for (size_t j = 0; j < 4; ++j) {
    +
    5012 if (this->interval.end >= end || !text[this->interval.end])
    +
    5013 goto out;
    +
    5014 T chr = case_insensitive ? ctype.toupper(text[this->interval.end]) : text[this->interval.end];
    +
    5015 if (('0' <= chr && chr <= '9') || ('A' <= chr && chr <= 'Z')) {
    +
    5016 if (n >= _countof(reference) - 1)
    +
    5017 goto error; // reference overflow
    +
    5018 this->reference[n++] = chr;
    +
    5019 this->interval.end++;
    +
    5020 }
    +
    5021 else
    +
    5022 goto out;
    +
    5023 }
    +
    5024 }
    +
    5025 out:
    +
    5026 if (!n)
    +
    5027 goto error; // reference too short
    +
    5028 this->reference[_countof(this->reference) - 1] = 0;
    +
    5029 for (size_t i = n, j = _countof(this->reference) - 1; i;)
    +
    5030 this->reference[--j] = this->reference[--i];
    +
    5031 for (size_t j = _countof(this->reference) - 1 - n; j;)
    +
    5032 this->reference[--j] = '0';
    +
    5033
    +
    5034 // Normalize creditor reference.
    +
    5035 T normalized[47];
    +
    5036 available = 0;
    +
    5037 for (size_t i = 0; ; ++i) {
    +
    5038 if (!this->reference[i]) {
    +
    5039 normalized[available++] = '2'; // R
    +
    5040 normalized[available++] = '7';
    +
    5041 normalized[available++] = '1'; // F
    +
    5042 normalized[available++] = '5';
    +
    5043 normalized[available++] = this->check_digits[0];
    +
    5044 normalized[available++] = this->check_digits[1];
    +
    5045 normalized[available] = 0;
    +
    5046 break;
    +
    5047 }
    +
    5048 if ('0' <= this->reference[i] && this->reference[i] <= '9')
    +
    5049 normalized[available++] = this->reference[i];
    +
    5050 else if ('A' <= this->reference[i] && this->reference[i] <= 'J') {
    +
    5051 normalized[available++] = '1';
    +
    5052 normalized[available++] = '0' + this->reference[i] - 'A';
    +
    5053 }
    +
    5054 else if ('K' <= this->reference[i] && this->reference[i] <= 'T') {
    +
    5055 normalized[available++] = '2';
    +
    5056 normalized[available++] = '0' + this->reference[i] - 'K';
    +
    5057 }
    +
    5058 else if ('U' <= this->reference[i] && this->reference[i] <= 'Z') {
    +
    5059 normalized[available++] = '3';
    +
    5060 normalized[available++] = '0' + this->reference[i] - 'U';
    +
    5061 }
    +
    5062 }
    +
    5063
    +
    5064 // Calculate modulo 97.
    +
    5065 nominator = stdex::strtou32(normalized, 9, &next, 10);
    +
    5066 for (;;) {
    +
    5067 nominator %= 97;
    +
    5068 if (!normalized[next]) {
    +
    5069 this->is_valid = nominator == 1;
    +
    5070 break;
    +
    5071 }
    +
    5072 size_t digit_count = nominator == 0 ? 0 : nominator < 10 ? 1 : 2;
    +
    5073 for (; digit_count < 9 && normalized[next]; ++next, ++digit_count)
    +
    5074 nominator = nominator * 10 + (normalized[next] - '0');
    +
    5075 }
    +
    5076
    +
    5077 this->interval.start = start;
    +
    5078 return true;
    5079
    -
    5080 this->interval.start = start;
    -
    5081 return true;
    -
    5082
    -
    5083 error:
    -
    5084 this->check_digits[0] = 0;
    -
    5085 this->reference[0] = 0;
    -
    5086 this->is_valid = false;
    -
    5087 this->interval.start = (this->interval.end = start) + 1;
    -
    5088 return false;
    -
    5089 }
    -
    5090
    -
    5091 virtual void invalidate()
    -
    5092 {
    -
    5093 this->check_digits[0] = 0;
    -
    5094 this->reference[0] = 0;
    -
    5095 this->is_valid = false;
    - -
    5097 }
    -
    5098
    -
    5099 public:
    - - - -
    5103
    -
    5104 protected:
    -
    5105 std::shared_ptr<basic_parser<T>> m_space;
    -
    5106 };
    +
    5080 error:
    +
    5081 this->check_digits[0] = 0;
    +
    5082 this->reference[0] = 0;
    +
    5083 this->is_valid = false;
    +
    5084 this->interval.start = (this->interval.end = start) + 1;
    +
    5085 return false;
    +
    5086 }
    +
    5087
    +
    5088 virtual void invalidate()
    +
    5089 {
    +
    5090 this->check_digits[0] = 0;
    +
    5091 this->reference[0] = 0;
    +
    5092 this->is_valid = false;
    + +
    5094 }
    +
    5095
    +
    5096 public:
    + + + +
    5100
    +
    5101 protected:
    +
    5102 std::shared_ptr<basic_parser<T>> m_space;
    +
    5103 };
    -
    5107
    - - -
    5110#ifdef _UNICODE
    - -
    5112#else
    - -
    5114#endif
    - -
    5116
    -
    5122 template <class T>
    -
    - -
    5124 {
    -
    5125 public:
    -
    5126 basic_si_reference_part(_In_ const std::locale& locale = std::locale()) : basic_parser<T>(locale) {}
    -
    5127
    -
    5128 virtual bool match(
    -
    5129 _In_reads_or_z_(end) const T* text,
    -
    5130 _In_ size_t start = 0,
    -
    5131 _In_ size_t end = (size_t)-1,
    -
    5132 _In_ int flags = match_default)
    -
    5133 {
    -
    5134 _Assume_(text || start >= end);
    -
    5135 this->interval.end = start;
    -
    5136 for (;;) {
    -
    5137 if (this->interval.end >= end || !text[this->interval.end])
    -
    5138 break;
    -
    5139 if ('0' <= text[this->interval.end] && text[this->interval.end] <= '9')
    -
    5140 this->interval.end++;
    -
    5141 else
    -
    5142 break;
    -
    5143 }
    - -
    5145 this->interval.start = start;
    -
    5146 return true;
    -
    5147 }
    -
    5148 this->interval.start = (this->interval.end = start) + 1;
    -
    5149 return false;
    -
    5150 }
    -
    5151 };
    +
    5104
    + + +
    5107#ifdef _UNICODE
    + +
    5109#else
    + +
    5111#endif
    + +
    5113
    +
    5119 template <class T>
    +
    + +
    5121 {
    +
    5122 public:
    +
    5123 basic_si_reference_part(_In_ const std::locale& locale = std::locale()) : basic_parser<T>(locale) {}
    +
    5124
    +
    5125 virtual bool match(
    +
    5126 _In_reads_or_z_(end) const T* text,
    +
    5127 _In_ size_t start = 0,
    +
    5128 _In_ size_t end = (size_t)-1,
    +
    5129 _In_ int flags = match_default)
    +
    5130 {
    +
    5131 _Assume_(text || start >= end);
    +
    5132 this->interval.end = start;
    +
    5133 for (;;) {
    +
    5134 if (this->interval.end >= end || !text[this->interval.end])
    +
    5135 break;
    +
    5136 if ('0' <= text[this->interval.end] && text[this->interval.end] <= '9')
    +
    5137 this->interval.end++;
    +
    5138 else
    +
    5139 break;
    +
    5140 }
    + +
    5142 this->interval.start = start;
    +
    5143 return true;
    +
    5144 }
    +
    5145 this->interval.start = (this->interval.end = start) + 1;
    +
    5146 return false;
    +
    5147 }
    +
    5148 };
    -
    5152
    - - -
    5155#ifdef _UNICODE
    - -
    5157#else
    - -
    5159#endif
    - -
    5161
    -
    5167 template <class T>
    -
    - -
    5169 {
    -
    5170 public:
    -
    5171 basic_si_reference_delimiter(_In_ const std::locale& locale = std::locale()) : basic_parser<T>(locale) {}
    -
    5172
    -
    5173 virtual bool match(
    -
    5174 _In_reads_or_z_(end) const T* text,
    -
    5175 _In_ size_t start = 0,
    -
    5176 _In_ size_t end = (size_t)-1,
    -
    5177 _In_ int flags = match_default)
    -
    5178 {
    -
    5179 _Assume_(text || start >= end);
    -
    5180 if (start < end && text[start] == '-') {
    -
    5181 this->interval.end = (this->interval.start = start) + 1;
    -
    5182 return true;
    -
    5183 }
    -
    5184 this->interval.start = (this->interval.end = start) + 1;
    -
    5185 return false;
    -
    5186 }
    -
    5187 };
    +
    5149
    + + +
    5152#ifdef _UNICODE
    + +
    5154#else
    + +
    5156#endif
    + +
    5158
    +
    5164 template <class T>
    +
    + +
    5166 {
    +
    5167 public:
    +
    5168 basic_si_reference_delimiter(_In_ const std::locale& locale = std::locale()) : basic_parser<T>(locale) {}
    +
    5169
    +
    5170 virtual bool match(
    +
    5171 _In_reads_or_z_(end) const T* text,
    +
    5172 _In_ size_t start = 0,
    +
    5173 _In_ size_t end = (size_t)-1,
    +
    5174 _In_ int flags = match_default)
    +
    5175 {
    +
    5176 _Assume_(text || start >= end);
    +
    5177 if (start < end && text[start] == '-') {
    +
    5178 this->interval.end = (this->interval.start = start) + 1;
    +
    5179 return true;
    +
    5180 }
    +
    5181 this->interval.start = (this->interval.end = start) + 1;
    +
    5182 return false;
    +
    5183 }
    +
    5184 };
    -
    5188
    - - -
    5191#ifdef _UNICODE
    - -
    5193#else
    - -
    5195#endif
    - -
    5197
    -
    5205 template <class T>
    -
    - -
    5207 {
    -
    5208 public:
    - -
    5210 _In_ const std::shared_ptr<basic_parser<T>>& space,
    -
    5211 _In_ const std::locale& locale = std::locale()) :
    -
    5212 basic_parser<T>(locale),
    -
    5213 part1(locale),
    -
    5214 part2(locale),
    -
    5215 part3(locale),
    -
    5216 is_valid(false),
    -
    5217 m_space(space),
    -
    5218 m_delimiter(locale)
    -
    5219 {
    -
    5220 this->model[0] = 0;
    -
    5221 }
    -
    5222
    -
    5223 virtual bool match(
    -
    5224 _In_reads_or_z_(end) const T* text,
    -
    5225 _In_ size_t start = 0,
    -
    5226 _In_ size_t end = (size_t)-1,
    -
    5227 _In_ int flags = match_default)
    -
    5228 {
    -
    5229 _Assume_(text || start >= end);
    -
    5230 const auto& ctype = std::use_facet<std::ctype<T>>(this->m_locale);
    -
    5231 const bool case_insensitive = flags & match_case_insensitive ? true : false;
    -
    5232
    -
    5233 this->interval.end = start;
    -
    5234 if (this->interval.end + 1 >= end ||
    -
    5235 (case_insensitive ? ctype.toupper(text[this->interval.end]) : text[this->interval.end]) != 'S' ||
    -
    5236 (case_insensitive ? ctype.toupper(text[this->interval.end + 1]) : text[this->interval.end + 1]) != 'I')
    -
    5237 goto error; // incomplete or wrong reference ID
    -
    5238 this->interval.end += 2;
    -
    5239
    -
    5240 for (size_t i = 0; i < 2; ++i, ++this->interval.end) {
    -
    5241 if (this->interval.end >= end || text[this->interval.end] < '0' || '9' < text[this->interval.end])
    -
    5242 goto error; // incomplete or invalid model
    -
    5243 this->model[i] = text[this->interval.end];
    -
    5244 }
    -
    5245 this->model[2] = 0;
    -
    5246
    -
    5247 this->part1.invalidate();
    -
    5248 this->part2.invalidate();
    -
    5249 this->part3.invalidate();
    -
    5250 if (this->model[0] == '9' && this->model[1] == '9') {
    -
    5251 is_valid = true;
    -
    5252 this->interval.start = start;
    -
    5253 return true;
    -
    5254 }
    +
    5185
    + + +
    5188#ifdef _UNICODE
    + +
    5190#else
    + +
    5192#endif
    + +
    5194
    +
    5202 template <class T>
    +
    + +
    5204 {
    +
    5205 public:
    + +
    5207 _In_ const std::shared_ptr<basic_parser<T>>& space,
    +
    5208 _In_ const std::locale& locale = std::locale()) :
    +
    5209 basic_parser<T>(locale),
    +
    5210 part1(locale),
    +
    5211 part2(locale),
    +
    5212 part3(locale),
    +
    5213 is_valid(false),
    +
    5214 m_space(space),
    +
    5215 m_delimiter(locale)
    +
    5216 {
    +
    5217 this->model[0] = 0;
    +
    5218 }
    +
    5219
    +
    5220 virtual bool match(
    +
    5221 _In_reads_or_z_(end) const T* text,
    +
    5222 _In_ size_t start = 0,
    +
    5223 _In_ size_t end = (size_t)-1,
    +
    5224 _In_ int flags = match_default)
    +
    5225 {
    +
    5226 _Assume_(text || start >= end);
    +
    5227 const auto& ctype = std::use_facet<std::ctype<T>>(this->m_locale);
    +
    5228 const bool case_insensitive = flags & match_case_insensitive ? true : false;
    +
    5229
    +
    5230 this->interval.end = start;
    +
    5231 if (this->interval.end + 1 >= end ||
    +
    5232 (case_insensitive ? ctype.toupper(text[this->interval.end]) : text[this->interval.end]) != 'S' ||
    +
    5233 (case_insensitive ? ctype.toupper(text[this->interval.end + 1]) : text[this->interval.end + 1]) != 'I')
    +
    5234 goto error; // incomplete or wrong reference ID
    +
    5235 this->interval.end += 2;
    +
    5236
    +
    5237 for (size_t i = 0; i < 2; ++i, ++this->interval.end) {
    +
    5238 if (this->interval.end >= end || text[this->interval.end] < '0' || '9' < text[this->interval.end])
    +
    5239 goto error; // incomplete or invalid model
    +
    5240 this->model[i] = text[this->interval.end];
    +
    5241 }
    +
    5242 this->model[2] = 0;
    +
    5243
    +
    5244 this->part1.invalidate();
    +
    5245 this->part2.invalidate();
    +
    5246 this->part3.invalidate();
    +
    5247 if (this->model[0] == '9' && this->model[1] == '9') {
    +
    5248 is_valid = true;
    +
    5249 this->interval.start = start;
    +
    5250 return true;
    +
    5251 }
    +
    5252
    +
    5253 if (m_space && m_space->match(text, this->interval.end, end, flags))
    +
    5254 this->interval.end = m_space->interval.end;
    5255
    -
    5256 if (m_space && m_space->match(text, this->interval.end, end, flags))
    -
    5257 this->interval.end = m_space->interval.end;
    -
    5258
    -
    5259 this->part1.match(text, this->interval.end, end, flags) &&
    -
    5260 this->m_delimiter.match(text, this->part1.interval.end, end, flags) &&
    -
    5261 this->part2.match(text, this->m_delimiter.interval.end, end, flags) &&
    -
    5262 this->m_delimiter.match(text, this->part2.interval.end, end, flags) &&
    -
    5263 this->part3.match(text, this->m_delimiter.interval.end, end, flags);
    -
    5264
    -
    5265 this->interval.start = start;
    -
    5266 if (this->part3.interval)
    -
    5267 this->interval.end = this->part3.interval.end;
    -
    5268 else if (this->part2.interval)
    -
    5269 this->interval.end = this->part2.interval.end;
    -
    5270 else if (this->part1.interval)
    -
    5271 this->interval.end = this->part1.interval.end;
    -
    5272 else
    -
    5273 this->interval.end = start + 4;
    -
    5274
    -
    5275 if (this->model[0] == '0' && this->model[1] == '0')
    -
    5276 is_valid =
    -
    5277 this->part3.interval ?
    -
    5278 this->part1.interval.size() <= 12 && this->part2.interval.size() <= 12 && this->part3.interval.size() <= 12 &&
    -
    5279 this->part1.interval.size() + this->part2.interval.size() + this->part3.interval.size() <= 20 :
    -
    5280 this->part2.interval ?
    -
    5281 this->part1.interval.size() <= 12 && this->part2.interval.size() <= 12 &&
    -
    5282 this->part1.interval.size() + this->part2.interval.size() <= 20 :
    -
    5283 this->part1.interval ?
    -
    5284 this->part1.interval.size() <= 12 :
    -
    5285 false;
    -
    5286 else if (this->model[0] == '0' && this->model[1] == '1')
    -
    5287 is_valid =
    -
    5288 this->part3.interval ?
    -
    5289 this->part1.interval.size() <= 12 && this->part2.interval.size() <= 12 && this->part3.interval.size() <= 12 &&
    -
    5290 this->part1.interval.size() + this->part2.interval.size() + this->part3.interval.size() <= 20 &&
    -
    5291 check11(
    -
    5292 text + this->part1.interval.start, this->part1.interval.size(),
    -
    5293 text + this->part2.interval.start, this->part2.interval.size(),
    -
    5294 text + this->part3.interval.start, this->part3.interval.size()) :
    -
    5295 this->part2.interval ?
    -
    5296 this->part1.interval.size() <= 12 && this->part2.interval.size() <= 12 &&
    -
    5297 this->part1.interval.size() + this->part2.interval.size() <= 20 &&
    -
    5298 check11(
    -
    5299 text + this->part1.interval.start, this->part1.interval.size(),
    -
    5300 text + this->part2.interval.start, this->part2.interval.size()) :
    -
    5301 this->part1.interval ?
    -
    5302 this->part1.interval.size() <= 12 &&
    -
    5303 check11(text + this->part1.interval.start, this->part1.interval.size()) :
    -
    5304 false;
    -
    5305 else if (this->model[0] == '0' && this->model[1] == '2')
    -
    5306 is_valid =
    -
    5307 this->part3.interval ?
    -
    5308 this->part1.interval.size() <= 12 && this->part2.interval.size() <= 12 && this->part3.interval.size() <= 12 &&
    -
    5309 this->part1.interval.size() + this->part2.interval.size() + this->part3.interval.size() <= 20 &&
    -
    5310 check11(text + this->part2.interval.start, this->part2.interval.size()) &&
    -
    5311 check11(text + this->part3.interval.start, this->part3.interval.size()) :
    -
    5312 false;
    -
    5313 else if (this->model[0] == '0' && this->model[1] == '3')
    -
    5314 is_valid =
    -
    5315 this->part3.interval ?
    -
    5316 this->part1.interval.size() <= 12 && this->part2.interval.size() <= 12 && this->part3.interval.size() <= 12 &&
    -
    5317 this->part1.interval.size() + this->part2.interval.size() + this->part3.interval.size() <= 20 &&
    -
    5318 check11(text + this->part1.interval.start, this->part1.interval.size()) &&
    -
    5319 check11(text + this->part2.interval.start, this->part2.interval.size()) &&
    -
    5320 check11(text + this->part3.interval.start, this->part3.interval.size()) :
    -
    5321 false;
    -
    5322 else if (this->model[0] == '0' && this->model[1] == '4')
    -
    5323 is_valid =
    -
    5324 this->part3.interval ?
    -
    5325 this->part1.interval.size() <= 12 && this->part2.interval.size() <= 12 && this->part3.interval.size() <= 12 &&
    -
    5326 this->part1.interval.size() + this->part2.interval.size() + this->part3.interval.size() <= 20 &&
    -
    5327 check11(text + this->part1.interval.start, this->part1.interval.size()) &&
    -
    5328 check11(text + this->part3.interval.start, this->part3.interval.size()) :
    -
    5329 false;
    -
    5330 else if ((this->model[0] == '0' || this->model[0] == '5') && this->model[1] == '5')
    -
    5331 is_valid =
    -
    5332 this->part3.interval ?
    -
    5333 this->part1.interval.size() <= 12 && this->part2.interval.size() <= 12 && this->part3.interval.size() <= 12 &&
    -
    5334 this->part1.interval.size() + this->part2.interval.size() + this->part3.interval.size() <= 20 &&
    -
    5335 check11(text + this->part1.interval.start, this->part1.interval.size()) :
    -
    5336 this->part2.interval ?
    -
    5337 this->part1.interval.size() <= 12 && this->part2.interval.size() <= 12 &&
    -
    5338 this->part1.interval.size() + this->part2.interval.size() <= 20 &&
    -
    5339 check11(text + this->part1.interval.start, this->part1.interval.size()) :
    -
    5340 this->part1.interval ?
    -
    5341 this->part1.interval.size() <= 12 &&
    -
    5342 check11(text + this->part1.interval.start, this->part1.interval.size()) :
    -
    5343 false;
    -
    5344 else if (this->model[0] == '0' && this->model[1] == '6')
    -
    5345 is_valid =
    -
    5346 this->part3.interval ?
    -
    5347 this->part1.interval.size() <= 12 && this->part2.interval.size() <= 12 && this->part3.interval.size() <= 12 &&
    -
    5348 this->part1.interval.size() + this->part2.interval.size() + this->part3.interval.size() <= 20 &&
    -
    5349 check11(
    -
    5350 text + this->part2.interval.start, this->part2.interval.size(),
    -
    5351 text + this->part3.interval.start, this->part3.interval.size()) :
    -
    5352 this->part2.interval ?
    -
    5353 this->part1.interval.size() <= 12 && this->part2.interval.size() <= 12 &&
    -
    5354 this->part1.interval.size() + this->part2.interval.size() <= 20 &&
    -
    5355 check11(text + this->part2.interval.start, this->part2.interval.size()) :
    -
    5356 false;
    -
    5357 else if (this->model[0] == '0' && this->model[1] == '7')
    -
    5358 is_valid =
    -
    5359 this->part3.interval ?
    -
    5360 this->part1.interval.size() <= 12 && this->part2.interval.size() <= 12 && this->part3.interval.size() <= 12 &&
    -
    5361 this->part1.interval.size() + this->part2.interval.size() + this->part3.interval.size() <= 20 &&
    -
    5362 check11(text + this->part2.interval.start, this->part2.interval.size()) :
    -
    5363 this->part2.interval ?
    -
    5364 this->part1.interval.size() <= 12 && this->part2.interval.size() <= 12 &&
    -
    5365 this->part1.interval.size() + this->part2.interval.size() <= 20 &&
    -
    5366 check11(text + this->part2.interval.start, this->part2.interval.size()) :
    -
    5367 false;
    -
    5368 else if (this->model[0] == '0' && this->model[1] == '8')
    -
    5369 is_valid =
    -
    5370 this->part3.interval ?
    -
    5371 this->part1.interval.size() <= 12 && this->part2.interval.size() <= 12 && this->part3.interval.size() <= 12 &&
    -
    5372 this->part1.interval.size() + this->part2.interval.size() + this->part3.interval.size() <= 20 &&
    -
    5373 check11(
    -
    5374 text + this->part1.interval.start, this->part1.interval.size(),
    -
    5375 text + this->part2.interval.start, this->part2.interval.size()) &&
    -
    5376 check11(text + this->part3.interval.start, this->part3.interval.size()) :
    -
    5377 false;
    -
    5378 else if (this->model[0] == '0' && this->model[1] == '9')
    -
    5379 is_valid =
    -
    5380 this->part3.interval ?
    -
    5381 this->part1.interval.size() <= 12 && this->part2.interval.size() <= 12 && this->part3.interval.size() <= 12 &&
    -
    5382 this->part1.interval.size() + this->part2.interval.size() + this->part3.interval.size() <= 20 &&
    -
    5383 check11(
    -
    5384 text + this->part1.interval.start, this->part1.interval.size(),
    -
    5385 text + this->part2.interval.start, this->part2.interval.size()) :
    -
    5386 this->part2.interval ?
    -
    5387 this->part1.interval.size() <= 12 && this->part2.interval.size() <= 12 &&
    -
    5388 this->part1.interval.size() + this->part2.interval.size() <= 20 &&
    -
    5389 check11(
    -
    5390 text + this->part1.interval.start, this->part1.interval.size(),
    -
    5391 text + this->part2.interval.start, this->part2.interval.size()) :
    -
    5392 this->part1.interval ?
    -
    5393 this->part1.interval.size() <= 12 &&
    -
    5394 check11(text + this->part1.interval.start, this->part1.interval.size()) :
    -
    5395 false;
    -
    5396 else if (this->model[0] == '1' && this->model[1] == '0')
    -
    5397 is_valid =
    -
    5398 this->part3.interval ?
    -
    5399 this->part1.interval.size() <= 12 && this->part2.interval.size() <= 12 && this->part3.interval.size() <= 12 &&
    -
    5400 this->part1.interval.size() + this->part2.interval.size() + this->part3.interval.size() <= 20 &&
    -
    5401 check11(text + this->part1.interval.start, this->part1.interval.size()) &&
    -
    5402 check11(
    -
    5403 text + this->part2.interval.start, this->part2.interval.size(),
    -
    5404 text + this->part3.interval.start, this->part3.interval.size()) :
    -
    5405 this->part2.interval ?
    -
    5406 this->part1.interval.size() <= 12 && this->part2.interval.size() <= 12 &&
    -
    5407 this->part1.interval.size() + this->part2.interval.size() <= 20 &&
    -
    5408 check11(text + this->part1.interval.start, this->part1.interval.size()) &&
    -
    5409 check11(text + this->part2.interval.start, this->part2.interval.size()) :
    -
    5410 false;
    -
    5411 else if (
    -
    5412 (this->model[0] == '1' && (this->model[1] == '1' || this->model[1] == '8' || this->model[1] == '9')) ||
    -
    5413 ((this->model[0] == '2' || this->model[0] == '3') && this->model[1] == '8') ||
    -
    5414 (this->model[0] == '4' && (this->model[1] == '0' || this->model[1] == '1' || this->model[1] == '8' || this->model[1] == '9')) ||
    -
    5415 (this->model[0] == '5' && (this->model[1] == '1' || this->model[1] == '8')))
    -
    5416 is_valid =
    -
    5417 this->part3.interval ?
    -
    5418 this->part1.interval.size() <= 12 && this->part2.interval.size() <= 12 && this->part3.interval.size() <= 12 &&
    -
    5419 this->part1.interval.size() + this->part2.interval.size() + this->part3.interval.size() <= 20 &&
    -
    5420 check11(text + this->part1.interval.start, this->part1.interval.size()) &&
    -
    5421 check11(text + this->part2.interval.start, this->part2.interval.size()) :
    -
    5422 this->part2.interval ?
    -
    5423 this->part1.interval.size() <= 12 && this->part2.interval.size() <= 12 &&
    -
    5424 this->part1.interval.size() + this->part2.interval.size() <= 20 &&
    -
    5425 check11(text + this->part1.interval.start, this->part1.interval.size()) &&
    -
    5426 check11(text + this->part2.interval.start, this->part2.interval.size()) :
    -
    5427 false;
    -
    5428 else if (this->model[0] == '1' && this->model[1] == '2')
    -
    5429 is_valid =
    -
    5430 this->part3.interval ? false :
    -
    5431 this->part2.interval ? false :
    -
    5432 this->part1.interval ?
    -
    5433 this->part1.interval.size() <= 13 &&
    -
    5434 check11(text + this->part1.interval.start, this->part1.interval.size()) :
    -
    5435 false;
    -
    5436 else if ((this->model[0] == '2' || this->model[0] == '3') && this->model[1] == '1')
    -
    5437 is_valid =
    -
    5438 this->part3.interval ? false :
    -
    5439 this->part2.interval ?
    -
    5440 this->part1.interval.size() <= 12 && this->part2.interval.size() <= 12 &&
    -
    5441 this->part1.interval.size() + this->part2.interval.size() <= 20 &&
    -
    5442 check11(text + this->part1.interval.start, this->part1.interval.size()) :
    -
    5443 false;
    -
    5444 else
    -
    5445 is_valid = true; // Assume models we don't handle as valid
    -
    5446 return true;
    -
    5447
    -
    5448 error:
    -
    5449 this->model[0] = 0;
    -
    5450 this->part1.interval.start = (this->part1.interval.end = start) + 1;
    -
    5451 this->part2.interval.start = (this->part2.interval.end = start) + 1;
    -
    5452 this->part3.interval.start = (this->part3.interval.end = start) + 1;
    -
    5453 this->is_valid = false;
    -
    5454 this->interval.start = (this->interval.end = start) + 1;
    -
    5455 return false;
    -
    5456 }
    -
    5457
    -
    5458 virtual void invalidate()
    -
    5459 {
    -
    5460 this->model[0] = 0;
    -
    5461 this->part1.invalidate();
    -
    5462 this->part2.invalidate();
    -
    5463 this->part3.invalidate();
    -
    5464 this->is_valid = false;
    - -
    5466 }
    -
    5467
    -
    5468 protected:
    -
    5469 static bool check11(
    -
    5470 _In_count_(num_part1) const T* part1, _In_ size_t num_part1)
    -
    5471 {
    -
    5472 _Assume_(part1 && num_part1 >= 1);
    -
    5473 uint32_t nominator = 0, ponder = 2;
    -
    5474 for (size_t i = num_part1 - 1; i--; ++ponder)
    -
    5475 nominator += (part1[i] - '0') * ponder;
    -
    5476 uint8_t control = 11 - static_cast<uint8_t>(nominator % 11);
    -
    5477 if (control >= 10)
    -
    5478 control = 0;
    -
    5479 return control == part1[num_part1 - 1] - '0';
    -
    5480 }
    -
    5481
    -
    5482 static bool check11(
    -
    5483 _In_count_(num_part1) const T* part1, _In_ size_t num_part1,
    -
    5484 _In_count_(num_part2) const T* part2, _In_ size_t num_part2)
    -
    5485 {
    -
    5486 _Assume_(part1 || !num_part1);
    -
    5487 _Assume_(part2 && num_part2 >= 1);
    -
    5488 uint32_t nominator = 0, ponder = 2;
    -
    5489 for (size_t i = num_part2 - 1; i--; ++ponder)
    -
    5490 nominator += (part2[i] - '0') * ponder;
    -
    5491 for (size_t i = num_part1; i--; ++ponder)
    -
    5492 nominator += (part1[i] - '0') * ponder;
    -
    5493 uint8_t control = 11 - static_cast<uint8_t>(nominator % 11);
    -
    5494 if (control == 10)
    -
    5495 control = 0;
    -
    5496 return control == part2[num_part2 - 1] - '0';
    -
    5497 }
    -
    5498
    -
    5499 static bool check11(
    -
    5500 _In_count_(num_part1) const T* part1, _In_ size_t num_part1,
    -
    5501 _In_count_(num_part2) const T* part2, _In_ size_t num_part2,
    -
    5502 _In_count_(num_part3) const T* part3, _In_ size_t num_part3)
    -
    5503 {
    -
    5504 _Assume_(part1 || !num_part1);
    -
    5505 _Assume_(part2 || !num_part2);
    -
    5506 _Assume_(part3 && num_part3 >= 1);
    -
    5507 uint32_t nominator = 0, ponder = 2;
    -
    5508 for (size_t i = num_part3 - 1; i--; ++ponder)
    -
    5509 nominator += (part3[i] - '0') * ponder;
    -
    5510 for (size_t i = num_part2; i--; ++ponder)
    -
    5511 nominator += (part2[i] - '0') * ponder;
    -
    5512 for (size_t i = num_part1; i--; ++ponder)
    -
    5513 nominator += (part1[i] - '0') * ponder;
    -
    5514 uint8_t control = 11 - static_cast<uint8_t>(nominator % 11);
    -
    5515 if (control == 10)
    -
    5516 control = 0;
    -
    5517 return control == part2[num_part3 - 1] - '0';
    -
    5518 }
    -
    5519
    -
    5520 public:
    -
    5521 T model[3];
    - - - - -
    5526
    -
    5527 protected:
    -
    5528 std::shared_ptr<basic_parser<T>> m_space;
    - -
    5530 };
    +
    5256 this->part1.match(text, this->interval.end, end, flags) &&
    +
    5257 this->m_delimiter.match(text, this->part1.interval.end, end, flags) &&
    +
    5258 this->part2.match(text, this->m_delimiter.interval.end, end, flags) &&
    +
    5259 this->m_delimiter.match(text, this->part2.interval.end, end, flags) &&
    +
    5260 this->part3.match(text, this->m_delimiter.interval.end, end, flags);
    +
    5261
    +
    5262 this->interval.start = start;
    +
    5263 if (this->part3.interval)
    +
    5264 this->interval.end = this->part3.interval.end;
    +
    5265 else if (this->part2.interval)
    +
    5266 this->interval.end = this->part2.interval.end;
    +
    5267 else if (this->part1.interval)
    +
    5268 this->interval.end = this->part1.interval.end;
    +
    5269 else
    +
    5270 this->interval.end = start + 4;
    +
    5271
    +
    5272 if (this->model[0] == '0' && this->model[1] == '0')
    +
    5273 is_valid =
    +
    5274 this->part3.interval ?
    +
    5275 this->part1.interval.size() <= 12 && this->part2.interval.size() <= 12 && this->part3.interval.size() <= 12 &&
    +
    5276 this->part1.interval.size() + this->part2.interval.size() + this->part3.interval.size() <= 20 :
    +
    5277 this->part2.interval ?
    +
    5278 this->part1.interval.size() <= 12 && this->part2.interval.size() <= 12 &&
    +
    5279 this->part1.interval.size() + this->part2.interval.size() <= 20 :
    +
    5280 this->part1.interval ?
    +
    5281 this->part1.interval.size() <= 12 :
    +
    5282 false;
    +
    5283 else if (this->model[0] == '0' && this->model[1] == '1')
    +
    5284 is_valid =
    +
    5285 this->part3.interval ?
    +
    5286 this->part1.interval.size() <= 12 && this->part2.interval.size() <= 12 && this->part3.interval.size() <= 12 &&
    +
    5287 this->part1.interval.size() + this->part2.interval.size() + this->part3.interval.size() <= 20 &&
    +
    5288 check11(
    +
    5289 text + this->part1.interval.start, this->part1.interval.size(),
    +
    5290 text + this->part2.interval.start, this->part2.interval.size(),
    +
    5291 text + this->part3.interval.start, this->part3.interval.size()) :
    +
    5292 this->part2.interval ?
    +
    5293 this->part1.interval.size() <= 12 && this->part2.interval.size() <= 12 &&
    +
    5294 this->part1.interval.size() + this->part2.interval.size() <= 20 &&
    +
    5295 check11(
    +
    5296 text + this->part1.interval.start, this->part1.interval.size(),
    +
    5297 text + this->part2.interval.start, this->part2.interval.size()) :
    +
    5298 this->part1.interval ?
    +
    5299 this->part1.interval.size() <= 12 &&
    +
    5300 check11(text + this->part1.interval.start, this->part1.interval.size()) :
    +
    5301 false;
    +
    5302 else if (this->model[0] == '0' && this->model[1] == '2')
    +
    5303 is_valid =
    +
    5304 this->part3.interval ?
    +
    5305 this->part1.interval.size() <= 12 && this->part2.interval.size() <= 12 && this->part3.interval.size() <= 12 &&
    +
    5306 this->part1.interval.size() + this->part2.interval.size() + this->part3.interval.size() <= 20 &&
    +
    5307 check11(text + this->part2.interval.start, this->part2.interval.size()) &&
    +
    5308 check11(text + this->part3.interval.start, this->part3.interval.size()) :
    +
    5309 false;
    +
    5310 else if (this->model[0] == '0' && this->model[1] == '3')
    +
    5311 is_valid =
    +
    5312 this->part3.interval ?
    +
    5313 this->part1.interval.size() <= 12 && this->part2.interval.size() <= 12 && this->part3.interval.size() <= 12 &&
    +
    5314 this->part1.interval.size() + this->part2.interval.size() + this->part3.interval.size() <= 20 &&
    +
    5315 check11(text + this->part1.interval.start, this->part1.interval.size()) &&
    +
    5316 check11(text + this->part2.interval.start, this->part2.interval.size()) &&
    +
    5317 check11(text + this->part3.interval.start, this->part3.interval.size()) :
    +
    5318 false;
    +
    5319 else if (this->model[0] == '0' && this->model[1] == '4')
    +
    5320 is_valid =
    +
    5321 this->part3.interval ?
    +
    5322 this->part1.interval.size() <= 12 && this->part2.interval.size() <= 12 && this->part3.interval.size() <= 12 &&
    +
    5323 this->part1.interval.size() + this->part2.interval.size() + this->part3.interval.size() <= 20 &&
    +
    5324 check11(text + this->part1.interval.start, this->part1.interval.size()) &&
    +
    5325 check11(text + this->part3.interval.start, this->part3.interval.size()) :
    +
    5326 false;
    +
    5327 else if ((this->model[0] == '0' || this->model[0] == '5') && this->model[1] == '5')
    +
    5328 is_valid =
    +
    5329 this->part3.interval ?
    +
    5330 this->part1.interval.size() <= 12 && this->part2.interval.size() <= 12 && this->part3.interval.size() <= 12 &&
    +
    5331 this->part1.interval.size() + this->part2.interval.size() + this->part3.interval.size() <= 20 &&
    +
    5332 check11(text + this->part1.interval.start, this->part1.interval.size()) :
    +
    5333 this->part2.interval ?
    +
    5334 this->part1.interval.size() <= 12 && this->part2.interval.size() <= 12 &&
    +
    5335 this->part1.interval.size() + this->part2.interval.size() <= 20 &&
    +
    5336 check11(text + this->part1.interval.start, this->part1.interval.size()) :
    +
    5337 this->part1.interval ?
    +
    5338 this->part1.interval.size() <= 12 &&
    +
    5339 check11(text + this->part1.interval.start, this->part1.interval.size()) :
    +
    5340 false;
    +
    5341 else if (this->model[0] == '0' && this->model[1] == '6')
    +
    5342 is_valid =
    +
    5343 this->part3.interval ?
    +
    5344 this->part1.interval.size() <= 12 && this->part2.interval.size() <= 12 && this->part3.interval.size() <= 12 &&
    +
    5345 this->part1.interval.size() + this->part2.interval.size() + this->part3.interval.size() <= 20 &&
    +
    5346 check11(
    +
    5347 text + this->part2.interval.start, this->part2.interval.size(),
    +
    5348 text + this->part3.interval.start, this->part3.interval.size()) :
    +
    5349 this->part2.interval ?
    +
    5350 this->part1.interval.size() <= 12 && this->part2.interval.size() <= 12 &&
    +
    5351 this->part1.interval.size() + this->part2.interval.size() <= 20 &&
    +
    5352 check11(text + this->part2.interval.start, this->part2.interval.size()) :
    +
    5353 false;
    +
    5354 else if (this->model[0] == '0' && this->model[1] == '7')
    +
    5355 is_valid =
    +
    5356 this->part3.interval ?
    +
    5357 this->part1.interval.size() <= 12 && this->part2.interval.size() <= 12 && this->part3.interval.size() <= 12 &&
    +
    5358 this->part1.interval.size() + this->part2.interval.size() + this->part3.interval.size() <= 20 &&
    +
    5359 check11(text + this->part2.interval.start, this->part2.interval.size()) :
    +
    5360 this->part2.interval ?
    +
    5361 this->part1.interval.size() <= 12 && this->part2.interval.size() <= 12 &&
    +
    5362 this->part1.interval.size() + this->part2.interval.size() <= 20 &&
    +
    5363 check11(text + this->part2.interval.start, this->part2.interval.size()) :
    +
    5364 false;
    +
    5365 else if (this->model[0] == '0' && this->model[1] == '8')
    +
    5366 is_valid =
    +
    5367 this->part3.interval ?
    +
    5368 this->part1.interval.size() <= 12 && this->part2.interval.size() <= 12 && this->part3.interval.size() <= 12 &&
    +
    5369 this->part1.interval.size() + this->part2.interval.size() + this->part3.interval.size() <= 20 &&
    +
    5370 check11(
    +
    5371 text + this->part1.interval.start, this->part1.interval.size(),
    +
    5372 text + this->part2.interval.start, this->part2.interval.size()) &&
    +
    5373 check11(text + this->part3.interval.start, this->part3.interval.size()) :
    +
    5374 false;
    +
    5375 else if (this->model[0] == '0' && this->model[1] == '9')
    +
    5376 is_valid =
    +
    5377 this->part3.interval ?
    +
    5378 this->part1.interval.size() <= 12 && this->part2.interval.size() <= 12 && this->part3.interval.size() <= 12 &&
    +
    5379 this->part1.interval.size() + this->part2.interval.size() + this->part3.interval.size() <= 20 &&
    +
    5380 check11(
    +
    5381 text + this->part1.interval.start, this->part1.interval.size(),
    +
    5382 text + this->part2.interval.start, this->part2.interval.size()) :
    +
    5383 this->part2.interval ?
    +
    5384 this->part1.interval.size() <= 12 && this->part2.interval.size() <= 12 &&
    +
    5385 this->part1.interval.size() + this->part2.interval.size() <= 20 &&
    +
    5386 check11(
    +
    5387 text + this->part1.interval.start, this->part1.interval.size(),
    +
    5388 text + this->part2.interval.start, this->part2.interval.size()) :
    +
    5389 this->part1.interval ?
    +
    5390 this->part1.interval.size() <= 12 &&
    +
    5391 check11(text + this->part1.interval.start, this->part1.interval.size()) :
    +
    5392 false;
    +
    5393 else if (this->model[0] == '1' && this->model[1] == '0')
    +
    5394 is_valid =
    +
    5395 this->part3.interval ?
    +
    5396 this->part1.interval.size() <= 12 && this->part2.interval.size() <= 12 && this->part3.interval.size() <= 12 &&
    +
    5397 this->part1.interval.size() + this->part2.interval.size() + this->part3.interval.size() <= 20 &&
    +
    5398 check11(text + this->part1.interval.start, this->part1.interval.size()) &&
    +
    5399 check11(
    +
    5400 text + this->part2.interval.start, this->part2.interval.size(),
    +
    5401 text + this->part3.interval.start, this->part3.interval.size()) :
    +
    5402 this->part2.interval ?
    +
    5403 this->part1.interval.size() <= 12 && this->part2.interval.size() <= 12 &&
    +
    5404 this->part1.interval.size() + this->part2.interval.size() <= 20 &&
    +
    5405 check11(text + this->part1.interval.start, this->part1.interval.size()) &&
    +
    5406 check11(text + this->part2.interval.start, this->part2.interval.size()) :
    +
    5407 false;
    +
    5408 else if (
    +
    5409 (this->model[0] == '1' && (this->model[1] == '1' || this->model[1] == '8' || this->model[1] == '9')) ||
    +
    5410 ((this->model[0] == '2' || this->model[0] == '3') && this->model[1] == '8') ||
    +
    5411 (this->model[0] == '4' && (this->model[1] == '0' || this->model[1] == '1' || this->model[1] == '8' || this->model[1] == '9')) ||
    +
    5412 (this->model[0] == '5' && (this->model[1] == '1' || this->model[1] == '8')))
    +
    5413 is_valid =
    +
    5414 this->part3.interval ?
    +
    5415 this->part1.interval.size() <= 12 && this->part2.interval.size() <= 12 && this->part3.interval.size() <= 12 &&
    +
    5416 this->part1.interval.size() + this->part2.interval.size() + this->part3.interval.size() <= 20 &&
    +
    5417 check11(text + this->part1.interval.start, this->part1.interval.size()) &&
    +
    5418 check11(text + this->part2.interval.start, this->part2.interval.size()) :
    +
    5419 this->part2.interval ?
    +
    5420 this->part1.interval.size() <= 12 && this->part2.interval.size() <= 12 &&
    +
    5421 this->part1.interval.size() + this->part2.interval.size() <= 20 &&
    +
    5422 check11(text + this->part1.interval.start, this->part1.interval.size()) &&
    +
    5423 check11(text + this->part2.interval.start, this->part2.interval.size()) :
    +
    5424 false;
    +
    5425 else if (this->model[0] == '1' && this->model[1] == '2')
    +
    5426 is_valid =
    +
    5427 this->part3.interval ? false :
    +
    5428 this->part2.interval ? false :
    +
    5429 this->part1.interval ?
    +
    5430 this->part1.interval.size() <= 13 &&
    +
    5431 check11(text + this->part1.interval.start, this->part1.interval.size()) :
    +
    5432 false;
    +
    5433 else if ((this->model[0] == '2' || this->model[0] == '3') && this->model[1] == '1')
    +
    5434 is_valid =
    +
    5435 this->part3.interval ? false :
    +
    5436 this->part2.interval ?
    +
    5437 this->part1.interval.size() <= 12 && this->part2.interval.size() <= 12 &&
    +
    5438 this->part1.interval.size() + this->part2.interval.size() <= 20 &&
    +
    5439 check11(text + this->part1.interval.start, this->part1.interval.size()) :
    +
    5440 false;
    +
    5441 else
    +
    5442 is_valid = true; // Assume models we don't handle as valid
    +
    5443 return true;
    +
    5444
    +
    5445 error:
    +
    5446 this->model[0] = 0;
    +
    5447 this->part1.interval.start = (this->part1.interval.end = start) + 1;
    +
    5448 this->part2.interval.start = (this->part2.interval.end = start) + 1;
    +
    5449 this->part3.interval.start = (this->part3.interval.end = start) + 1;
    +
    5450 this->is_valid = false;
    +
    5451 this->interval.start = (this->interval.end = start) + 1;
    +
    5452 return false;
    +
    5453 }
    +
    5454
    +
    5455 virtual void invalidate()
    +
    5456 {
    +
    5457 this->model[0] = 0;
    +
    5458 this->part1.invalidate();
    +
    5459 this->part2.invalidate();
    +
    5460 this->part3.invalidate();
    +
    5461 this->is_valid = false;
    + +
    5463 }
    +
    5464
    +
    5465 protected:
    +
    5466 static bool check11(
    +
    5467 _In_count_(num_part1) const T* part1, _In_ size_t num_part1)
    +
    5468 {
    +
    5469 _Assume_(part1 && num_part1 >= 1);
    +
    5470 uint32_t nominator = 0, ponder = 2;
    +
    5471 for (size_t i = num_part1 - 1; i--; ++ponder)
    +
    5472 nominator += (part1[i] - '0') * ponder;
    +
    5473 uint8_t control = 11 - static_cast<uint8_t>(nominator % 11);
    +
    5474 if (control >= 10)
    +
    5475 control = 0;
    +
    5476 return control == part1[num_part1 - 1] - '0';
    +
    5477 }
    +
    5478
    +
    5479 static bool check11(
    +
    5480 _In_count_(num_part1) const T* part1, _In_ size_t num_part1,
    +
    5481 _In_count_(num_part2) const T* part2, _In_ size_t num_part2)
    +
    5482 {
    +
    5483 _Assume_(part1 || !num_part1);
    +
    5484 _Assume_(part2 && num_part2 >= 1);
    +
    5485 uint32_t nominator = 0, ponder = 2;
    +
    5486 for (size_t i = num_part2 - 1; i--; ++ponder)
    +
    5487 nominator += (part2[i] - '0') * ponder;
    +
    5488 for (size_t i = num_part1; i--; ++ponder)
    +
    5489 nominator += (part1[i] - '0') * ponder;
    +
    5490 uint8_t control = 11 - static_cast<uint8_t>(nominator % 11);
    +
    5491 if (control == 10)
    +
    5492 control = 0;
    +
    5493 return control == part2[num_part2 - 1] - '0';
    +
    5494 }
    +
    5495
    +
    5496 static bool check11(
    +
    5497 _In_count_(num_part1) const T* part1, _In_ size_t num_part1,
    +
    5498 _In_count_(num_part2) const T* part2, _In_ size_t num_part2,
    +
    5499 _In_count_(num_part3) const T* part3, _In_ size_t num_part3)
    +
    5500 {
    +
    5501 _Assume_(part1 || !num_part1);
    +
    5502 _Assume_(part2 || !num_part2);
    +
    5503 _Assume_(part3 && num_part3 >= 1);
    +
    5504 uint32_t nominator = 0, ponder = 2;
    +
    5505 for (size_t i = num_part3 - 1; i--; ++ponder)
    +
    5506 nominator += (part3[i] - '0') * ponder;
    +
    5507 for (size_t i = num_part2; i--; ++ponder)
    +
    5508 nominator += (part2[i] - '0') * ponder;
    +
    5509 for (size_t i = num_part1; i--; ++ponder)
    +
    5510 nominator += (part1[i] - '0') * ponder;
    +
    5511 uint8_t control = 11 - static_cast<uint8_t>(nominator % 11);
    +
    5512 if (control == 10)
    +
    5513 control = 0;
    +
    5514 return control == part2[num_part3 - 1] - '0';
    +
    5515 }
    +
    5516
    +
    5517 public:
    +
    5518 T model[3];
    + + + + +
    5523
    +
    5524 protected:
    +
    5525 std::shared_ptr<basic_parser<T>> m_space;
    + +
    5527 };
    -
    5531
    - - -
    5534#ifdef _UNICODE
    - -
    5536#else
    - -
    5538#endif
    - -
    5540
    -
    5544 template <class T>
    -
    - -
    5546 {
    -
    5547 public:
    - -
    5549 _In_ const std::shared_ptr<basic_parser<T>>& element,
    -
    5550 _In_ const std::shared_ptr<basic_parser<T>>& digit,
    -
    5551 _In_ const std::shared_ptr<basic_parser<T>>& sign,
    -
    5552 _In_ const std::locale& locale = std::locale()) :
    -
    5553 basic_parser<T>(locale),
    -
    5554 m_element(element),
    -
    5555 m_digit(digit),
    -
    5556 m_sign(sign),
    -
    5557 has_digits(false),
    -
    5558 has_charge(false)
    -
    5559 {}
    -
    5560
    -
    5561 virtual bool match(
    -
    5562 _In_reads_or_z_(end) const T* text,
    -
    5563 _In_ size_t start = 0,
    -
    5564 _In_ size_t end = (size_t)-1,
    -
    5565 _In_ int flags = match_default)
    -
    5566 {
    -
    5567 _Assume_(text || start >= end);
    -
    5568
    -
    5569 has_digits = false;
    -
    5570 has_charge = false;
    -
    5571 this->interval.end = start;
    -
    5572
    -
    5573 const int element_match_flags = flags & ~match_case_insensitive; // Chemical elements are always case-sensitive.
    -
    5574 for (;;) {
    -
    5575 if (m_element->match(text, this->interval.end, end, element_match_flags)) {
    -
    5576 this->interval.end = m_element->interval.end;
    -
    5577 while (m_digit->match(text, this->interval.end, end, flags)) {
    -
    5578 this->interval.end = m_digit->interval.end;
    -
    5579 has_digits = true;
    -
    5580 }
    -
    5581 }
    -
    5582 else if (start < this->interval.end) {
    -
    5583 if (m_sign->match(text, this->interval.end, end, flags)) {
    -
    5584 this->interval.end = m_sign->interval.end;
    -
    5585 has_charge = true;
    -
    5586 }
    -
    5587 this->interval.start = start;
    -
    5588 return true;
    -
    5589 }
    -
    5590 else {
    -
    5591 this->interval.start = (this->interval.end = start) + 1;
    -
    5592 return false;
    -
    5593 }
    -
    5594 }
    -
    5595 }
    -
    5596
    -
    5597 virtual void invalidate()
    -
    5598 {
    -
    5599 has_digits = false;
    -
    5600 has_charge = false;
    - -
    5602 }
    -
    5603
    -
    5604 public:
    -
    5605 bool has_digits;
    -
    5606 bool has_charge;
    -
    5607
    -
    5608 protected:
    -
    5609 std::shared_ptr<basic_parser<T>> m_element;
    -
    5610 std::shared_ptr<basic_parser<T>> m_digit;
    -
    5611 std::shared_ptr<basic_parser<T>> m_sign;
    -
    5612 };
    +
    5528
    + + +
    5531#ifdef _UNICODE
    + +
    5533#else
    + +
    5535#endif
    + +
    5537
    +
    5541 template <class T>
    +
    + +
    5543 {
    +
    5544 public:
    + +
    5546 _In_ const std::shared_ptr<basic_parser<T>>& element,
    +
    5547 _In_ const std::shared_ptr<basic_parser<T>>& digit,
    +
    5548 _In_ const std::shared_ptr<basic_parser<T>>& sign,
    +
    5549 _In_ const std::locale& locale = std::locale()) :
    +
    5550 basic_parser<T>(locale),
    +
    5551 m_element(element),
    +
    5552 m_digit(digit),
    +
    5553 m_sign(sign),
    +
    5554 has_digits(false),
    +
    5555 has_charge(false)
    +
    5556 {}
    +
    5557
    +
    5558 virtual bool match(
    +
    5559 _In_reads_or_z_(end) const T* text,
    +
    5560 _In_ size_t start = 0,
    +
    5561 _In_ size_t end = (size_t)-1,
    +
    5562 _In_ int flags = match_default)
    +
    5563 {
    +
    5564 _Assume_(text || start >= end);
    +
    5565
    +
    5566 has_digits = false;
    +
    5567 has_charge = false;
    +
    5568 this->interval.end = start;
    +
    5569
    +
    5570 const int element_match_flags = flags & ~match_case_insensitive; // Chemical elements are always case-sensitive.
    +
    5571 for (;;) {
    +
    5572 if (m_element->match(text, this->interval.end, end, element_match_flags)) {
    +
    5573 this->interval.end = m_element->interval.end;
    +
    5574 while (m_digit->match(text, this->interval.end, end, flags)) {
    +
    5575 this->interval.end = m_digit->interval.end;
    +
    5576 has_digits = true;
    +
    5577 }
    +
    5578 }
    +
    5579 else if (start < this->interval.end) {
    +
    5580 if (m_sign->match(text, this->interval.end, end, flags)) {
    +
    5581 this->interval.end = m_sign->interval.end;
    +
    5582 has_charge = true;
    +
    5583 }
    +
    5584 this->interval.start = start;
    +
    5585 return true;
    +
    5586 }
    +
    5587 else {
    +
    5588 this->interval.start = (this->interval.end = start) + 1;
    +
    5589 return false;
    +
    5590 }
    +
    5591 }
    +
    5592 }
    +
    5593
    +
    5594 virtual void invalidate()
    +
    5595 {
    +
    5596 has_digits = false;
    +
    5597 has_charge = false;
    + +
    5599 }
    +
    5600
    +
    5601 public:
    +
    5602 bool has_digits;
    +
    5603 bool has_charge;
    +
    5604
    +
    5605 protected:
    +
    5606 std::shared_ptr<basic_parser<T>> m_element;
    +
    5607 std::shared_ptr<basic_parser<T>> m_digit;
    +
    5608 std::shared_ptr<basic_parser<T>> m_sign;
    +
    5609 };
    -
    5613
    - - -
    5616#ifdef _UNICODE
    - -
    5618#else
    - -
    5620#endif
    - -
    5622
    -
    - -
    5627 {
    -
    5628 public:
    -
    5629 virtual bool match(
    -
    5630 _In_reads_or_z_(end) const char* text,
    -
    5631 _In_ size_t start = 0,
    -
    5632 _In_ size_t end = (size_t)-1,
    -
    5633 _In_ int flags = match_default)
    -
    5634 {
    -
    5635 _Assume_(text || start >= end);
    -
    5636 this->interval.end = start;
    -
    5637
    -
    5638 _Assume_(text || this->interval.end >= end);
    -
    5639 if (this->interval.end < end && text[this->interval.end]) {
    -
    5640 if (text[this->interval.end] == '\r') {
    -
    5641 this->interval.end++;
    -
    5642 if (this->interval.end < end && text[this->interval.end] == '\n') {
    -
    5643 this->interval.start = start;
    -
    5644 this->interval.end++;
    -
    5645 return true;
    -
    5646 }
    -
    5647 }
    -
    5648 else if (text[this->interval.end] == '\n') {
    -
    5649 this->interval.start = start;
    -
    5650 this->interval.end++;
    -
    5651 return true;
    -
    5652 }
    -
    5653 }
    -
    5654 this->interval.start = (this->interval.end = start) + 1;
    -
    5655 return false;
    -
    5656 }
    -
    5657 };
    +
    5610
    + + +
    5613#ifdef _UNICODE
    + +
    5615#else
    + +
    5617#endif
    + +
    5619
    +
    + +
    5624 {
    +
    5625 public:
    +
    5626 virtual bool match(
    +
    5627 _In_reads_or_z_(end) const char* text,
    +
    5628 _In_ size_t start = 0,
    +
    5629 _In_ size_t end = (size_t)-1,
    +
    5630 _In_ int flags = match_default)
    +
    5631 {
    +
    5632 _Assume_(text || start >= end);
    +
    5633 this->interval.end = start;
    +
    5634
    +
    5635 _Assume_(text || this->interval.end >= end);
    +
    5636 if (this->interval.end < end && text[this->interval.end]) {
    +
    5637 if (text[this->interval.end] == '\r') {
    +
    5638 this->interval.end++;
    +
    5639 if (this->interval.end < end && text[this->interval.end] == '\n') {
    +
    5640 this->interval.start = start;
    +
    5641 this->interval.end++;
    +
    5642 return true;
    +
    5643 }
    +
    5644 }
    +
    5645 else if (text[this->interval.end] == '\n') {
    +
    5646 this->interval.start = start;
    +
    5647 this->interval.end++;
    +
    5648 return true;
    +
    5649 }
    +
    5650 }
    +
    5651 this->interval.start = (this->interval.end = start) + 1;
    +
    5652 return false;
    +
    5653 }
    +
    5654 };
    -
    5658
    -
    -
    5662 class http_space : public parser
    -
    5663 {
    -
    5664 public:
    -
    5665 virtual bool match(
    -
    5666 _In_reads_or_z_(end) const char* text,
    -
    5667 _In_ size_t start = 0,
    -
    5668 _In_ size_t end = (size_t)-1,
    -
    5669 _In_ int flags = match_default)
    -
    5670 {
    -
    5671 _Assume_(text || start >= end);
    -
    5672 this->interval.end = start;
    -
    5673 if (m_line_break.match(text, this->interval.end, end, flags)) {
    -
    5674 this->interval.end = m_line_break.interval.end;
    -
    5675 if (this->interval.end < end && text[this->interval.end] && isspace(text[this->interval.end])) {
    -
    5676 this->interval.start = start;
    -
    5677 this->interval.end++;
    -
    5678 while (this->interval.end < end && text[this->interval.end] && isspace(text[this->interval.end])) this->interval.end++;
    -
    5679 return true;
    -
    5680 }
    -
    5681 }
    -
    5682 else if (this->interval.end < end && text[this->interval.end] && isspace(text[this->interval.end])) {
    -
    5683 this->interval.start = start;
    -
    5684 this->interval.end++;
    -
    5685 while (this->interval.end < end && text[this->interval.end] && isspace(text[this->interval.end])) this->interval.end++;
    -
    5686 return true;
    -
    5687 }
    -
    5688 this->interval.start = (this->interval.end = start) + 1;
    -
    5689 return false;
    -
    5690 }
    -
    5691
    -
    5692 protected:
    -
    5693 http_line_break m_line_break;
    -
    5694 };
    +
    5655
    +
    +
    5659 class http_space : public parser
    +
    5660 {
    +
    5661 public:
    +
    5662 virtual bool match(
    +
    5663 _In_reads_or_z_(end) const char* text,
    +
    5664 _In_ size_t start = 0,
    +
    5665 _In_ size_t end = (size_t)-1,
    +
    5666 _In_ int flags = match_default)
    +
    5667 {
    +
    5668 _Assume_(text || start >= end);
    +
    5669 this->interval.end = start;
    +
    5670 if (m_line_break.match(text, this->interval.end, end, flags)) {
    +
    5671 this->interval.end = m_line_break.interval.end;
    +
    5672 if (this->interval.end < end && text[this->interval.end] && isspace(text[this->interval.end])) {
    +
    5673 this->interval.start = start;
    +
    5674 this->interval.end++;
    +
    5675 while (this->interval.end < end && text[this->interval.end] && isspace(text[this->interval.end])) this->interval.end++;
    +
    5676 return true;
    +
    5677 }
    +
    5678 }
    +
    5679 else if (this->interval.end < end && text[this->interval.end] && isspace(text[this->interval.end])) {
    +
    5680 this->interval.start = start;
    +
    5681 this->interval.end++;
    +
    5682 while (this->interval.end < end && text[this->interval.end] && isspace(text[this->interval.end])) this->interval.end++;
    +
    5683 return true;
    +
    5684 }
    +
    5685 this->interval.start = (this->interval.end = start) + 1;
    +
    5686 return false;
    +
    5687 }
    +
    5688
    +
    5689 protected:
    +
    5690 http_line_break m_line_break;
    +
    5691 };
    -
    5695
    -
    -
    5699 class http_text_char : public parser
    -
    5700 {
    -
    5701 public:
    -
    5702 virtual bool match(
    -
    5703 _In_reads_or_z_(end) const char* text,
    -
    5704 _In_ size_t start = 0,
    -
    5705 _In_ size_t end = (size_t)-1,
    -
    5706 _In_ int flags = match_default)
    -
    5707 {
    -
    5708 _Assume_(text || start >= end);
    -
    5709 this->interval.end = start;
    -
    5710
    -
    5711 _Assume_(text || this->interval.end >= end);
    -
    5712 if (m_space.match(text, this->interval.end, end, flags)) {
    -
    5713 this->interval.start = start;
    -
    5714 this->interval.end = m_space.interval.end;
    -
    5715 return true;
    -
    5716 }
    -
    5717 else if (this->interval.end < end && text[this->interval.end] && text[this->interval.end] >= 0x20) {
    -
    5718 this->interval.start = start;
    -
    5719 this->interval.end++;
    -
    5720 return true;
    -
    5721 }
    -
    5722 this->interval.start = (this->interval.end = start) + 1;
    -
    5723 return false;
    -
    5724 }
    -
    5725
    -
    5726 protected:
    -
    5727 http_space m_space;
    -
    5728 };
    +
    5692
    +
    +
    5696 class http_text_char : public parser
    +
    5697 {
    +
    5698 public:
    +
    5699 virtual bool match(
    +
    5700 _In_reads_or_z_(end) const char* text,
    +
    5701 _In_ size_t start = 0,
    +
    5702 _In_ size_t end = (size_t)-1,
    +
    5703 _In_ int flags = match_default)
    +
    5704 {
    +
    5705 _Assume_(text || start >= end);
    +
    5706 this->interval.end = start;
    +
    5707
    +
    5708 _Assume_(text || this->interval.end >= end);
    +
    5709 if (m_space.match(text, this->interval.end, end, flags)) {
    +
    5710 this->interval.start = start;
    +
    5711 this->interval.end = m_space.interval.end;
    +
    5712 return true;
    +
    5713 }
    +
    5714 else if (this->interval.end < end && text[this->interval.end] && text[this->interval.end] >= 0x20) {
    +
    5715 this->interval.start = start;
    +
    5716 this->interval.end++;
    +
    5717 return true;
    +
    5718 }
    +
    5719 this->interval.start = (this->interval.end = start) + 1;
    +
    5720 return false;
    +
    5721 }
    +
    5722
    +
    5723 protected:
    +
    5724 http_space m_space;
    +
    5725 };
    -
    5729
    -
    -
    5733 class http_token : public parser
    -
    5734 {
    -
    5735 public:
    -
    5736 virtual bool match(
    -
    5737 _In_reads_or_z_(end) const char* text,
    -
    5738 _In_ size_t start = 0,
    -
    5739 _In_ size_t end = (size_t)-1,
    -
    5740 _In_ int flags = match_default)
    -
    5741 {
    -
    5742 _Assume_(text || start >= end);
    -
    5743 this->interval.end = start;
    -
    5744 for (;;) {
    -
    5745 if (this->interval.end < end && text[this->interval.end]) {
    -
    5746 if ((unsigned int)text[this->interval.end] < 0x20 ||
    -
    5747 (unsigned int)text[this->interval.end] == 0x7f ||
    -
    5748 text[this->interval.end] == '(' ||
    -
    5749 text[this->interval.end] == ')' ||
    -
    5750 text[this->interval.end] == '<' ||
    -
    5751 text[this->interval.end] == '>' ||
    -
    5752 text[this->interval.end] == '@' ||
    -
    5753 text[this->interval.end] == ',' ||
    -
    5754 text[this->interval.end] == ';' ||
    -
    5755 text[this->interval.end] == ':' ||
    -
    5756 text[this->interval.end] == '\\' ||
    -
    5757 text[this->interval.end] == '\"' ||
    -
    5758 text[this->interval.end] == '/' ||
    -
    5759 text[this->interval.end] == '[' ||
    -
    5760 text[this->interval.end] == ']' ||
    -
    5761 text[this->interval.end] == '?' ||
    -
    5762 text[this->interval.end] == '=' ||
    -
    5763 text[this->interval.end] == '{' ||
    -
    5764 text[this->interval.end] == '}' ||
    -
    5765 isspace(text[this->interval.end]))
    -
    5766 break;
    -
    5767 else
    -
    5768 this->interval.end++;
    -
    5769 }
    -
    5770 else
    -
    5771 break;
    -
    5772 }
    - -
    5774 this->interval.start = start;
    -
    5775 return true;
    -
    5776 }
    -
    5777 else {
    -
    5778 this->interval.start = (this->interval.end = start) + 1;
    -
    5779 return false;
    -
    5780 }
    -
    5781 }
    -
    5782 };
    +
    5726
    +
    +
    5730 class http_token : public parser
    +
    5731 {
    +
    5732 public:
    +
    5733 virtual bool match(
    +
    5734 _In_reads_or_z_(end) const char* text,
    +
    5735 _In_ size_t start = 0,
    +
    5736 _In_ size_t end = (size_t)-1,
    +
    5737 _In_ int flags = match_default)
    +
    5738 {
    +
    5739 _Assume_(text || start >= end);
    +
    5740 this->interval.end = start;
    +
    5741 for (;;) {
    +
    5742 if (this->interval.end < end && text[this->interval.end]) {
    +
    5743 if ((unsigned int)text[this->interval.end] < 0x20 ||
    +
    5744 (unsigned int)text[this->interval.end] == 0x7f ||
    +
    5745 text[this->interval.end] == '(' ||
    +
    5746 text[this->interval.end] == ')' ||
    +
    5747 text[this->interval.end] == '<' ||
    +
    5748 text[this->interval.end] == '>' ||
    +
    5749 text[this->interval.end] == '@' ||
    +
    5750 text[this->interval.end] == ',' ||
    +
    5751 text[this->interval.end] == ';' ||
    +
    5752 text[this->interval.end] == ':' ||
    +
    5753 text[this->interval.end] == '\\' ||
    +
    5754 text[this->interval.end] == '\"' ||
    +
    5755 text[this->interval.end] == '/' ||
    +
    5756 text[this->interval.end] == '[' ||
    +
    5757 text[this->interval.end] == ']' ||
    +
    5758 text[this->interval.end] == '?' ||
    +
    5759 text[this->interval.end] == '=' ||
    +
    5760 text[this->interval.end] == '{' ||
    +
    5761 text[this->interval.end] == '}' ||
    +
    5762 isspace(text[this->interval.end]))
    +
    5763 break;
    +
    5764 else
    +
    5765 this->interval.end++;
    +
    5766 }
    +
    5767 else
    +
    5768 break;
    +
    5769 }
    + +
    5771 this->interval.start = start;
    +
    5772 return true;
    +
    5773 }
    +
    5774 else {
    +
    5775 this->interval.start = (this->interval.end = start) + 1;
    +
    5776 return false;
    +
    5777 }
    +
    5778 }
    +
    5779 };
    -
    5783
    -
    - -
    5788 {
    -
    5789 public:
    -
    5790 virtual bool match(
    -
    5791 _In_reads_or_z_(end) const char* text,
    -
    5792 _In_ size_t start = 0,
    -
    5793 _In_ size_t end = (size_t)-1,
    -
    5794 _In_ int flags = match_default)
    -
    5795 {
    -
    5796 _Assume_(text || start >= end);
    -
    5797 this->interval.end = start;
    -
    5798 if (this->interval.end < end && text[this->interval.end] != '"')
    -
    5799 goto error;
    -
    5800 this->interval.end++;
    -
    5801 content.start = this->interval.end;
    -
    5802 for (;;) {
    -
    5803 _Assume_(text || this->interval.end >= end);
    -
    5804 if (this->interval.end < end && text[this->interval.end]) {
    -
    5805 if (text[this->interval.end] == '"') {
    -
    5806 content.end = this->interval.end;
    -
    5807 this->interval.end++;
    -
    5808 break;
    -
    5809 }
    -
    5810 else if (text[this->interval.end] == '\\') {
    -
    5811 this->interval.end++;
    -
    5812 if (this->interval.end < end && text[this->interval.end]) {
    -
    5813 this->interval.end++;
    -
    5814 }
    -
    5815 else
    -
    5816 goto error;
    -
    5817 }
    -
    5818 else if (m_chr.match(text, this->interval.end, end, flags))
    -
    5819 this->interval.end++;
    -
    5820 else
    -
    5821 goto error;
    -
    5822 }
    -
    5823 else
    -
    5824 goto error;
    -
    5825 }
    -
    5826 this->interval.start = start;
    -
    5827 return true;
    -
    5828
    -
    5829 error:
    -
    5830 content.start = 1;
    -
    5831 content.end = 0;
    -
    5832 this->interval.start = (this->interval.end = start) + 1;
    -
    5833 return false;
    -
    5834 }
    -
    5835
    -
    5836 virtual void invalidate()
    -
    5837 {
    -
    5838 content.start = 1;
    -
    5839 content.end = 0;
    -
    5840 parser::invalidate();
    -
    5841 }
    +
    5780
    +
    + +
    5785 {
    +
    5786 public:
    +
    5787 virtual bool match(
    +
    5788 _In_reads_or_z_(end) const char* text,
    +
    5789 _In_ size_t start = 0,
    +
    5790 _In_ size_t end = (size_t)-1,
    +
    5791 _In_ int flags = match_default)
    +
    5792 {
    +
    5793 _Assume_(text || start >= end);
    +
    5794 this->interval.end = start;
    +
    5795 if (this->interval.end < end && text[this->interval.end] != '"')
    +
    5796 goto error;
    +
    5797 this->interval.end++;
    +
    5798 content.start = this->interval.end;
    +
    5799 for (;;) {
    +
    5800 _Assume_(text || this->interval.end >= end);
    +
    5801 if (this->interval.end < end && text[this->interval.end]) {
    +
    5802 if (text[this->interval.end] == '"') {
    +
    5803 content.end = this->interval.end;
    +
    5804 this->interval.end++;
    +
    5805 break;
    +
    5806 }
    +
    5807 else if (text[this->interval.end] == '\\') {
    +
    5808 this->interval.end++;
    +
    5809 if (this->interval.end < end && text[this->interval.end]) {
    +
    5810 this->interval.end++;
    +
    5811 }
    +
    5812 else
    +
    5813 goto error;
    +
    5814 }
    +
    5815 else if (m_chr.match(text, this->interval.end, end, flags))
    +
    5816 this->interval.end++;
    +
    5817 else
    +
    5818 goto error;
    +
    5819 }
    +
    5820 else
    +
    5821 goto error;
    +
    5822 }
    +
    5823 this->interval.start = start;
    +
    5824 return true;
    +
    5825
    +
    5826 error:
    +
    5827 content.start = 1;
    +
    5828 content.end = 0;
    +
    5829 this->interval.start = (this->interval.end = start) + 1;
    +
    5830 return false;
    +
    5831 }
    +
    5832
    +
    5833 virtual void invalidate()
    +
    5834 {
    +
    5835 content.start = 1;
    +
    5836 content.end = 0;
    +
    5837 parser::invalidate();
    +
    5838 }
    +
    5839
    +
    5840 public:
    +
    5842
    -
    5843 public:
    - -
    5845
    -
    5846 protected:
    -
    5847 http_text_char m_chr;
    -
    5848 };
    +
    5843 protected:
    +
    5844 http_text_char m_chr;
    +
    5845 };
    -
    5849
    -
    -
    5853 class http_value : public parser
    -
    5854 {
    -
    5855 public:
    -
    5856 virtual bool match(
    -
    5857 _In_reads_or_z_(end) const char* text,
    -
    5858 _In_ size_t start = 0,
    -
    5859 _In_ size_t end = (size_t)-1,
    -
    5860 _In_ int flags = match_default)
    -
    5861 {
    -
    5862 _Assume_(text || start >= end);
    -
    5863 this->interval.end = start;
    -
    5864 if (string.match(text, this->interval.end, end, flags)) {
    -
    5865 token.invalidate();
    -
    5866 this->interval.end = string.interval.end;
    -
    5867 this->interval.start = start;
    -
    5868 return true;
    -
    5869 }
    -
    5870 else if (token.match(text, this->interval.end, end, flags)) {
    -
    5871 string.invalidate();
    -
    5872 this->interval.end = token.interval.end;
    -
    5873 this->interval.start = start;
    -
    5874 return true;
    -
    5875 }
    -
    5876 else {
    -
    5877 this->interval.start = (this->interval.end = start) + 1;
    -
    5878 return false;
    -
    5879 }
    -
    5880 }
    -
    5881
    -
    5882 virtual void invalidate()
    -
    5883 {
    -
    5884 string.invalidate();
    -
    5885 token.invalidate();
    -
    5886 parser::invalidate();
    -
    5887 }
    -
    5888
    -
    5889 public:
    - - -
    5892 };
    +
    5846
    +
    +
    5850 class http_value : public parser
    +
    5851 {
    +
    5852 public:
    +
    5853 virtual bool match(
    +
    5854 _In_reads_or_z_(end) const char* text,
    +
    5855 _In_ size_t start = 0,
    +
    5856 _In_ size_t end = (size_t)-1,
    +
    5857 _In_ int flags = match_default)
    +
    5858 {
    +
    5859 _Assume_(text || start >= end);
    +
    5860 this->interval.end = start;
    +
    5861 if (string.match(text, this->interval.end, end, flags)) {
    +
    5862 token.invalidate();
    +
    5863 this->interval.end = string.interval.end;
    +
    5864 this->interval.start = start;
    +
    5865 return true;
    +
    5866 }
    +
    5867 else if (token.match(text, this->interval.end, end, flags)) {
    +
    5868 string.invalidate();
    +
    5869 this->interval.end = token.interval.end;
    +
    5870 this->interval.start = start;
    +
    5871 return true;
    +
    5872 }
    +
    5873 else {
    +
    5874 this->interval.start = (this->interval.end = start) + 1;
    +
    5875 return false;
    +
    5876 }
    +
    5877 }
    +
    5878
    +
    5879 virtual void invalidate()
    +
    5880 {
    +
    5881 string.invalidate();
    +
    5882 token.invalidate();
    +
    5883 parser::invalidate();
    +
    5884 }
    +
    5885
    +
    5886 public:
    + + +
    5889 };
    -
    5893
    -
    -
    5897 class http_parameter : public parser
    -
    5898 {
    -
    5899 public:
    -
    5900 virtual bool match(
    -
    5901 _In_reads_or_z_(end) const char* text,
    -
    5902 _In_ size_t start = 0,
    -
    5903 _In_ size_t end = (size_t)-1,
    -
    5904 _In_ int flags = match_default)
    -
    5905 {
    -
    5906 _Assume_(text || start >= end);
    -
    5907 this->interval.end = start;
    -
    5908 if (name.match(text, this->interval.end, end, flags))
    -
    5909 this->interval.end = name.interval.end;
    -
    5910 else
    -
    5911 goto error;
    -
    5912 while (m_space.match(text, this->interval.end, end, flags))
    -
    5913 this->interval.end = m_space.interval.end;
    -
    5914 _Assume_(text || this->interval.end >= end);
    -
    5915 if (this->interval.end < end && text[this->interval.end] == '=')
    -
    5916 this->interval.end++;
    -
    5917 else
    -
    5918 while (m_space.match(text, this->interval.end, end, flags))
    -
    5919 this->interval.end = m_space.interval.end;
    -
    5920 if (value.match(text, this->interval.end, end, flags))
    -
    5921 this->interval.end = value.interval.end;
    -
    5922 else
    -
    5923 goto error;
    -
    5924 this->interval.start = start;
    -
    5925 return true;
    -
    5926
    -
    5927 error:
    -
    5928 name.invalidate();
    -
    5929 value.invalidate();
    -
    5930 this->interval.start = (this->interval.end = start) + 1;
    -
    5931 return false;
    -
    5932 }
    -
    5933
    -
    5934 virtual void invalidate()
    -
    5935 {
    -
    5936 name.invalidate();
    -
    5937 value.invalidate();
    -
    5938 parser::invalidate();
    -
    5939 }
    -
    5940
    -
    5941 public:
    - - -
    5944
    -
    5945 protected:
    -
    5946 http_space m_space;
    -
    5947 };
    +
    5890
    +
    +
    5894 class http_parameter : public parser
    +
    5895 {
    +
    5896 public:
    +
    5897 virtual bool match(
    +
    5898 _In_reads_or_z_(end) const char* text,
    +
    5899 _In_ size_t start = 0,
    +
    5900 _In_ size_t end = (size_t)-1,
    +
    5901 _In_ int flags = match_default)
    +
    5902 {
    +
    5903 _Assume_(text || start >= end);
    +
    5904 this->interval.end = start;
    +
    5905 if (name.match(text, this->interval.end, end, flags))
    +
    5906 this->interval.end = name.interval.end;
    +
    5907 else
    +
    5908 goto error;
    +
    5909 while (m_space.match(text, this->interval.end, end, flags))
    +
    5910 this->interval.end = m_space.interval.end;
    +
    5911 _Assume_(text || this->interval.end >= end);
    +
    5912 if (this->interval.end < end && text[this->interval.end] == '=')
    +
    5913 this->interval.end++;
    +
    5914 else
    +
    5915 while (m_space.match(text, this->interval.end, end, flags))
    +
    5916 this->interval.end = m_space.interval.end;
    +
    5917 if (value.match(text, this->interval.end, end, flags))
    +
    5918 this->interval.end = value.interval.end;
    +
    5919 else
    +
    5920 goto error;
    +
    5921 this->interval.start = start;
    +
    5922 return true;
    +
    5923
    +
    5924 error:
    +
    5925 name.invalidate();
    +
    5926 value.invalidate();
    +
    5927 this->interval.start = (this->interval.end = start) + 1;
    +
    5928 return false;
    +
    5929 }
    +
    5930
    +
    5931 virtual void invalidate()
    +
    5932 {
    +
    5933 name.invalidate();
    +
    5934 value.invalidate();
    +
    5935 parser::invalidate();
    +
    5936 }
    +
    5937
    +
    5938 public:
    + + +
    5941
    +
    5942 protected:
    +
    5943 http_space m_space;
    +
    5944 };
    -
    5948
    -
    -
    5952 class http_any_type : public parser
    -
    5953 {
    -
    5954 public:
    -
    5955 virtual bool match(
    -
    5956 _In_reads_or_z_(end) const char* text,
    -
    5957 _In_ size_t start = 0,
    -
    5958 _In_ size_t end = (size_t)-1,
    -
    5959 _In_ int flags = match_default)
    -
    5960 {
    -
    5961 _Assume_(text || start >= end);
    -
    5962 if (start + 2 < end &&
    -
    5963 text[start] == '*' &&
    -
    5964 text[start + 1] == '/' &&
    -
    5965 text[start + 2] == '*')
    -
    5966 {
    -
    5967 this->interval.end = (this->interval.start = start) + 3;
    -
    5968 return true;
    -
    5969 }
    -
    5970 else if (start < end && text[start] == '*') {
    -
    5971 this->interval.end = (this->interval.start = start) + 1;
    -
    5972 return true;
    -
    5973 }
    -
    5974 else {
    -
    5975 this->interval.start = (this->interval.end = start) + 1;
    -
    5976 return false;
    -
    5977 }
    -
    5978 }
    -
    5979 };
    +
    5945
    +
    +
    5949 class http_any_type : public parser
    +
    5950 {
    +
    5951 public:
    +
    5952 virtual bool match(
    +
    5953 _In_reads_or_z_(end) const char* text,
    +
    5954 _In_ size_t start = 0,
    +
    5955 _In_ size_t end = (size_t)-1,
    +
    5956 _In_ int flags = match_default)
    +
    5957 {
    +
    5958 _Assume_(text || start >= end);
    +
    5959 if (start + 2 < end &&
    +
    5960 text[start] == '*' &&
    +
    5961 text[start + 1] == '/' &&
    +
    5962 text[start + 2] == '*')
    +
    5963 {
    +
    5964 this->interval.end = (this->interval.start = start) + 3;
    +
    5965 return true;
    +
    5966 }
    +
    5967 else if (start < end && text[start] == '*') {
    +
    5968 this->interval.end = (this->interval.start = start) + 1;
    +
    5969 return true;
    +
    5970 }
    +
    5971 else {
    +
    5972 this->interval.start = (this->interval.end = start) + 1;
    +
    5973 return false;
    +
    5974 }
    +
    5975 }
    +
    5976 };
    -
    5980
    -
    - -
    5985 {
    -
    5986 public:
    -
    5987 virtual bool match(
    -
    5988 _In_reads_or_z_(end) const char* text,
    -
    5989 _In_ size_t start = 0,
    -
    5990 _In_ size_t end = (size_t)-1,
    -
    5991 _In_ int flags = match_default)
    -
    5992 {
    -
    5993 _Assume_(text || start >= end);
    -
    5994 this->interval.end = start;
    -
    5995 if (type.match(text, this->interval.end, end, flags))
    -
    5996 this->interval.end = type.interval.end;
    -
    5997 else
    -
    5998 goto error;
    -
    5999 while (m_space.match(text, this->interval.end, end, flags))
    -
    6000 this->interval.end = m_space.interval.end;
    -
    6001 if (this->interval.end < end && text[this->interval.end] == '/')
    -
    6002 this->interval.end++;
    -
    6003 else
    -
    6004 goto error;
    -
    6005 while (m_space.match(text, this->interval.end, end, flags))
    -
    6006 this->interval.end = m_space.interval.end;
    -
    6007 if (subtype.match(text, this->interval.end, end, flags))
    -
    6008 this->interval.end = subtype.interval.end;
    -
    6009 else
    -
    6010 goto error;
    -
    6011 this->interval.start = start;
    -
    6012 return true;
    -
    6013
    -
    6014 error:
    -
    6015 type.invalidate();
    -
    6016 subtype.invalidate();
    -
    6017 this->interval.start = (this->interval.end = start) + 1;
    -
    6018 return false;
    -
    6019 }
    -
    6020
    -
    6021 virtual void invalidate()
    -
    6022 {
    -
    6023 type.invalidate();
    -
    6024 subtype.invalidate();
    -
    6025 parser::invalidate();
    -
    6026 }
    -
    6027
    -
    6028 public:
    -
    6029 http_token type;
    -
    6030 http_token subtype;
    -
    6031
    -
    6032 protected:
    -
    6033 http_space m_space;
    -
    6034 };
    +
    5977
    +
    + +
    5982 {
    +
    5983 public:
    +
    5984 virtual bool match(
    +
    5985 _In_reads_or_z_(end) const char* text,
    +
    5986 _In_ size_t start = 0,
    +
    5987 _In_ size_t end = (size_t)-1,
    +
    5988 _In_ int flags = match_default)
    +
    5989 {
    +
    5990 _Assume_(text || start >= end);
    +
    5991 this->interval.end = start;
    +
    5992 if (type.match(text, this->interval.end, end, flags))
    +
    5993 this->interval.end = type.interval.end;
    +
    5994 else
    +
    5995 goto error;
    +
    5996 while (m_space.match(text, this->interval.end, end, flags))
    +
    5997 this->interval.end = m_space.interval.end;
    +
    5998 if (this->interval.end < end && text[this->interval.end] == '/')
    +
    5999 this->interval.end++;
    +
    6000 else
    +
    6001 goto error;
    +
    6002 while (m_space.match(text, this->interval.end, end, flags))
    +
    6003 this->interval.end = m_space.interval.end;
    +
    6004 if (subtype.match(text, this->interval.end, end, flags))
    +
    6005 this->interval.end = subtype.interval.end;
    +
    6006 else
    +
    6007 goto error;
    +
    6008 this->interval.start = start;
    +
    6009 return true;
    +
    6010
    +
    6011 error:
    +
    6012 type.invalidate();
    +
    6013 subtype.invalidate();
    +
    6014 this->interval.start = (this->interval.end = start) + 1;
    +
    6015 return false;
    +
    6016 }
    +
    6017
    +
    6018 virtual void invalidate()
    +
    6019 {
    +
    6020 type.invalidate();
    +
    6021 subtype.invalidate();
    +
    6022 parser::invalidate();
    +
    6023 }
    +
    6024
    +
    6025 public:
    +
    6026 http_token type;
    +
    6027 http_token subtype;
    +
    6028
    +
    6029 protected:
    +
    6030 http_space m_space;
    +
    6031 };
    -
    6035
    -
    - -
    6040 {
    -
    6041 public:
    -
    6042 virtual bool match(
    -
    6043 _In_reads_or_z_(end) const char* text,
    -
    6044 _In_ size_t start = 0,
    -
    6045 _In_ size_t end = (size_t)-1,
    -
    6046 _In_ int flags = match_default)
    -
    6047 {
    -
    6048 _Assume_(text || start >= end);
    -
    6049 if (!http_media_range::match(text, start, end, flags))
    -
    6050 goto error;
    -
    6051 params.clear();
    -
    6052 for (;;) {
    -
    6053 if (this->interval.end < end && text[this->interval.end]) {
    -
    6054 if (m_space.match(text, this->interval.end, end, flags))
    -
    6055 this->interval.end = m_space.interval.end;
    -
    6056 else if (text[this->interval.end] == ';') {
    -
    6057 this->interval.end++;
    -
    6058 while (m_space.match(text, this->interval.end, end, flags))
    -
    6059 this->interval.end = m_space.interval.end;
    - -
    6061 if (param.match(text, this->interval.end, end, flags)) {
    -
    6062 this->interval.end = param.interval.end;
    -
    6063 params.push_back(std::move(param));
    -
    6064 }
    -
    6065 else
    -
    6066 break;
    -
    6067 }
    -
    6068 else
    -
    6069 break;
    -
    6070 }
    -
    6071 else
    -
    6072 break;
    -
    6073 }
    -
    6074 this->interval.end = params.empty() ? subtype.interval.end : params.back().interval.end;
    -
    6075 return true;
    -
    6076
    -
    6077 error:
    -
    6078 http_media_range::invalidate();
    -
    6079 params.clear();
    -
    6080 this->interval.start = (this->interval.end = start) + 1;
    -
    6081 return false;
    -
    6082 }
    -
    6083
    -
    6084 virtual void invalidate()
    -
    6085 {
    -
    6086 params.clear();
    -
    6087 http_media_range::invalidate();
    -
    6088 }
    -
    6089
    -
    6090 public:
    -
    6091 std::list<http_parameter> params;
    -
    6092 };
    +
    6032
    +
    + +
    6037 {
    +
    6038 public:
    +
    6039 virtual bool match(
    +
    6040 _In_reads_or_z_(end) const char* text,
    +
    6041 _In_ size_t start = 0,
    +
    6042 _In_ size_t end = (size_t)-1,
    +
    6043 _In_ int flags = match_default)
    +
    6044 {
    +
    6045 _Assume_(text || start >= end);
    +
    6046 if (!http_media_range::match(text, start, end, flags))
    +
    6047 goto error;
    +
    6048 params.clear();
    +
    6049 for (;;) {
    +
    6050 if (this->interval.end < end && text[this->interval.end]) {
    +
    6051 if (m_space.match(text, this->interval.end, end, flags))
    +
    6052 this->interval.end = m_space.interval.end;
    +
    6053 else if (text[this->interval.end] == ';') {
    +
    6054 this->interval.end++;
    +
    6055 while (m_space.match(text, this->interval.end, end, flags))
    +
    6056 this->interval.end = m_space.interval.end;
    + +
    6058 if (param.match(text, this->interval.end, end, flags)) {
    +
    6059 this->interval.end = param.interval.end;
    +
    6060 params.push_back(std::move(param));
    +
    6061 }
    +
    6062 else
    +
    6063 break;
    +
    6064 }
    +
    6065 else
    +
    6066 break;
    +
    6067 }
    +
    6068 else
    +
    6069 break;
    +
    6070 }
    +
    6071 this->interval.end = params.empty() ? subtype.interval.end : params.back().interval.end;
    +
    6072 return true;
    +
    6073
    +
    6074 error:
    +
    6075 http_media_range::invalidate();
    +
    6076 params.clear();
    +
    6077 this->interval.start = (this->interval.end = start) + 1;
    +
    6078 return false;
    +
    6079 }
    +
    6080
    +
    6081 virtual void invalidate()
    +
    6082 {
    +
    6083 params.clear();
    +
    6084 http_media_range::invalidate();
    +
    6085 }
    +
    6086
    +
    6087 public:
    +
    6088 std::list<http_parameter> params;
    +
    6089 };
    -
    6093
    -
    - -
    6098 {
    -
    6099 public:
    -
    6100 virtual bool match(
    -
    6101 _In_reads_or_z_(end) const char* text,
    -
    6102 _In_ size_t start = 0,
    -
    6103 _In_ size_t end = (size_t)-1,
    -
    6104 _In_ int flags = match_default)
    -
    6105 {
    -
    6106 _Assume_(text || start >= end);
    -
    6107 this->interval.end = start;
    -
    6108 for (;;) {
    -
    6109 if (this->interval.end < end && text[this->interval.end]) {
    -
    6110 if ((unsigned int)text[this->interval.end] < 0x20 ||
    -
    6111 (unsigned int)text[this->interval.end] == 0x7f ||
    -
    6112 text[this->interval.end] == ':' ||
    -
    6113 text[this->interval.end] == '/' ||
    -
    6114 isspace(text[this->interval.end]))
    -
    6115 break;
    -
    6116 else
    -
    6117 this->interval.end++;
    -
    6118 }
    -
    6119 else
    -
    6120 break;
    -
    6121 }
    - -
    6123 this->interval.start = start;
    -
    6124 return true;
    -
    6125 }
    -
    6126 this->interval.start = (this->interval.end = start) + 1;
    -
    6127 return false;
    -
    6128 }
    -
    6129 };
    +
    6090
    +
    + +
    6095 {
    +
    6096 public:
    +
    6097 virtual bool match(
    +
    6098 _In_reads_or_z_(end) const char* text,
    +
    6099 _In_ size_t start = 0,
    +
    6100 _In_ size_t end = (size_t)-1,
    +
    6101 _In_ int flags = match_default)
    +
    6102 {
    +
    6103 _Assume_(text || start >= end);
    +
    6104 this->interval.end = start;
    +
    6105 for (;;) {
    +
    6106 if (this->interval.end < end && text[this->interval.end]) {
    +
    6107 if ((unsigned int)text[this->interval.end] < 0x20 ||
    +
    6108 (unsigned int)text[this->interval.end] == 0x7f ||
    +
    6109 text[this->interval.end] == ':' ||
    +
    6110 text[this->interval.end] == '/' ||
    +
    6111 isspace(text[this->interval.end]))
    +
    6112 break;
    +
    6113 else
    +
    6114 this->interval.end++;
    +
    6115 }
    +
    6116 else
    +
    6117 break;
    +
    6118 }
    + +
    6120 this->interval.start = start;
    +
    6121 return true;
    +
    6122 }
    +
    6123 this->interval.start = (this->interval.end = start) + 1;
    +
    6124 return false;
    +
    6125 }
    +
    6126 };
    -
    6130
    -
    -
    6134 class http_url_port : public parser
    -
    6135 {
    -
    6136 public:
    -
    6137 http_url_port(_In_ const std::locale& locale = std::locale()) :
    -
    6138 parser(locale),
    -
    6139 value(0)
    -
    6140 {}
    -
    6141
    -
    6142 virtual bool match(
    -
    6143 _In_reads_or_z_(end) const char* text,
    -
    6144 _In_ size_t start = 0,
    -
    6145 _In_ size_t end = (size_t)-1,
    -
    6146 _In_ int flags = match_default)
    -
    6147 {
    -
    6148 _Assume_(text || start >= end);
    -
    6149 value = 0;
    -
    6150 this->interval.end = start;
    -
    6151 for (;;) {
    -
    6152 if (this->interval.end < end && text[this->interval.end]) {
    -
    6153 if ('0' <= text[this->interval.end] && text[this->interval.end] <= '9') {
    -
    6154 size_t _value = (size_t)value * 10 + text[this->interval.end] - '0';
    -
    6155 if (_value > (uint16_t)-1) {
    -
    6156 value = 0;
    -
    6157 this->interval.start = (this->interval.end = start) + 1;
    -
    6158 return false;
    -
    6159 }
    -
    6160 value = (uint16_t)_value;
    -
    6161 this->interval.end++;
    -
    6162 }
    -
    6163 else
    -
    6164 break;
    -
    6165 }
    -
    6166 else
    -
    6167 break;
    -
    6168 }
    - -
    6170 this->interval.start = start;
    -
    6171 return true;
    -
    6172 }
    -
    6173 this->interval.start = (this->interval.end = start) + 1;
    -
    6174 return false;
    -
    6175 }
    -
    6176
    -
    6177 virtual void invalidate()
    -
    6178 {
    -
    6179 value = 0;
    -
    6180 parser::invalidate();
    -
    6181 }
    -
    6182
    -
    6183 public:
    -
    6184 uint16_t value;
    -
    6185 };
    +
    6127
    +
    +
    6131 class http_url_port : public parser
    +
    6132 {
    +
    6133 public:
    +
    6134 http_url_port(_In_ const std::locale& locale = std::locale()) :
    +
    6135 parser(locale),
    +
    6136 value(0)
    +
    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 _Assume_(text || start >= end);
    +
    6146 value = 0;
    +
    6147 this->interval.end = start;
    +
    6148 for (;;) {
    +
    6149 if (this->interval.end < end && text[this->interval.end]) {
    +
    6150 if ('0' <= text[this->interval.end] && text[this->interval.end] <= '9') {
    +
    6151 size_t _value = (size_t)value * 10 + text[this->interval.end] - '0';
    +
    6152 if (_value > (uint16_t)-1) {
    +
    6153 value = 0;
    +
    6154 this->interval.start = (this->interval.end = start) + 1;
    +
    6155 return false;
    +
    6156 }
    +
    6157 value = (uint16_t)_value;
    +
    6158 this->interval.end++;
    +
    6159 }
    +
    6160 else
    +
    6161 break;
    +
    6162 }
    +
    6163 else
    +
    6164 break;
    +
    6165 }
    + +
    6167 this->interval.start = start;
    +
    6168 return true;
    +
    6169 }
    +
    6170 this->interval.start = (this->interval.end = start) + 1;
    +
    6171 return false;
    +
    6172 }
    +
    6173
    +
    6174 virtual void invalidate()
    +
    6175 {
    +
    6176 value = 0;
    +
    6177 parser::invalidate();
    +
    6178 }
    +
    6179
    +
    6180 public:
    +
    6181 uint16_t value;
    +
    6182 };
    -
    6186
    -
    - -
    6191 {
    -
    6192 public:
    -
    6193 virtual bool match(
    -
    6194 _In_reads_or_z_(end) const char* text,
    -
    6195 _In_ size_t start = 0,
    -
    6196 _In_ size_t end = (size_t)-1,
    -
    6197 _In_ int flags = match_default)
    -
    6198 {
    -
    6199 _Assume_(text || start >= end);
    -
    6200 this->interval.end = start;
    -
    6201 for (;;) {
    -
    6202 if (this->interval.end < end && text[this->interval.end]) {
    -
    6203 if ((unsigned int)text[this->interval.end] < 0x20 ||
    -
    6204 (unsigned int)text[this->interval.end] == 0x7f ||
    -
    6205 text[this->interval.end] == '?' ||
    -
    6206 text[this->interval.end] == '/' ||
    -
    6207 isspace(text[this->interval.end]))
    -
    6208 break;
    -
    6209 else
    -
    6210 this->interval.end++;
    -
    6211 }
    -
    6212 else
    -
    6213 break;
    -
    6214 }
    -
    6215 this->interval.start = start;
    -
    6216 return true;
    -
    6217 }
    -
    6218 };
    +
    6183
    +
    + +
    6188 {
    +
    6189 public:
    +
    6190 virtual bool match(
    +
    6191 _In_reads_or_z_(end) const char* text,
    +
    6192 _In_ size_t start = 0,
    +
    6193 _In_ size_t end = (size_t)-1,
    +
    6194 _In_ int flags = match_default)
    +
    6195 {
    +
    6196 _Assume_(text || start >= end);
    +
    6197 this->interval.end = start;
    +
    6198 for (;;) {
    +
    6199 if (this->interval.end < end && text[this->interval.end]) {
    +
    6200 if ((unsigned int)text[this->interval.end] < 0x20 ||
    +
    6201 (unsigned int)text[this->interval.end] == 0x7f ||
    +
    6202 text[this->interval.end] == '?' ||
    +
    6203 text[this->interval.end] == '/' ||
    +
    6204 isspace(text[this->interval.end]))
    +
    6205 break;
    +
    6206 else
    +
    6207 this->interval.end++;
    +
    6208 }
    +
    6209 else
    +
    6210 break;
    +
    6211 }
    +
    6212 this->interval.start = start;
    +
    6213 return true;
    +
    6214 }
    +
    6215 };
    -
    6219
    -
    -
    6223 class http_url_path : public parser
    -
    6224 {
    -
    6225 public:
    -
    6226 virtual bool match(
    -
    6227 _In_reads_or_z_(end) const char* text,
    -
    6228 _In_ size_t start = 0,
    -
    6229 _In_ size_t end = (size_t)-1,
    -
    6230 _In_ int flags = match_default)
    -
    6231 {
    -
    6232 _Assume_(text || start >= end);
    - -
    6234 this->interval.end = start;
    -
    6235 segments.clear();
    -
    6236 _Assume_(text || this->interval.end >= end);
    -
    6237 if (this->interval.end < end && text[this->interval.end] != '/')
    -
    6238 goto error;
    -
    6239 this->interval.end++;
    -
    6240 s.match(text, this->interval.end, end, flags);
    -
    6241 segments.push_back(s);
    -
    6242 this->interval.end = s.interval.end;
    -
    6243 for (;;) {
    -
    6244 if (this->interval.end < end && text[this->interval.end]) {
    -
    6245 if (text[this->interval.end] == '/') {
    -
    6246 this->interval.end++;
    -
    6247 s.match(text, this->interval.end, end, flags);
    -
    6248 segments.push_back(s);
    -
    6249 this->interval.end = s.interval.end;
    -
    6250 }
    -
    6251 else
    -
    6252 break;
    -
    6253 }
    -
    6254 else
    -
    6255 break;
    -
    6256 }
    -
    6257 this->interval.start = start;
    -
    6258 return true;
    -
    6259
    -
    6260 error:
    -
    6261 segments.clear();
    -
    6262 this->interval.start = (this->interval.end = start) + 1;
    -
    6263 return false;
    -
    6264 }
    -
    6265
    -
    6266 virtual void invalidate()
    -
    6267 {
    -
    6268 segments.clear();
    -
    6269 parser::invalidate();
    -
    6270 }
    -
    6271
    -
    6272 public:
    -
    6273 std::vector<http_url_path_segment> segments;
    -
    6274 };
    +
    6216
    +
    +
    6220 class http_url_path : public parser
    +
    6221 {
    +
    6222 public:
    +
    6223 virtual bool match(
    +
    6224 _In_reads_or_z_(end) const char* text,
    +
    6225 _In_ size_t start = 0,
    +
    6226 _In_ size_t end = (size_t)-1,
    +
    6227 _In_ int flags = match_default)
    +
    6228 {
    +
    6229 _Assume_(text || start >= end);
    + +
    6231 this->interval.end = start;
    +
    6232 segments.clear();
    +
    6233 _Assume_(text || this->interval.end >= end);
    +
    6234 if (this->interval.end < end && text[this->interval.end] != '/')
    +
    6235 goto error;
    +
    6236 this->interval.end++;
    +
    6237 s.match(text, this->interval.end, end, flags);
    +
    6238 segments.push_back(s);
    +
    6239 this->interval.end = s.interval.end;
    +
    6240 for (;;) {
    +
    6241 if (this->interval.end < end && text[this->interval.end]) {
    +
    6242 if (text[this->interval.end] == '/') {
    +
    6243 this->interval.end++;
    +
    6244 s.match(text, this->interval.end, end, flags);
    +
    6245 segments.push_back(s);
    +
    6246 this->interval.end = s.interval.end;
    +
    6247 }
    +
    6248 else
    +
    6249 break;
    +
    6250 }
    +
    6251 else
    +
    6252 break;
    +
    6253 }
    +
    6254 this->interval.start = start;
    +
    6255 return true;
    +
    6256
    +
    6257 error:
    +
    6258 segments.clear();
    +
    6259 this->interval.start = (this->interval.end = start) + 1;
    +
    6260 return false;
    +
    6261 }
    +
    6262
    +
    6263 virtual void invalidate()
    +
    6264 {
    +
    6265 segments.clear();
    +
    6266 parser::invalidate();
    +
    6267 }
    +
    6268
    +
    6269 public:
    +
    6270 std::vector<http_url_path_segment> segments;
    +
    6271 };
    -
    6275
    -
    - -
    6280 {
    -
    6281 public:
    -
    6282 virtual bool match(
    -
    6283 _In_reads_or_z_(end) const char* text,
    -
    6284 _In_ size_t start = 0,
    -
    6285 _In_ size_t end = (size_t)-1,
    -
    6286 _In_ int flags = match_default)
    -
    6287 {
    -
    6288 _Assume_(text || start >= end);
    -
    6289 this->interval.end = start;
    -
    6290 name.start = this->interval.end;
    -
    6291 for (;;) {
    -
    6292 if (this->interval.end < end && text[this->interval.end]) {
    -
    6293 if ((unsigned int)text[this->interval.end] < 0x20 ||
    -
    6294 (unsigned int)text[this->interval.end] == 0x7f ||
    -
    6295 text[this->interval.end] == '&' ||
    -
    6296 text[this->interval.end] == '=' ||
    -
    6297 isspace(text[this->interval.end]))
    -
    6298 break;
    -
    6299 else
    -
    6300 this->interval.end++;
    -
    6301 }
    -
    6302 else
    -
    6303 break;
    -
    6304 }
    - -
    6306 name.end = this->interval.end;
    -
    6307 else
    -
    6308 goto error;
    -
    6309 if (text[this->interval.end] == '=') {
    -
    6310 this->interval.end++;
    -
    6311 value.start = this->interval.end;
    -
    6312 for (;;) {
    -
    6313 if (this->interval.end < end && text[this->interval.end]) {
    -
    6314 if ((unsigned int)text[this->interval.end] < 0x20 ||
    -
    6315 (unsigned int)text[this->interval.end] == 0x7f ||
    -
    6316 text[this->interval.end] == '&' ||
    -
    6317 isspace(text[this->interval.end]))
    -
    6318 break;
    -
    6319 else
    -
    6320 this->interval.end++;
    -
    6321 }
    -
    6322 else
    -
    6323 break;
    -
    6324 }
    -
    6325 value.end = this->interval.end;
    -
    6326 }
    -
    6327 else {
    -
    6328 value.start = 1;
    -
    6329 value.end = 0;
    -
    6330 }
    -
    6331 this->interval.start = start;
    -
    6332 return true;
    -
    6333
    -
    6334 error:
    -
    6335 name.start = 1;
    -
    6336 name.end = 0;
    -
    6337 value.start = 1;
    -
    6338 value.end = 0;
    -
    6339 this->interval.start = (this->interval.end = start) + 1;
    -
    6340 return false;
    -
    6341 }
    -
    6342
    -
    6343 virtual void invalidate()
    -
    6344 {
    -
    6345 name.start = 1;
    -
    6346 name.end = 0;
    -
    6347 value.start = 1;
    -
    6348 value.end = 0;
    -
    6349 parser::invalidate();
    -
    6350 }
    -
    6351
    -
    6352 public:
    - - -
    6355 };
    +
    6272
    +
    + +
    6277 {
    +
    6278 public:
    +
    6279 virtual bool match(
    +
    6280 _In_reads_or_z_(end) const char* text,
    +
    6281 _In_ size_t start = 0,
    +
    6282 _In_ size_t end = (size_t)-1,
    +
    6283 _In_ int flags = match_default)
    +
    6284 {
    +
    6285 _Assume_(text || start >= end);
    +
    6286 this->interval.end = start;
    +
    6287 name.start = this->interval.end;
    +
    6288 for (;;) {
    +
    6289 if (this->interval.end < end && text[this->interval.end]) {
    +
    6290 if ((unsigned int)text[this->interval.end] < 0x20 ||
    +
    6291 (unsigned int)text[this->interval.end] == 0x7f ||
    +
    6292 text[this->interval.end] == '&' ||
    +
    6293 text[this->interval.end] == '=' ||
    +
    6294 isspace(text[this->interval.end]))
    +
    6295 break;
    +
    6296 else
    +
    6297 this->interval.end++;
    +
    6298 }
    +
    6299 else
    +
    6300 break;
    +
    6301 }
    + +
    6303 name.end = this->interval.end;
    +
    6304 else
    +
    6305 goto error;
    +
    6306 if (text[this->interval.end] == '=') {
    +
    6307 this->interval.end++;
    +
    6308 value.start = this->interval.end;
    +
    6309 for (;;) {
    +
    6310 if (this->interval.end < end && text[this->interval.end]) {
    +
    6311 if ((unsigned int)text[this->interval.end] < 0x20 ||
    +
    6312 (unsigned int)text[this->interval.end] == 0x7f ||
    +
    6313 text[this->interval.end] == '&' ||
    +
    6314 isspace(text[this->interval.end]))
    +
    6315 break;
    +
    6316 else
    +
    6317 this->interval.end++;
    +
    6318 }
    +
    6319 else
    +
    6320 break;
    +
    6321 }
    +
    6322 value.end = this->interval.end;
    +
    6323 }
    +
    6324 else {
    +
    6325 value.start = 1;
    +
    6326 value.end = 0;
    +
    6327 }
    +
    6328 this->interval.start = start;
    +
    6329 return true;
    +
    6330
    +
    6331 error:
    +
    6332 name.start = 1;
    +
    6333 name.end = 0;
    +
    6334 value.start = 1;
    +
    6335 value.end = 0;
    +
    6336 this->interval.start = (this->interval.end = start) + 1;
    +
    6337 return false;
    +
    6338 }
    +
    6339
    +
    6340 virtual void invalidate()
    +
    6341 {
    +
    6342 name.start = 1;
    +
    6343 name.end = 0;
    +
    6344 value.start = 1;
    +
    6345 value.end = 0;
    +
    6346 parser::invalidate();
    +
    6347 }
    +
    6348
    +
    6349 public:
    + + +
    6352 };
    -
    6356
    -
    -
    6360 class http_url : public parser
    -
    6361 {
    -
    6362 public:
    -
    6363 http_url(_In_ const std::locale& locale = std::locale()) :
    -
    6364 parser(locale),
    -
    6365 port(locale)
    -
    6366 {}
    -
    6367
    -
    6368 virtual bool match(
    -
    6369 _In_reads_or_z_(end) const char* text,
    -
    6370 _In_ size_t start = 0,
    -
    6371 _In_ size_t end = (size_t)-1,
    -
    6372 _In_ int flags = match_default)
    -
    6373 {
    -
    6374 _Assume_(text || start >= end);
    -
    6375 this->interval.end = start;
    -
    6376
    -
    6377 if (this->interval.end + 7 <= end && stdex::strnicmp(text + this->interval.end, 7, "http://", (size_t)-1, m_locale) == 0) {
    -
    6378 this->interval.end += 7;
    -
    6379 if (server.match(text, this->interval.end, end, flags))
    -
    6380 this->interval.end = server.interval.end;
    -
    6381 else
    -
    6382 goto error;
    -
    6383 if (this->interval.end < end && text[this->interval.end] == ':') {
    -
    6384 this->interval.end++;
    -
    6385 if (port.match(text, this->interval.end, end, flags))
    -
    6386 this->interval.end = port.interval.end;
    -
    6387 }
    -
    6388 else {
    -
    6389 port.invalidate();
    -
    6390 port.value = 80;
    -
    6391 }
    -
    6392 }
    -
    6393 else {
    -
    6394 server.invalidate();
    -
    6395 port.invalidate();
    -
    6396 port.value = 80;
    -
    6397 }
    -
    6398
    -
    6399 if (path.match(text, this->interval.end, end, flags))
    -
    6400 this->interval.end = path.interval.end;
    -
    6401 else
    -
    6402 goto error;
    -
    6403
    -
    6404 params.clear();
    -
    6405
    -
    6406 if (this->interval.end < end && text[this->interval.end] == '?') {
    -
    6407 this->interval.end++;
    -
    6408 for (;;) {
    -
    6409 if (this->interval.end < end && text[this->interval.end]) {
    -
    6410 if ((unsigned int)text[this->interval.end] < 0x20 ||
    -
    6411 (unsigned int)text[this->interval.end] == 0x7f ||
    -
    6412 isspace(text[this->interval.end]))
    -
    6413 break;
    -
    6414 else if (text[this->interval.end] == '&')
    -
    6415 this->interval.end++;
    -
    6416 else {
    - -
    6418 if (param.match(text, this->interval.end, end, flags)) {
    -
    6419 this->interval.end = param.interval.end;
    -
    6420 params.push_back(std::move(param));
    -
    6421 }
    -
    6422 else
    -
    6423 break;
    -
    6424 }
    -
    6425 }
    -
    6426 else
    -
    6427 break;
    -
    6428 }
    -
    6429 }
    +
    6353
    +
    +
    6357 class http_url : public parser
    +
    6358 {
    +
    6359 public:
    +
    6360 http_url(_In_ const std::locale& locale = std::locale()) :
    +
    6361 parser(locale),
    +
    6362 port(locale)
    +
    6363 {}
    +
    6364
    +
    6365 virtual bool match(
    +
    6366 _In_reads_or_z_(end) const char* text,
    +
    6367 _In_ size_t start = 0,
    +
    6368 _In_ size_t end = (size_t)-1,
    +
    6369 _In_ int flags = match_default)
    +
    6370 {
    +
    6371 _Assume_(text || start >= end);
    +
    6372 this->interval.end = start;
    +
    6373
    +
    6374 if (this->interval.end + 7 <= end && stdex::strnicmp(text + this->interval.end, 7, "http://", (size_t)-1, m_locale) == 0) {
    +
    6375 this->interval.end += 7;
    +
    6376 if (server.match(text, this->interval.end, end, flags))
    +
    6377 this->interval.end = server.interval.end;
    +
    6378 else
    +
    6379 goto error;
    +
    6380 if (this->interval.end < end && text[this->interval.end] == ':') {
    +
    6381 this->interval.end++;
    +
    6382 if (port.match(text, this->interval.end, end, flags))
    +
    6383 this->interval.end = port.interval.end;
    +
    6384 }
    +
    6385 else {
    +
    6386 port.invalidate();
    +
    6387 port.value = 80;
    +
    6388 }
    +
    6389 }
    +
    6390 else {
    +
    6391 server.invalidate();
    +
    6392 port.invalidate();
    +
    6393 port.value = 80;
    +
    6394 }
    +
    6395
    +
    6396 if (path.match(text, this->interval.end, end, flags))
    +
    6397 this->interval.end = path.interval.end;
    +
    6398 else
    +
    6399 goto error;
    +
    6400
    +
    6401 params.clear();
    +
    6402
    +
    6403 if (this->interval.end < end && text[this->interval.end] == '?') {
    +
    6404 this->interval.end++;
    +
    6405 for (;;) {
    +
    6406 if (this->interval.end < end && text[this->interval.end]) {
    +
    6407 if ((unsigned int)text[this->interval.end] < 0x20 ||
    +
    6408 (unsigned int)text[this->interval.end] == 0x7f ||
    +
    6409 isspace(text[this->interval.end]))
    +
    6410 break;
    +
    6411 else if (text[this->interval.end] == '&')
    +
    6412 this->interval.end++;
    +
    6413 else {
    + +
    6415 if (param.match(text, this->interval.end, end, flags)) {
    +
    6416 this->interval.end = param.interval.end;
    +
    6417 params.push_back(std::move(param));
    +
    6418 }
    +
    6419 else
    +
    6420 break;
    +
    6421 }
    +
    6422 }
    +
    6423 else
    +
    6424 break;
    +
    6425 }
    +
    6426 }
    +
    6427
    +
    6428 this->interval.start = start;
    +
    6429 return true;
    6430
    -
    6431 this->interval.start = start;
    -
    6432 return true;
    -
    6433
    -
    6434 error:
    -
    6435 server.invalidate();
    -
    6436 port.invalidate();
    -
    6437 path.invalidate();
    -
    6438 params.clear();
    -
    6439 this->interval.start = (this->interval.end = start) + 1;
    -
    6440 return false;
    -
    6441 }
    -
    6442
    -
    6443 virtual void invalidate()
    -
    6444 {
    -
    6445 server.invalidate();
    -
    6446 port.invalidate();
    -
    6447 path.invalidate();
    -
    6448 params.clear();
    -
    6449 parser::invalidate();
    -
    6450 }
    -
    6451
    -
    6452 public:
    -
    6453 http_url_server server;
    -
    6454 http_url_port port;
    -
    6455 http_url_path path;
    -
    6456 std::list<http_url_parameter> params;
    -
    6457 };
    +
    6431 error:
    +
    6432 server.invalidate();
    +
    6433 port.invalidate();
    +
    6434 path.invalidate();
    +
    6435 params.clear();
    +
    6436 this->interval.start = (this->interval.end = start) + 1;
    +
    6437 return false;
    +
    6438 }
    +
    6439
    +
    6440 virtual void invalidate()
    +
    6441 {
    +
    6442 server.invalidate();
    +
    6443 port.invalidate();
    +
    6444 path.invalidate();
    +
    6445 params.clear();
    +
    6446 parser::invalidate();
    +
    6447 }
    +
    6448
    +
    6449 public:
    +
    6450 http_url_server server;
    +
    6451 http_url_port port;
    +
    6452 http_url_path path;
    +
    6453 std::list<http_url_parameter> params;
    +
    6454 };
    -
    6458
    -
    -
    6462 class http_language : public parser
    -
    6463 {
    -
    6464 public:
    -
    6465 virtual bool match(
    -
    6466 _In_reads_or_z_(end) const char* text,
    -
    6467 _In_ size_t start = 0,
    -
    6468 _In_ size_t end = (size_t)-1,
    -
    6469 _In_ int flags = match_default)
    -
    6470 {
    -
    6471 _Assume_(text || start >= end);
    -
    6472 this->interval.end = start;
    -
    6473 components.clear();
    -
    6474 for (;;) {
    -
    6475 if (this->interval.end < end && text[this->interval.end]) {
    - -
    6477 k.end = this->interval.end;
    -
    6478 for (;;) {
    -
    6479 if (k.end < end && text[k.end]) {
    -
    6480 if (isalpha(text[k.end]))
    -
    6481 k.end++;
    -
    6482 else
    -
    6483 break;
    -
    6484 }
    -
    6485 else
    -
    6486 break;
    -
    6487 }
    -
    6488 if (this->interval.end < k.end) {
    -
    6489 k.start = this->interval.end;
    -
    6490 this->interval.end = k.end;
    -
    6491 components.push_back(k);
    -
    6492 }
    -
    6493 else
    -
    6494 break;
    -
    6495 if (this->interval.end < end && text[this->interval.end] == '-')
    -
    6496 this->interval.end++;
    -
    6497 else
    -
    6498 break;
    -
    6499 }
    -
    6500 else
    -
    6501 break;
    -
    6502 }
    -
    6503 if (!components.empty()) {
    -
    6504 this->interval.start = start;
    -
    6505 this->interval.end = components.back().end;
    -
    6506 return true;
    -
    6507 }
    -
    6508 this->interval.start = (this->interval.end = start) + 1;
    -
    6509 return false;
    -
    6510 }
    -
    6511
    -
    6512 virtual void invalidate()
    -
    6513 {
    -
    6514 components.clear();
    -
    6515 parser::invalidate();
    -
    6516 }
    -
    6517
    -
    6518 public:
    -
    6519 std::vector<stdex::interval<size_t>> components;
    -
    6520 };
    +
    6455
    +
    +
    6459 class http_language : public parser
    +
    6460 {
    +
    6461 public:
    +
    6462 virtual bool match(
    +
    6463 _In_reads_or_z_(end) const char* text,
    +
    6464 _In_ size_t start = 0,
    +
    6465 _In_ size_t end = (size_t)-1,
    +
    6466 _In_ int flags = match_default)
    +
    6467 {
    +
    6468 _Assume_(text || start >= end);
    +
    6469 this->interval.end = start;
    +
    6470 components.clear();
    +
    6471 for (;;) {
    +
    6472 if (this->interval.end < end && text[this->interval.end]) {
    + +
    6474 k.end = this->interval.end;
    +
    6475 for (;;) {
    +
    6476 if (k.end < end && text[k.end]) {
    +
    6477 if (isalpha(text[k.end]))
    +
    6478 k.end++;
    +
    6479 else
    +
    6480 break;
    +
    6481 }
    +
    6482 else
    +
    6483 break;
    +
    6484 }
    +
    6485 if (this->interval.end < k.end) {
    +
    6486 k.start = this->interval.end;
    +
    6487 this->interval.end = k.end;
    +
    6488 components.push_back(k);
    +
    6489 }
    +
    6490 else
    +
    6491 break;
    +
    6492 if (this->interval.end < end && text[this->interval.end] == '-')
    +
    6493 this->interval.end++;
    +
    6494 else
    +
    6495 break;
    +
    6496 }
    +
    6497 else
    +
    6498 break;
    +
    6499 }
    +
    6500 if (!components.empty()) {
    +
    6501 this->interval.start = start;
    +
    6502 this->interval.end = components.back().end;
    +
    6503 return true;
    +
    6504 }
    +
    6505 this->interval.start = (this->interval.end = start) + 1;
    +
    6506 return false;
    +
    6507 }
    +
    6508
    +
    6509 virtual void invalidate()
    +
    6510 {
    +
    6511 components.clear();
    +
    6512 parser::invalidate();
    +
    6513 }
    +
    6514
    +
    6515 public:
    +
    6516 std::vector<stdex::interval<size_t>> components;
    +
    6517 };
    -
    6521
    -
    -
    6525 class http_weight : public parser
    -
    6526 {
    -
    6527 public:
    -
    6528 http_weight(_In_ const std::locale& locale = std::locale()) :
    -
    6529 parser(locale),
    -
    6530 value(1.0f)
    -
    6531 {}
    -
    6532
    -
    6533 virtual bool match(
    -
    6534 _In_reads_or_z_(end) const char* text,
    -
    6535 _In_ size_t start = 0,
    -
    6536 _In_ size_t end = (size_t)-1,
    -
    6537 _In_ int flags = match_default)
    -
    6538 {
    -
    6539 _Assume_(text || start >= end);
    -
    6540 size_t celi_del = 0, decimalni_del = 0, decimalni_del_n = 1;
    -
    6541 this->interval.end = start;
    -
    6542 for (;;) {
    -
    6543 if (this->interval.end < end && text[this->interval.end]) {
    -
    6544 if ('0' <= text[this->interval.end] && text[this->interval.end] <= '9') {
    -
    6545 celi_del = celi_del * 10 + text[this->interval.end] - '0';
    +
    6518
    +
    +
    6522 class http_weight : public parser
    +
    6523 {
    +
    6524 public:
    +
    6525 http_weight(_In_ const std::locale& locale = std::locale()) :
    +
    6526 parser(locale),
    +
    6527 value(1.0f)
    +
    6528 {}
    +
    6529
    +
    6530 virtual bool match(
    +
    6531 _In_reads_or_z_(end) const char* text,
    +
    6532 _In_ size_t start = 0,
    +
    6533 _In_ size_t end = (size_t)-1,
    +
    6534 _In_ int flags = match_default)
    +
    6535 {
    +
    6536 _Assume_(text || start >= end);
    +
    6537 size_t celi_del = 0, decimalni_del = 0, decimalni_del_n = 1;
    +
    6538 this->interval.end = start;
    +
    6539 for (;;) {
    +
    6540 if (this->interval.end < end && text[this->interval.end]) {
    +
    6541 if ('0' <= text[this->interval.end] && text[this->interval.end] <= '9') {
    +
    6542 celi_del = celi_del * 10 + text[this->interval.end] - '0';
    +
    6543 this->interval.end++;
    +
    6544 }
    +
    6545 else if (text[this->interval.end] == '.') {
    6546 this->interval.end++;
    -
    6547 }
    -
    6548 else if (text[this->interval.end] == '.') {
    -
    6549 this->interval.end++;
    -
    6550 for (;;) {
    -
    6551 if (this->interval.end < end && text[this->interval.end]) {
    -
    6552 if ('0' <= text[this->interval.end] && text[this->interval.end] <= '9') {
    -
    6553 decimalni_del = decimalni_del * 10 + text[this->interval.end] - '0';
    -
    6554 decimalni_del_n *= 10;
    -
    6555 this->interval.end++;
    -
    6556 }
    -
    6557 else
    -
    6558 break;
    -
    6559 }
    -
    6560 else
    -
    6561 break;
    -
    6562 }
    +
    6547 for (;;) {
    +
    6548 if (this->interval.end < end && text[this->interval.end]) {
    +
    6549 if ('0' <= text[this->interval.end] && text[this->interval.end] <= '9') {
    +
    6550 decimalni_del = decimalni_del * 10 + text[this->interval.end] - '0';
    +
    6551 decimalni_del_n *= 10;
    +
    6552 this->interval.end++;
    +
    6553 }
    +
    6554 else
    +
    6555 break;
    +
    6556 }
    +
    6557 else
    +
    6558 break;
    +
    6559 }
    +
    6560 break;
    +
    6561 }
    +
    6562 else
    6563 break;
    -
    6564 }
    -
    6565 else
    -
    6566 break;
    -
    6567 }
    -
    6568 else
    -
    6569 break;
    -
    6570 }
    - - -
    6573 this->interval.start = start;
    -
    6574 return true;
    -
    6575 }
    -
    6576 value = 1.0f;
    -
    6577 this->interval.start = (this->interval.end = start) + 1;
    -
    6578 return false;
    -
    6579 }
    -
    6580
    -
    6581 virtual void invalidate()
    -
    6582 {
    -
    6583 value = 1.0f;
    -
    6584 parser::invalidate();
    -
    6585 }
    -
    6586
    -
    6587 public:
    -
    6588 float value;
    -
    6589 };
    +
    6564 }
    +
    6565 else
    +
    6566 break;
    +
    6567 }
    + + +
    6570 this->interval.start = start;
    +
    6571 return true;
    +
    6572 }
    +
    6573 value = 1.0f;
    +
    6574 this->interval.start = (this->interval.end = start) + 1;
    +
    6575 return false;
    +
    6576 }
    +
    6577
    +
    6578 virtual void invalidate()
    +
    6579 {
    +
    6580 value = 1.0f;
    +
    6581 parser::invalidate();
    +
    6582 }
    +
    6583
    +
    6584 public:
    +
    6585 float value;
    +
    6586 };
    -
    6590
    -
    -
    6594 class http_asterisk : public parser
    -
    6595 {
    -
    6596 public:
    -
    6597 virtual bool match(
    -
    6598 _In_reads_or_z_(end) const char* text,
    -
    6599 _In_ size_t start = 0,
    -
    6600 _In_ size_t end = (size_t)-1,
    -
    6601 _In_ int flags = match_default)
    -
    6602 {
    -
    6603 _Assume_(text || end <= start);
    -
    6604 if (start < end && text[start] == '*') {
    -
    6605 this->interval.end = (this->interval.start = start) + 1;
    -
    6606 return true;
    -
    6607 }
    -
    6608 this->interval.start = (this->interval.end = start) + 1;
    -
    6609 return false;
    -
    6610 }
    -
    6611 };
    +
    6587
    +
    +
    6591 class http_asterisk : public parser
    +
    6592 {
    +
    6593 public:
    +
    6594 virtual bool match(
    +
    6595 _In_reads_or_z_(end) const char* text,
    +
    6596 _In_ size_t start = 0,
    +
    6597 _In_ size_t end = (size_t)-1,
    +
    6598 _In_ int flags = match_default)
    +
    6599 {
    +
    6600 _Assume_(text || end <= start);
    +
    6601 if (start < end && text[start] == '*') {
    +
    6602 this->interval.end = (this->interval.start = start) + 1;
    +
    6603 return true;
    +
    6604 }
    +
    6605 this->interval.start = (this->interval.end = start) + 1;
    +
    6606 return false;
    +
    6607 }
    +
    6608 };
    -
    6612
    -
    6616 template <class T, class T_asterisk = http_asterisk>
    -
    - -
    6618 {
    -
    6619 public:
    -
    6620 http_weighted_value(_In_ const std::locale& locale = std::locale()) :
    -
    6621 parser(locale),
    -
    6622 factor(locale)
    -
    6623 {}
    -
    6624
    -
    6625 virtual bool match(
    -
    6626 _In_reads_or_z_(end) const char* text,
    -
    6627 _In_ size_t start = 0,
    -
    6628 _In_ size_t end = (size_t)-1,
    -
    6629 _In_ int flags = match_default)
    -
    6630 {
    -
    6631 _Assume_(text || start >= end);
    -
    6632 size_t konec_vrednosti;
    -
    6633 this->interval.end = start;
    -
    6634 if (asterisk.match(text, this->interval.end, end, flags)) {
    -
    6635 this->interval.end = konec_vrednosti = asterisk.interval.end;
    -
    6636 value.invalidate();
    -
    6637 }
    -
    6638 else if (value.match(text, this->interval.end, end, flags)) {
    -
    6639 this->interval.end = konec_vrednosti = value.interval.end;
    +
    6609
    +
    6613 template <class T, class T_asterisk = http_asterisk>
    +
    + +
    6615 {
    +
    6616 public:
    +
    6617 http_weighted_value(_In_ const std::locale& locale = std::locale()) :
    +
    6618 parser(locale),
    +
    6619 factor(locale)
    +
    6620 {}
    +
    6621
    +
    6622 virtual bool match(
    +
    6623 _In_reads_or_z_(end) const char* text,
    +
    6624 _In_ size_t start = 0,
    +
    6625 _In_ size_t end = (size_t)-1,
    +
    6626 _In_ int flags = match_default)
    +
    6627 {
    +
    6628 _Assume_(text || start >= end);
    +
    6629 size_t konec_vrednosti;
    +
    6630 this->interval.end = start;
    +
    6631 if (asterisk.match(text, this->interval.end, end, flags)) {
    +
    6632 this->interval.end = konec_vrednosti = asterisk.interval.end;
    +
    6633 value.invalidate();
    +
    6634 }
    +
    6635 else if (value.match(text, this->interval.end, end, flags)) {
    +
    6636 this->interval.end = konec_vrednosti = value.interval.end;
    +
    6637 asterisk.invalidate();
    +
    6638 }
    +
    6639 else {
    6640 asterisk.invalidate();
    -
    6641 }
    -
    6642 else {
    -
    6643 asterisk.invalidate();
    -
    6644 value.invalidate();
    -
    6645 this->interval.start = (this->interval.end = start) + 1;
    -
    6646 return false;
    -
    6647 }
    -
    6648
    -
    6649 while (this->interval.end < end && text[this->interval.end] && isspace(text[this->interval.end])) this->interval.end++;
    -
    6650 if (this->interval.end < end && text[this->interval.end] == ';') {
    -
    6651 this->interval.end++;
    -
    6652 while (this->interval.end < end && text[this->interval.end] && isspace(text[this->interval.end])) this->interval.end++;
    -
    6653 if (this->interval.end < end && (text[this->interval.end] == 'q' || text[this->interval.end] == 'Q')) {
    -
    6654 this->interval.end++;
    -
    6655 while (this->interval.end < end && text[this->interval.end] && isspace(text[this->interval.end])) this->interval.end++;
    -
    6656 if (this->interval.end < end && text[this->interval.end] == '=') {
    -
    6657 this->interval.end++;
    -
    6658 while (this->interval.end < end && text[this->interval.end] && isspace(text[this->interval.end])) this->interval.end++;
    -
    6659 if (factor.match(text, this->interval.end, end, flags))
    -
    6660 this->interval.end = factor.interval.end;
    -
    6661 }
    -
    6662 }
    -
    6663 }
    -
    6664 if (!factor.interval) {
    -
    6665 factor.invalidate();
    - -
    6667 }
    -
    6668 this->interval.start = start;
    -
    6669 return true;
    -
    6670 }
    -
    6671
    -
    6672 virtual void invalidate()
    -
    6673 {
    -
    6674 asterisk.invalidate();
    -
    6675 value.invalidate();
    -
    6676 factor.invalidate();
    -
    6677 parser::invalidate();
    -
    6678 }
    -
    6679
    -
    6680 public:
    -
    6681 T_asterisk asterisk;
    -
    6682 T value;
    -
    6683 http_weight factor;
    -
    6684 };
    +
    6641 value.invalidate();
    +
    6642 this->interval.start = (this->interval.end = start) + 1;
    +
    6643 return false;
    +
    6644 }
    +
    6645
    +
    6646 while (this->interval.end < end && text[this->interval.end] && isspace(text[this->interval.end])) this->interval.end++;
    +
    6647 if (this->interval.end < end && text[this->interval.end] == ';') {
    +
    6648 this->interval.end++;
    +
    6649 while (this->interval.end < end && text[this->interval.end] && isspace(text[this->interval.end])) this->interval.end++;
    +
    6650 if (this->interval.end < end && (text[this->interval.end] == 'q' || text[this->interval.end] == 'Q')) {
    +
    6651 this->interval.end++;
    +
    6652 while (this->interval.end < end && text[this->interval.end] && isspace(text[this->interval.end])) this->interval.end++;
    +
    6653 if (this->interval.end < end && text[this->interval.end] == '=') {
    +
    6654 this->interval.end++;
    +
    6655 while (this->interval.end < end && text[this->interval.end] && isspace(text[this->interval.end])) this->interval.end++;
    +
    6656 if (factor.match(text, this->interval.end, end, flags))
    +
    6657 this->interval.end = factor.interval.end;
    +
    6658 }
    +
    6659 }
    +
    6660 }
    +
    6661 if (!factor.interval) {
    +
    6662 factor.invalidate();
    + +
    6664 }
    +
    6665 this->interval.start = start;
    +
    6666 return true;
    +
    6667 }
    +
    6668
    +
    6669 virtual void invalidate()
    +
    6670 {
    +
    6671 asterisk.invalidate();
    +
    6672 value.invalidate();
    +
    6673 factor.invalidate();
    +
    6674 parser::invalidate();
    +
    6675 }
    +
    6676
    +
    6677 public:
    +
    6678 T_asterisk asterisk;
    +
    6679 T value;
    +
    6680 http_weight factor;
    +
    6681 };
    -
    6685
    -
    - -
    6690 {
    -
    6691 public:
    -
    6692 virtual bool match(
    -
    6693 _In_reads_or_z_(end) const char* text,
    -
    6694 _In_ size_t start = 0,
    -
    6695 _In_ size_t end = (size_t)-1,
    -
    6696 _In_ int flags = match_default)
    -
    6697 {
    -
    6698 _Assume_(text || start >= end);
    -
    6699 this->interval.end = start;
    -
    6700 if (this->interval.end < end && text[this->interval.end] == '$')
    -
    6701 this->interval.end++;
    -
    6702 else
    -
    6703 goto error;
    -
    6704 if (name.match(text, this->interval.end, end, flags))
    -
    6705 this->interval.end = name.interval.end;
    -
    6706 else
    -
    6707 goto error;
    -
    6708 while (m_space.match(text, this->interval.end, end, flags))
    -
    6709 this->interval.end = m_space.interval.end;
    -
    6710 if (this->interval.end < end && text[this->interval.end] == '=')
    -
    6711 this->interval.end++;
    -
    6712 else
    -
    6713 goto error;
    -
    6714 while (m_space.match(text, this->interval.end, end, flags))
    -
    6715 this->interval.end = m_space.interval.end;
    -
    6716 if (value.match(text, this->interval.end, end, flags))
    -
    6717 this->interval.end = value.interval.end;
    -
    6718 else
    -
    6719 goto error;
    -
    6720 this->interval.start = start;
    -
    6721 return true;
    -
    6722
    -
    6723 error:
    -
    6724 name.invalidate();
    -
    6725 value.invalidate();
    -
    6726 this->interval.start = (this->interval.end = start) + 1;
    -
    6727 return false;
    -
    6728 }
    -
    6729
    -
    6730 virtual void invalidate()
    -
    6731 {
    -
    6732 name.invalidate();
    -
    6733 value.invalidate();
    -
    6734 parser::invalidate();
    -
    6735 }
    -
    6736
    -
    6737 public:
    -
    6738 http_token name;
    -
    6739 http_value value;
    -
    6740
    -
    6741 protected:
    -
    6742 http_space m_space;
    -
    6743 };
    +
    6682
    +
    + +
    6687 {
    +
    6688 public:
    +
    6689 virtual bool match(
    +
    6690 _In_reads_or_z_(end) const char* text,
    +
    6691 _In_ size_t start = 0,
    +
    6692 _In_ size_t end = (size_t)-1,
    +
    6693 _In_ int flags = match_default)
    +
    6694 {
    +
    6695 _Assume_(text || start >= end);
    +
    6696 this->interval.end = start;
    +
    6697 if (this->interval.end < end && text[this->interval.end] == '$')
    +
    6698 this->interval.end++;
    +
    6699 else
    +
    6700 goto error;
    +
    6701 if (name.match(text, this->interval.end, end, flags))
    +
    6702 this->interval.end = name.interval.end;
    +
    6703 else
    +
    6704 goto error;
    +
    6705 while (m_space.match(text, this->interval.end, end, flags))
    +
    6706 this->interval.end = m_space.interval.end;
    +
    6707 if (this->interval.end < end && text[this->interval.end] == '=')
    +
    6708 this->interval.end++;
    +
    6709 else
    +
    6710 goto error;
    +
    6711 while (m_space.match(text, this->interval.end, end, flags))
    +
    6712 this->interval.end = m_space.interval.end;
    +
    6713 if (value.match(text, this->interval.end, end, flags))
    +
    6714 this->interval.end = value.interval.end;
    +
    6715 else
    +
    6716 goto error;
    +
    6717 this->interval.start = start;
    +
    6718 return true;
    +
    6719
    +
    6720 error:
    +
    6721 name.invalidate();
    +
    6722 value.invalidate();
    +
    6723 this->interval.start = (this->interval.end = start) + 1;
    +
    6724 return false;
    +
    6725 }
    +
    6726
    +
    6727 virtual void invalidate()
    +
    6728 {
    +
    6729 name.invalidate();
    +
    6730 value.invalidate();
    +
    6731 parser::invalidate();
    +
    6732 }
    +
    6733
    +
    6734 public:
    +
    6735 http_token name;
    +
    6736 http_value value;
    +
    6737
    +
    6738 protected:
    +
    6739 http_space m_space;
    +
    6740 };
    -
    6744
    -
    -
    6748 class http_cookie : public parser
    -
    6749 {
    -
    6750 public:
    -
    6751 virtual bool match(
    -
    6752 _In_reads_or_z_(end) const char* text,
    -
    6753 _In_ size_t start = 0,
    -
    6754 _In_ size_t end = (size_t)-1,
    -
    6755 _In_ int flags = match_default)
    -
    6756 {
    -
    6757 _Assume_(text || start >= end);
    -
    6758 this->interval.end = start;
    -
    6759 if (name.match(text, this->interval.end, end, flags))
    -
    6760 this->interval.end = name.interval.end;
    -
    6761 else
    -
    6762 goto error;
    -
    6763 while (m_space.match(text, this->interval.end, end, flags))
    -
    6764 this->interval.end = m_space.interval.end;
    -
    6765 if (this->interval.end < end && text[this->interval.end] == '=')
    -
    6766 this->interval.end++;
    -
    6767 else
    -
    6768 goto error;
    -
    6769 while (m_space.match(text, this->interval.end, end, flags))
    -
    6770 this->interval.end = m_space.interval.end;
    -
    6771 if (value.match(text, this->interval.end, end, flags))
    -
    6772 this->interval.end = value.interval.end;
    -
    6773 else
    -
    6774 goto error;
    -
    6775 params.clear();
    -
    6776 for (;;) {
    -
    6777 if (this->interval.end < end && text[this->interval.end]) {
    -
    6778 if (m_space.match(text, this->interval.end, end, flags))
    -
    6779 this->interval.end = m_space.interval.end;
    -
    6780 else if (text[this->interval.end] == ';') {
    -
    6781 this->interval.end++;
    -
    6782 while (m_space.match(text, this->interval.end, end, flags))
    -
    6783 this->interval.end = m_space.interval.end;
    - -
    6785 if (param.match(text, this->interval.end, end, flags)) {
    -
    6786 this->interval.end = param.interval.end;
    -
    6787 params.push_back(std::move(param));
    -
    6788 }
    -
    6789 else
    -
    6790 break;
    -
    6791 }
    -
    6792 else
    -
    6793 break;
    -
    6794 }
    -
    6795 else
    -
    6796 break;
    -
    6797 }
    -
    6798 this->interval.start = start;
    -
    6799 this->interval.end = params.empty() ? value.interval.end : params.back().interval.end;
    -
    6800 return true;
    -
    6801
    -
    6802 error:
    -
    6803 name.invalidate();
    -
    6804 value.invalidate();
    -
    6805 params.clear();
    -
    6806 this->interval.start = (this->interval.end = start) + 1;
    -
    6807 return false;
    -
    6808 }
    -
    6809
    -
    6810 virtual void invalidate()
    -
    6811 {
    -
    6812 name.invalidate();
    -
    6813 value.invalidate();
    -
    6814 params.clear();
    -
    6815 parser::invalidate();
    -
    6816 }
    -
    6817
    -
    6818 public:
    - - -
    6821 std::list<http_cookie_parameter> params;
    -
    6822
    -
    6823 protected:
    -
    6824 http_space m_space;
    -
    6825 };
    +
    6741
    +
    +
    6745 class http_cookie : public parser
    +
    6746 {
    +
    6747 public:
    +
    6748 virtual bool match(
    +
    6749 _In_reads_or_z_(end) const char* text,
    +
    6750 _In_ size_t start = 0,
    +
    6751 _In_ size_t end = (size_t)-1,
    +
    6752 _In_ int flags = match_default)
    +
    6753 {
    +
    6754 _Assume_(text || start >= end);
    +
    6755 this->interval.end = start;
    +
    6756 if (name.match(text, this->interval.end, end, flags))
    +
    6757 this->interval.end = name.interval.end;
    +
    6758 else
    +
    6759 goto error;
    +
    6760 while (m_space.match(text, this->interval.end, end, flags))
    +
    6761 this->interval.end = m_space.interval.end;
    +
    6762 if (this->interval.end < end && text[this->interval.end] == '=')
    +
    6763 this->interval.end++;
    +
    6764 else
    +
    6765 goto error;
    +
    6766 while (m_space.match(text, this->interval.end, end, flags))
    +
    6767 this->interval.end = m_space.interval.end;
    +
    6768 if (value.match(text, this->interval.end, end, flags))
    +
    6769 this->interval.end = value.interval.end;
    +
    6770 else
    +
    6771 goto error;
    +
    6772 params.clear();
    +
    6773 for (;;) {
    +
    6774 if (this->interval.end < end && text[this->interval.end]) {
    +
    6775 if (m_space.match(text, this->interval.end, end, flags))
    +
    6776 this->interval.end = m_space.interval.end;
    +
    6777 else if (text[this->interval.end] == ';') {
    +
    6778 this->interval.end++;
    +
    6779 while (m_space.match(text, this->interval.end, end, flags))
    +
    6780 this->interval.end = m_space.interval.end;
    + +
    6782 if (param.match(text, this->interval.end, end, flags)) {
    +
    6783 this->interval.end = param.interval.end;
    +
    6784 params.push_back(std::move(param));
    +
    6785 }
    +
    6786 else
    +
    6787 break;
    +
    6788 }
    +
    6789 else
    +
    6790 break;
    +
    6791 }
    +
    6792 else
    +
    6793 break;
    +
    6794 }
    +
    6795 this->interval.start = start;
    +
    6796 this->interval.end = params.empty() ? value.interval.end : params.back().interval.end;
    +
    6797 return true;
    +
    6798
    +
    6799 error:
    +
    6800 name.invalidate();
    +
    6801 value.invalidate();
    +
    6802 params.clear();
    +
    6803 this->interval.start = (this->interval.end = start) + 1;
    +
    6804 return false;
    +
    6805 }
    +
    6806
    +
    6807 virtual void invalidate()
    +
    6808 {
    +
    6809 name.invalidate();
    +
    6810 value.invalidate();
    +
    6811 params.clear();
    +
    6812 parser::invalidate();
    +
    6813 }
    +
    6814
    +
    6815 public:
    + + +
    6818 std::list<http_cookie_parameter> params;
    +
    6819
    +
    6820 protected:
    +
    6821 http_space m_space;
    +
    6822 };
    -
    6826
    -
    -
    6830 class http_agent : public parser
    -
    6831 {
    -
    6832 public:
    -
    6833 virtual bool match(
    -
    6834 _In_reads_or_z_(end) const char* text,
    -
    6835 _In_ size_t start = 0,
    -
    6836 _In_ size_t end = (size_t)-1,
    -
    6837 _In_ int flags = match_default)
    -
    6838 {
    -
    6839 _Assume_(text || start >= end);
    -
    6840 this->interval.end = start;
    -
    6841 type.start = this->interval.end;
    -
    6842 for (;;) {
    -
    6843 if (this->interval.end < end && text[this->interval.end]) {
    -
    6844 if (text[this->interval.end] == '/') {
    -
    6845 type.end = this->interval.end;
    -
    6846 this->interval.end++;
    -
    6847 version.start = this->interval.end;
    -
    6848 for (;;) {
    -
    6849 if (this->interval.end < end && text[this->interval.end]) {
    -
    6850 if (isspace(text[this->interval.end])) {
    -
    6851 version.end = this->interval.end;
    -
    6852 break;
    -
    6853 }
    -
    6854 else
    -
    6855 this->interval.end++;
    -
    6856 }
    -
    6857 else {
    -
    6858 version.end = this->interval.end;
    -
    6859 break;
    -
    6860 }
    -
    6861 }
    -
    6862 break;
    -
    6863 }
    -
    6864 else if (isspace(text[this->interval.end])) {
    -
    6865 type.end = this->interval.end;
    -
    6866 break;
    -
    6867 }
    -
    6868 else
    -
    6869 this->interval.end++;
    -
    6870 }
    -
    6871 else {
    -
    6872 type.end = this->interval.end;
    -
    6873 break;
    -
    6874 }
    -
    6875 }
    - -
    6877 this->interval.start = start;
    -
    6878 return true;
    -
    6879 }
    -
    6880 type.start = 1;
    -
    6881 type.end = 0;
    -
    6882 version.start = 1;
    -
    6883 version.end = 0;
    -
    6884 this->interval.start = 1;
    -
    6885 this->interval.end = 0;
    -
    6886 return false;
    -
    6887 }
    -
    6888
    -
    6889 virtual void invalidate()
    -
    6890 {
    -
    6891 type.start = 1;
    -
    6892 type.end = 0;
    -
    6893 version.start = 1;
    -
    6894 version.end = 0;
    -
    6895 parser::invalidate();
    -
    6896 }
    -
    6897
    -
    6898 public:
    - - -
    6901 };
    +
    6823
    +
    +
    6827 class http_agent : public parser
    +
    6828 {
    +
    6829 public:
    +
    6830 virtual bool match(
    +
    6831 _In_reads_or_z_(end) const char* text,
    +
    6832 _In_ size_t start = 0,
    +
    6833 _In_ size_t end = (size_t)-1,
    +
    6834 _In_ int flags = match_default)
    +
    6835 {
    +
    6836 _Assume_(text || start >= end);
    +
    6837 this->interval.end = start;
    +
    6838 type.start = this->interval.end;
    +
    6839 for (;;) {
    +
    6840 if (this->interval.end < end && text[this->interval.end]) {
    +
    6841 if (text[this->interval.end] == '/') {
    +
    6842 type.end = this->interval.end;
    +
    6843 this->interval.end++;
    +
    6844 version.start = this->interval.end;
    +
    6845 for (;;) {
    +
    6846 if (this->interval.end < end && text[this->interval.end]) {
    +
    6847 if (isspace(text[this->interval.end])) {
    +
    6848 version.end = this->interval.end;
    +
    6849 break;
    +
    6850 }
    +
    6851 else
    +
    6852 this->interval.end++;
    +
    6853 }
    +
    6854 else {
    +
    6855 version.end = this->interval.end;
    +
    6856 break;
    +
    6857 }
    +
    6858 }
    +
    6859 break;
    +
    6860 }
    +
    6861 else if (isspace(text[this->interval.end])) {
    +
    6862 type.end = this->interval.end;
    +
    6863 break;
    +
    6864 }
    +
    6865 else
    +
    6866 this->interval.end++;
    +
    6867 }
    +
    6868 else {
    +
    6869 type.end = this->interval.end;
    +
    6870 break;
    +
    6871 }
    +
    6872 }
    + +
    6874 this->interval.start = start;
    +
    6875 return true;
    +
    6876 }
    +
    6877 type.start = 1;
    +
    6878 type.end = 0;
    +
    6879 version.start = 1;
    +
    6880 version.end = 0;
    +
    6881 this->interval.start = 1;
    +
    6882 this->interval.end = 0;
    +
    6883 return false;
    +
    6884 }
    +
    6885
    +
    6886 virtual void invalidate()
    +
    6887 {
    +
    6888 type.start = 1;
    +
    6889 type.end = 0;
    +
    6890 version.start = 1;
    +
    6891 version.end = 0;
    +
    6892 parser::invalidate();
    +
    6893 }
    +
    6894
    +
    6895 public:
    + + +
    6898 };
    -
    6902
    -
    -
    6906 class http_protocol : public parser
    -
    6907 {
    -
    6908 public:
    -
    6909 http_protocol(_In_ const std::locale& locale = std::locale()) :
    -
    6910 parser(locale),
    -
    6911 version(0x009)
    -
    6912 {}
    -
    6913
    -
    6914 virtual bool match(
    -
    6915 _In_reads_or_z_(end) const char* text,
    -
    6916 _In_ size_t start = 0,
    -
    6917 _In_ size_t end = (size_t)-1,
    -
    6918 _In_ int flags = match_default)
    -
    6919 {
    -
    6920 _Assume_(text || start >= end);
    -
    6921 this->interval.end = start;
    -
    6922 type.start = this->interval.end;
    -
    6923 for (;;) {
    -
    6924 if (this->interval.end < end && text[this->interval.end]) {
    -
    6925 if (text[this->interval.end] == '/') {
    -
    6926 type.end = this->interval.end;
    -
    6927 this->interval.end++;
    -
    6928 break;
    -
    6929 }
    -
    6930 else if (isspace(text[this->interval.end]))
    -
    6931 goto error;
    -
    6932 else
    -
    6933 this->interval.end++;
    -
    6934 }
    -
    6935 else {
    -
    6936 type.end = this->interval.end;
    -
    6937 goto error;
    -
    6938 }
    -
    6939 }
    -
    6940 version_maj.start = this->interval.end;
    -
    6941 for (;;) {
    -
    6942 if (this->interval.end < end && text[this->interval.end]) {
    -
    6943 if (text[this->interval.end] == '.') {
    -
    6944 version_maj.end = this->interval.end;
    -
    6945 this->interval.end++;
    -
    6946 version_min.start = this->interval.end;
    -
    6947 for (;;) {
    -
    6948 if (this->interval.end < end && text[this->interval.end]) {
    -
    6949 if (isspace(text[this->interval.end])) {
    -
    6950 version_min.end = this->interval.end;
    -
    6951 version =
    -
    6952 (uint16_t)strtoui(text + version_maj.start, version_maj.size(), nullptr, 10) * 0x100 +
    -
    6953 (uint16_t)strtoui(text + version_min.start, version_min.size(), nullptr, 10);
    -
    6954 break;
    -
    6955 }
    -
    6956 else
    -
    6957 this->interval.end++;
    -
    6958 }
    -
    6959 else
    -
    6960 goto error;
    -
    6961 }
    -
    6962 break;
    -
    6963 }
    -
    6964 else if (isspace(text[this->interval.end])) {
    -
    6965 version_maj.end = this->interval.end;
    -
    6966 version_min.start = 1;
    -
    6967 version_min.end = 0;
    -
    6968 version = (uint16_t)strtoui(text + version_maj.start, version_maj.size(), nullptr, 10) * 0x100;
    -
    6969 break;
    -
    6970 }
    -
    6971 else
    -
    6972 this->interval.end++;
    -
    6973 }
    -
    6974 else
    -
    6975 goto error;
    -
    6976 }
    -
    6977 this->interval.start = start;
    -
    6978 return true;
    -
    6979
    -
    6980 error:
    -
    6981 type.start = 1;
    -
    6982 type.end = 0;
    -
    6983 version_maj.start = 1;
    -
    6984 version_maj.end = 0;
    -
    6985 version_min.start = 1;
    -
    6986 version_min.end = 0;
    -
    6987 version = 0x009;
    -
    6988 this->interval.start = 1;
    -
    6989 this->interval.end = 0;
    -
    6990 return false;
    -
    6991 }
    -
    6992
    -
    6993 virtual void invalidate()
    -
    6994 {
    -
    6995 type.start = 1;
    -
    6996 type.end = 0;
    -
    6997 version_maj.start = 1;
    -
    6998 version_maj.end = 0;
    -
    6999 version_min.start = 1;
    -
    7000 version_min.end = 0;
    -
    7001 version = 0x009;
    -
    7002 parser::invalidate();
    -
    7003 }
    -
    7004
    -
    7005 public:
    - -
    7007 stdex::interval<size_t> version_maj;
    -
    7008 stdex::interval<size_t> version_min;
    - -
    7010 };
    +
    6899
    +
    +
    6903 class http_protocol : public parser
    +
    6904 {
    +
    6905 public:
    +
    6906 http_protocol(_In_ const std::locale& locale = std::locale()) :
    +
    6907 parser(locale),
    +
    6908 version(0x009)
    +
    6909 {}
    +
    6910
    +
    6911 virtual bool match(
    +
    6912 _In_reads_or_z_(end) const char* text,
    +
    6913 _In_ size_t start = 0,
    +
    6914 _In_ size_t end = (size_t)-1,
    +
    6915 _In_ int flags = match_default)
    +
    6916 {
    +
    6917 _Assume_(text || start >= end);
    +
    6918 this->interval.end = start;
    +
    6919 type.start = this->interval.end;
    +
    6920 for (;;) {
    +
    6921 if (this->interval.end < end && text[this->interval.end]) {
    +
    6922 if (text[this->interval.end] == '/') {
    +
    6923 type.end = this->interval.end;
    +
    6924 this->interval.end++;
    +
    6925 break;
    +
    6926 }
    +
    6927 else if (isspace(text[this->interval.end]))
    +
    6928 goto error;
    +
    6929 else
    +
    6930 this->interval.end++;
    +
    6931 }
    +
    6932 else {
    +
    6933 type.end = this->interval.end;
    +
    6934 goto error;
    +
    6935 }
    +
    6936 }
    +
    6937 version_maj.start = this->interval.end;
    +
    6938 for (;;) {
    +
    6939 if (this->interval.end < end && text[this->interval.end]) {
    +
    6940 if (text[this->interval.end] == '.') {
    +
    6941 version_maj.end = this->interval.end;
    +
    6942 this->interval.end++;
    +
    6943 version_min.start = this->interval.end;
    +
    6944 for (;;) {
    +
    6945 if (this->interval.end < end && text[this->interval.end]) {
    +
    6946 if (isspace(text[this->interval.end])) {
    +
    6947 version_min.end = this->interval.end;
    +
    6948 version =
    +
    6949 (uint16_t)strtoui(text + version_maj.start, version_maj.size(), nullptr, 10) * 0x100 +
    +
    6950 (uint16_t)strtoui(text + version_min.start, version_min.size(), nullptr, 10);
    +
    6951 break;
    +
    6952 }
    +
    6953 else
    +
    6954 this->interval.end++;
    +
    6955 }
    +
    6956 else
    +
    6957 goto error;
    +
    6958 }
    +
    6959 break;
    +
    6960 }
    +
    6961 else if (isspace(text[this->interval.end])) {
    +
    6962 version_maj.end = this->interval.end;
    +
    6963 version_min.start = 1;
    +
    6964 version_min.end = 0;
    +
    6965 version = (uint16_t)strtoui(text + version_maj.start, version_maj.size(), nullptr, 10) * 0x100;
    +
    6966 break;
    +
    6967 }
    +
    6968 else
    +
    6969 this->interval.end++;
    +
    6970 }
    +
    6971 else
    +
    6972 goto error;
    +
    6973 }
    +
    6974 this->interval.start = start;
    +
    6975 return true;
    +
    6976
    +
    6977 error:
    +
    6978 type.start = 1;
    +
    6979 type.end = 0;
    +
    6980 version_maj.start = 1;
    +
    6981 version_maj.end = 0;
    +
    6982 version_min.start = 1;
    +
    6983 version_min.end = 0;
    +
    6984 version = 0x009;
    +
    6985 this->interval.start = 1;
    +
    6986 this->interval.end = 0;
    +
    6987 return false;
    +
    6988 }
    +
    6989
    +
    6990 virtual void invalidate()
    +
    6991 {
    +
    6992 type.start = 1;
    +
    6993 type.end = 0;
    +
    6994 version_maj.start = 1;
    +
    6995 version_maj.end = 0;
    +
    6996 version_min.start = 1;
    +
    6997 version_min.end = 0;
    +
    6998 version = 0x009;
    +
    6999 parser::invalidate();
    +
    7000 }
    +
    7001
    +
    7002 public:
    + +
    7004 stdex::interval<size_t> version_maj;
    +
    7005 stdex::interval<size_t> version_min;
    + +
    7007 };
    -
    7011
    -
    -
    7015 class http_request : public parser
    -
    7016 {
    -
    7017 public:
    -
    7018 http_request(_In_ const std::locale& locale = std::locale()) :
    -
    7019 parser(locale),
    -
    7020 url(locale),
    -
    7021 protocol(locale)
    -
    7022 {}
    -
    7023
    -
    7024 virtual bool match(
    -
    7025 _In_reads_or_z_(end) const char* text,
    -
    7026 _In_ size_t start = 0,
    -
    7027 _In_ size_t end = (size_t)-1,
    -
    7028 _In_ int flags = match_default)
    -
    7029 {
    -
    7030 _Assume_(text || start >= end);
    -
    7031 this->interval.end = start;
    -
    7032
    -
    7033 for (;;) {
    -
    7034 if (m_line_break.match(text, this->interval.end, end, flags))
    -
    7035 goto error;
    -
    7036 else if (this->interval.end < end && text[this->interval.end]) {
    -
    7037 if (isspace(text[this->interval.end]))
    -
    7038 this->interval.end++;
    -
    7039 else
    -
    7040 break;
    -
    7041 }
    -
    7042 else
    -
    7043 goto error;
    -
    7044 }
    -
    7045 verb.start = this->interval.end;
    -
    7046 for (;;) {
    -
    7047 if (m_line_break.match(text, this->interval.end, end, flags))
    -
    7048 goto error;
    -
    7049 else if (this->interval.end < end && text[this->interval.end]) {
    -
    7050 if (isspace(text[this->interval.end])) {
    -
    7051 verb.end = this->interval.end;
    -
    7052 this->interval.end++;
    -
    7053 break;
    -
    7054 }
    -
    7055 else
    -
    7056 this->interval.end++;
    -
    7057 }
    -
    7058 else
    -
    7059 goto error;
    -
    7060 }
    -
    7061
    -
    7062 for (;;) {
    -
    7063 if (m_line_break.match(text, this->interval.end, end, flags))
    -
    7064 goto error;
    -
    7065 else if (this->interval.end < end && text[this->interval.end]) {
    -
    7066 if (isspace(text[this->interval.end]))
    -
    7067 this->interval.end++;
    -
    7068 else
    -
    7069 break;
    -
    7070 }
    -
    7071 else
    -
    7072 goto error;
    -
    7073 }
    -
    7074 if (url.match(text, this->interval.end, end, flags))
    -
    7075 this->interval.end = url.interval.end;
    -
    7076 else
    -
    7077 goto error;
    -
    7078
    -
    7079 protocol.invalidate();
    -
    7080 for (;;) {
    -
    7081 if (m_line_break.match(text, this->interval.end, end, flags)) {
    -
    7082 this->interval.end = m_line_break.interval.end;
    -
    7083 goto end;
    -
    7084 }
    -
    7085 else if (this->interval.end < end && text[this->interval.end]) {
    -
    7086 if (isspace(text[this->interval.end]))
    -
    7087 this->interval.end++;
    -
    7088 else
    -
    7089 break;
    -
    7090 }
    -
    7091 else
    -
    7092 goto end;
    -
    7093 }
    -
    7094 for (;;) {
    -
    7095 if (m_line_break.match(text, this->interval.end, end, flags)) {
    -
    7096 this->interval.end = m_line_break.interval.end;
    -
    7097 goto end;
    -
    7098 }
    -
    7099 else if (protocol.match(text, this->interval.end, end, flags)) {
    -
    7100 this->interval.end = protocol.interval.end;
    -
    7101 break;
    -
    7102 }
    -
    7103 else
    -
    7104 goto end;
    -
    7105 }
    -
    7106
    -
    7107 for (;;) {
    -
    7108 if (m_line_break.match(text, this->interval.end, end, flags)) {
    -
    7109 this->interval.end = m_line_break.interval.end;
    -
    7110 break;
    -
    7111 }
    -
    7112 else if (this->interval.end < end && text[this->interval.end])
    -
    7113 this->interval.end++;
    -
    7114 else
    -
    7115 goto end;
    -
    7116 }
    -
    7117
    -
    7118 end:
    -
    7119 this->interval.start = start;
    -
    7120 return true;
    -
    7121
    -
    7122 error:
    -
    7123 verb.start = 1;
    -
    7124 verb.end = 0;
    -
    7125 url.invalidate();
    -
    7126 protocol.invalidate();
    -
    7127 this->interval.start = 1;
    -
    7128 this->interval.end = 0;
    -
    7129 return false;
    -
    7130 }
    -
    7131
    -
    7132 virtual void invalidate()
    -
    7133 {
    -
    7134 verb.start = 1;
    -
    7135 verb.end = 0;
    -
    7136 url.invalidate();
    -
    7137 protocol.invalidate();
    -
    7138 parser::invalidate();
    -
    7139 }
    -
    7140
    -
    7141 public:
    - -
    7143 http_url url;
    -
    7144 http_protocol protocol;
    -
    7145
    -
    7146 protected:
    -
    7147 http_line_break m_line_break;
    -
    7148 };
    +
    7008
    +
    +
    7012 class http_request : public parser
    +
    7013 {
    +
    7014 public:
    +
    7015 http_request(_In_ const std::locale& locale = std::locale()) :
    +
    7016 parser(locale),
    +
    7017 url(locale),
    +
    7018 protocol(locale)
    +
    7019 {}
    +
    7020
    +
    7021 virtual bool match(
    +
    7022 _In_reads_or_z_(end) const char* text,
    +
    7023 _In_ size_t start = 0,
    +
    7024 _In_ size_t end = (size_t)-1,
    +
    7025 _In_ int flags = match_default)
    +
    7026 {
    +
    7027 _Assume_(text || start >= end);
    +
    7028 this->interval.end = start;
    +
    7029
    +
    7030 for (;;) {
    +
    7031 if (m_line_break.match(text, this->interval.end, end, flags))
    +
    7032 goto error;
    +
    7033 else if (this->interval.end < end && text[this->interval.end]) {
    +
    7034 if (isspace(text[this->interval.end]))
    +
    7035 this->interval.end++;
    +
    7036 else
    +
    7037 break;
    +
    7038 }
    +
    7039 else
    +
    7040 goto error;
    +
    7041 }
    +
    7042 verb.start = this->interval.end;
    +
    7043 for (;;) {
    +
    7044 if (m_line_break.match(text, this->interval.end, end, flags))
    +
    7045 goto error;
    +
    7046 else if (this->interval.end < end && text[this->interval.end]) {
    +
    7047 if (isspace(text[this->interval.end])) {
    +
    7048 verb.end = this->interval.end;
    +
    7049 this->interval.end++;
    +
    7050 break;
    +
    7051 }
    +
    7052 else
    +
    7053 this->interval.end++;
    +
    7054 }
    +
    7055 else
    +
    7056 goto error;
    +
    7057 }
    +
    7058
    +
    7059 for (;;) {
    +
    7060 if (m_line_break.match(text, this->interval.end, end, flags))
    +
    7061 goto error;
    +
    7062 else if (this->interval.end < end && text[this->interval.end]) {
    +
    7063 if (isspace(text[this->interval.end]))
    +
    7064 this->interval.end++;
    +
    7065 else
    +
    7066 break;
    +
    7067 }
    +
    7068 else
    +
    7069 goto error;
    +
    7070 }
    +
    7071 if (url.match(text, this->interval.end, end, flags))
    +
    7072 this->interval.end = url.interval.end;
    +
    7073 else
    +
    7074 goto error;
    +
    7075
    +
    7076 protocol.invalidate();
    +
    7077 for (;;) {
    +
    7078 if (m_line_break.match(text, this->interval.end, end, flags)) {
    +
    7079 this->interval.end = m_line_break.interval.end;
    +
    7080 goto end;
    +
    7081 }
    +
    7082 else if (this->interval.end < end && text[this->interval.end]) {
    +
    7083 if (isspace(text[this->interval.end]))
    +
    7084 this->interval.end++;
    +
    7085 else
    +
    7086 break;
    +
    7087 }
    +
    7088 else
    +
    7089 goto end;
    +
    7090 }
    +
    7091 for (;;) {
    +
    7092 if (m_line_break.match(text, this->interval.end, end, flags)) {
    +
    7093 this->interval.end = m_line_break.interval.end;
    +
    7094 goto end;
    +
    7095 }
    +
    7096 else if (protocol.match(text, this->interval.end, end, flags)) {
    +
    7097 this->interval.end = protocol.interval.end;
    +
    7098 break;
    +
    7099 }
    +
    7100 else
    +
    7101 goto end;
    +
    7102 }
    +
    7103
    +
    7104 for (;;) {
    +
    7105 if (m_line_break.match(text, this->interval.end, end, flags)) {
    +
    7106 this->interval.end = m_line_break.interval.end;
    +
    7107 break;
    +
    7108 }
    +
    7109 else if (this->interval.end < end && text[this->interval.end])
    +
    7110 this->interval.end++;
    +
    7111 else
    +
    7112 goto end;
    +
    7113 }
    +
    7114
    +
    7115 end:
    +
    7116 this->interval.start = start;
    +
    7117 return true;
    +
    7118
    +
    7119 error:
    +
    7120 verb.start = 1;
    +
    7121 verb.end = 0;
    +
    7122 url.invalidate();
    +
    7123 protocol.invalidate();
    +
    7124 this->interval.start = 1;
    +
    7125 this->interval.end = 0;
    +
    7126 return false;
    +
    7127 }
    +
    7128
    +
    7129 virtual void invalidate()
    +
    7130 {
    +
    7131 verb.start = 1;
    +
    7132 verb.end = 0;
    +
    7133 url.invalidate();
    +
    7134 protocol.invalidate();
    +
    7135 parser::invalidate();
    +
    7136 }
    +
    7137
    +
    7138 public:
    + +
    7140 http_url url;
    +
    7141 http_protocol protocol;
    +
    7142
    +
    7143 protected:
    +
    7144 http_line_break m_line_break;
    +
    7145 };
    -
    7149
    -
    -
    7153 class http_header : public parser
    -
    7154 {
    -
    7155 public:
    -
    7156 virtual bool match(
    -
    7157 _In_reads_or_z_(end) const char* text,
    -
    7158 _In_ size_t start = 0,
    -
    7159 _In_ size_t end = (size_t)-1,
    -
    7160 _In_ int flags = match_default)
    -
    7161 {
    -
    7162 _Assume_(text || start >= end);
    -
    7163 this->interval.end = start;
    -
    7164
    -
    7165 if (m_line_break.match(text, this->interval.end, end, flags) ||
    -
    7166 (this->interval.end < end && text[this->interval.end] && isspace(text[this->interval.end])))
    -
    7167 goto error;
    -
    7168 name.start = this->interval.end;
    -
    7169 for (;;) {
    -
    7170 if (m_line_break.match(text, this->interval.end, end, flags))
    -
    7171 goto error;
    -
    7172 else if (this->interval.end < end && text[this->interval.end]) {
    -
    7173 if (isspace(text[this->interval.end])) {
    -
    7174 name.end = this->interval.end;
    -
    7175 this->interval.end++;
    -
    7176 for (;;) {
    -
    7177 if (m_line_break.match(text, this->interval.end, end, flags))
    -
    7178 goto error;
    -
    7179 else if (this->interval.end < end && text[this->interval.end]) {
    -
    7180 if (isspace(text[this->interval.end]))
    -
    7181 this->interval.end++;
    -
    7182 else
    -
    7183 break;
    -
    7184 }
    -
    7185 else
    -
    7186 goto error;
    -
    7187 }
    -
    7188 if (this->interval.end < end && text[this->interval.end] == ':') {
    -
    7189 this->interval.end++;
    -
    7190 break;
    -
    7191 }
    -
    7192 else
    -
    7193 goto error;
    -
    7194 break;
    -
    7195 }
    -
    7196 else if (text[this->interval.end] == ':') {
    -
    7197 name.end = this->interval.end;
    -
    7198 this->interval.end++;
    -
    7199 break;
    -
    7200 }
    -
    7201 else
    -
    7202 this->interval.end++;
    -
    7203 }
    -
    7204 else
    -
    7205 goto error;
    -
    7206 }
    -
    7207 value.start = (size_t)-1;
    -
    7208 value.end = 0;
    -
    7209 for (;;) {
    -
    7210 if (m_line_break.match(text, this->interval.end, end, flags)) {
    -
    7211 this->interval.end = m_line_break.interval.end;
    -
    7212 if (!m_line_break.match(text, this->interval.end, end, flags) &&
    -
    7213 this->interval.end < end && text[this->interval.end] && isspace(text[this->interval.end]))
    -
    7214 this->interval.end++;
    -
    7215 else
    -
    7216 break;
    -
    7217 }
    -
    7218 else if (this->interval.end < end && text[this->interval.end]) {
    -
    7219 if (isspace(text[this->interval.end]))
    -
    7220 this->interval.end++;
    -
    7221 else {
    -
    7222 if (value.start == (size_t)-1) value.start = this->interval.end;
    -
    7223 value.end = ++this->interval.end;
    -
    7224 }
    -
    7225 }
    -
    7226 else
    -
    7227 break;
    -
    7228 }
    -
    7229 this->interval.start = start;
    -
    7230 return true;
    -
    7231
    -
    7232 error:
    -
    7233 name.start = 1;
    -
    7234 name.end = 0;
    -
    7235 value.start = 1;
    -
    7236 value.end = 0;
    -
    7237 this->interval.start = 1;
    -
    7238 this->interval.end = 0;
    -
    7239 return false;
    -
    7240 }
    -
    7241
    -
    7242 virtual void invalidate()
    -
    7243 {
    -
    7244 name.start = 1;
    -
    7245 name.end = 0;
    -
    7246 value.start = 1;
    -
    7247 value.end = 0;
    -
    7248 parser::invalidate();
    -
    7249 }
    -
    7250
    -
    7251 public:
    - - -
    7254
    -
    7255 protected:
    -
    7256 http_line_break m_line_break;
    -
    7257 };
    +
    7146
    +
    +
    7150 class http_header : public parser
    +
    7151 {
    +
    7152 public:
    +
    7153 virtual bool match(
    +
    7154 _In_reads_or_z_(end) const char* text,
    +
    7155 _In_ size_t start = 0,
    +
    7156 _In_ size_t end = (size_t)-1,
    +
    7157 _In_ int flags = match_default)
    +
    7158 {
    +
    7159 _Assume_(text || start >= end);
    +
    7160 this->interval.end = start;
    +
    7161
    +
    7162 if (m_line_break.match(text, this->interval.end, end, flags) ||
    +
    7163 (this->interval.end < end && text[this->interval.end] && isspace(text[this->interval.end])))
    +
    7164 goto error;
    +
    7165 name.start = this->interval.end;
    +
    7166 for (;;) {
    +
    7167 if (m_line_break.match(text, this->interval.end, end, flags))
    +
    7168 goto error;
    +
    7169 else if (this->interval.end < end && text[this->interval.end]) {
    +
    7170 if (isspace(text[this->interval.end])) {
    +
    7171 name.end = this->interval.end;
    +
    7172 this->interval.end++;
    +
    7173 for (;;) {
    +
    7174 if (m_line_break.match(text, this->interval.end, end, flags))
    +
    7175 goto error;
    +
    7176 else if (this->interval.end < end && text[this->interval.end]) {
    +
    7177 if (isspace(text[this->interval.end]))
    +
    7178 this->interval.end++;
    +
    7179 else
    +
    7180 break;
    +
    7181 }
    +
    7182 else
    +
    7183 goto error;
    +
    7184 }
    +
    7185 if (this->interval.end < end && text[this->interval.end] == ':') {
    +
    7186 this->interval.end++;
    +
    7187 break;
    +
    7188 }
    +
    7189 else
    +
    7190 goto error;
    +
    7191 break;
    +
    7192 }
    +
    7193 else if (text[this->interval.end] == ':') {
    +
    7194 name.end = this->interval.end;
    +
    7195 this->interval.end++;
    +
    7196 break;
    +
    7197 }
    +
    7198 else
    +
    7199 this->interval.end++;
    +
    7200 }
    +
    7201 else
    +
    7202 goto error;
    +
    7203 }
    +
    7204 value.start = (size_t)-1;
    +
    7205 value.end = 0;
    +
    7206 for (;;) {
    +
    7207 if (m_line_break.match(text, this->interval.end, end, flags)) {
    +
    7208 this->interval.end = m_line_break.interval.end;
    +
    7209 if (!m_line_break.match(text, this->interval.end, end, flags) &&
    +
    7210 this->interval.end < end && text[this->interval.end] && isspace(text[this->interval.end]))
    +
    7211 this->interval.end++;
    +
    7212 else
    +
    7213 break;
    +
    7214 }
    +
    7215 else if (this->interval.end < end && text[this->interval.end]) {
    +
    7216 if (isspace(text[this->interval.end]))
    +
    7217 this->interval.end++;
    +
    7218 else {
    +
    7219 if (value.start == (size_t)-1) value.start = this->interval.end;
    +
    7220 value.end = ++this->interval.end;
    +
    7221 }
    +
    7222 }
    +
    7223 else
    +
    7224 break;
    +
    7225 }
    +
    7226 this->interval.start = start;
    +
    7227 return true;
    +
    7228
    +
    7229 error:
    +
    7230 name.start = 1;
    +
    7231 name.end = 0;
    +
    7232 value.start = 1;
    +
    7233 value.end = 0;
    +
    7234 this->interval.start = 1;
    +
    7235 this->interval.end = 0;
    +
    7236 return false;
    +
    7237 }
    +
    7238
    +
    7239 virtual void invalidate()
    +
    7240 {
    +
    7241 name.start = 1;
    +
    7242 name.end = 0;
    +
    7243 value.start = 1;
    +
    7244 value.end = 0;
    +
    7245 parser::invalidate();
    +
    7246 }
    +
    7247
    +
    7248 public:
    + + +
    7251
    +
    7252 protected:
    +
    7253 http_line_break m_line_break;
    +
    7254 };
    -
    7258
    -
    7262 template <class _Key, class T>
    -
    -
    7263 class http_value_collection : public T
    -
    7264 {
    -
    7265 public:
    -
    7266 void insert(
    -
    7267 _In_reads_or_z_(end) const char* text,
    -
    7268 _In_ size_t start = 0,
    -
    7269 _In_ size_t end = (size_t)-1,
    -
    7270 _In_ int flags = match_default)
    -
    7271 {
    -
    7272 while (start < end) {
    -
    7273 while (start < end && text[start] && isspace(text[start])) start++;
    -
    7274 if (start < end && text[start] == ',') {
    -
    7275 start++;
    -
    7276 while (start < end&& text[start] && isspace(text[start])) start++;
    -
    7277 }
    -
    7278 _Key el;
    -
    7279 if (el.match(text, start, end, flags)) {
    -
    7280 start = el.interval.end;
    -
    7281 T::insert(std::move(el));
    -
    7282 }
    -
    7283 else
    -
    7284 break;
    -
    7285 }
    -
    7286 }
    -
    7287 };
    +
    7255
    +
    7259 template <class _Key, class T>
    +
    +
    7260 class http_value_collection : public T
    +
    7261 {
    +
    7262 public:
    +
    7263 void insert(
    +
    7264 _In_reads_or_z_(end) const char* text,
    +
    7265 _In_ size_t start = 0,
    +
    7266 _In_ size_t end = (size_t)-1,
    +
    7267 _In_ int flags = match_default)
    +
    7268 {
    +
    7269 while (start < end) {
    +
    7270 while (start < end && text[start] && isspace(text[start])) start++;
    +
    7271 if (start < end && text[start] == ',') {
    +
    7272 start++;
    +
    7273 while (start < end&& text[start] && isspace(text[start])) start++;
    +
    7274 }
    +
    7275 _Key el;
    +
    7276 if (el.match(text, start, end, flags)) {
    +
    7277 start = el.interval.end;
    +
    7278 T::insert(std::move(el));
    +
    7279 }
    +
    7280 else
    +
    7281 break;
    +
    7282 }
    +
    7283 }
    +
    7284 };
    -
    7288
    -
    7289 template <class T>
    -
    - -
    7291 constexpr bool operator()(const T& a, const T& b) const noexcept
    -
    7292 {
    -
    7293 return a.factor.value > b.factor.value;
    -
    7294 }
    -
    7295 };
    +
    7285
    +
    7286 template <class T>
    +
    + +
    7288 constexpr bool operator()(const T& a, const T& b) const noexcept
    +
    7289 {
    +
    7290 return a.factor.value > b.factor.value;
    +
    7291 }
    +
    7292 };
    -
    7296
    -
    7300 template <class T, class _Alloc = std::allocator<T>>
    - -
    7302
    -
    7306 template <class T>
    -
    - -
    7308 {
    -
    7309 public:
    - -
    7311 _In_ const std::shared_ptr<basic_parser<T>>& quote,
    -
    7312 _In_ const std::shared_ptr<basic_parser<T>>& chr,
    -
    7313 _In_ const std::shared_ptr<basic_parser<T>>& escape,
    -
    7314 _In_ const std::shared_ptr<basic_parser<T>>& sol,
    -
    7315 _In_ const std::shared_ptr<basic_parser<T>>& bs,
    -
    7316 _In_ const std::shared_ptr<basic_parser<T>>& ff,
    -
    7317 _In_ const std::shared_ptr<basic_parser<T>>& lf,
    -
    7318 _In_ const std::shared_ptr<basic_parser<T>>& cr,
    -
    7319 _In_ const std::shared_ptr<basic_parser<T>>& htab,
    -
    7320 _In_ const std::shared_ptr<basic_parser<T>>& uni,
    -
    7321 _In_ const std::shared_ptr<basic_integer16<T>>& hex,
    -
    7322 _In_ const std::locale& locale = std::locale()) :
    -
    7323 basic_parser<T>(locale),
    -
    7324 m_quote(quote),
    -
    7325 m_chr(chr),
    -
    7326 m_escape(escape),
    -
    7327 m_sol(sol),
    -
    7328 m_bs(bs),
    -
    7329 m_ff(ff),
    -
    7330 m_lf(lf),
    -
    7331 m_cr(cr),
    -
    7332 m_htab(htab),
    -
    7333 m_uni(uni),
    -
    7334 m_hex(hex)
    -
    7335 {}
    -
    7336
    -
    7337 virtual bool match(
    -
    7338 _In_reads_or_z_(end) const T* text,
    -
    7339 _In_ size_t start = 0,
    -
    7340 _In_ size_t end = (size_t)-1,
    -
    7341 _In_ int flags = match_default)
    -
    7342 {
    -
    7343 _Assume_(text || start >= end);
    -
    7344 this->interval.end = start;
    -
    7345 if (m_quote->match(text, this->interval.end, end, flags)) {
    -
    7346 this->interval.end = m_quote->interval.end;
    -
    7347 value.clear();
    -
    7348 for (;;) {
    -
    7349 if (m_quote->match(text, this->interval.end, end, flags)) {
    -
    7350 this->interval.start = start;
    -
    7351 this->interval.end = m_quote->interval.end;
    -
    7352 return true;
    -
    7353 }
    -
    7354 if (m_escape->match(text, this->interval.end, end, flags)) {
    -
    7355 if (m_quote->match(text, m_escape->interval.end, end, flags)) {
    -
    7356 value += '"'; this->interval.end = m_quote->interval.end;
    -
    7357 continue;
    -
    7358 }
    -
    7359 if (m_sol->match(text, m_escape->interval.end, end, flags)) {
    -
    7360 value += '/'; this->interval.end = m_sol->interval.end;
    -
    7361 continue;
    -
    7362 }
    -
    7363 if (m_bs->match(text, m_escape->interval.end, end, flags)) {
    -
    7364 value += '\b'; this->interval.end = m_bs->interval.end;
    -
    7365 continue;
    -
    7366 }
    -
    7367 if (m_ff->match(text, m_escape->interval.end, end, flags)) {
    -
    7368 value += '\f'; this->interval.end = m_ff->interval.end;
    -
    7369 continue;
    -
    7370 }
    -
    7371 if (m_lf->match(text, m_escape->interval.end, end, flags)) {
    -
    7372 value += '\n'; this->interval.end = m_lf->interval.end;
    -
    7373 continue;
    -
    7374 }
    -
    7375 if (m_cr->match(text, m_escape->interval.end, end, flags)) {
    -
    7376 value += '\r'; this->interval.end = m_cr->interval.end;
    -
    7377 continue;
    -
    7378 }
    -
    7379 if (m_htab->match(text, m_escape->interval.end, end, flags)) {
    -
    7380 value += '\t'; this->interval.end = m_htab->interval.end;
    -
    7381 continue;
    -
    7382 }
    -
    7383 if (
    -
    7384 m_uni->match(text, m_escape->interval.end, end, flags) &&
    -
    7385 m_hex->match(text, m_uni->interval.end, std::min(m_uni->interval.end + 4, end), flags | match_case_insensitive) &&
    -
    7386 m_hex->interval.size() == 4 /* JSON requests 4-digit Unicode sequneces: \u.... */)
    -
    7387 {
    -
    7388 _Assume_(m_hex->value <= 0xffff);
    -
    7389 if (sizeof(T) == 1) {
    -
    7390 if (m_hex->value > 0x7ff) {
    -
    7391 value += (T)(0xe0 | ((m_hex->value >> 12) & 0x0f));
    -
    7392 value += (T)(0x80 | ((m_hex->value >> 6) & 0x3f));
    -
    7393 value += (T)(0x80 | (m_hex->value & 0x3f));
    -
    7394 }
    -
    7395 else if (m_hex->value > 0x7f) {
    -
    7396 value += (T)(0xc0 | ((m_hex->value >> 6) & 0x1f));
    -
    7397 value += (T)(0x80 | (m_hex->value & 0x3f));
    -
    7398 }
    -
    7399 else
    -
    7400 value += (T)(m_hex->value & 0x7f);
    -
    7401 }
    -
    7402 else
    -
    7403 value += (T)m_hex->value;
    -
    7404 this->interval.end = m_hex->interval.end;
    -
    7405 continue;
    -
    7406 }
    -
    7407 if (m_escape->match(text, m_escape->interval.end, end, flags)) {
    -
    7408 value += '\\'; this->interval.end = m_escape->interval.end;
    -
    7409 continue;
    -
    7410 }
    -
    7411 }
    -
    7412 if (m_chr->match(text, this->interval.end, end, flags)) {
    -
    7413 value.Prilepi(text + m_chr->interval.start, m_chr->interval.size());
    -
    7414 this->interval.end = m_chr->interval.end;
    -
    7415 continue;
    -
    7416 }
    -
    7417 break;
    -
    7418 }
    -
    7419 }
    -
    7420 value.clear();
    -
    7421 this->interval.start = (this->interval.end = start) + 1;
    -
    7422 return false;
    -
    7423 }
    -
    7424
    -
    7425 virtual void invalidate()
    -
    7426 {
    -
    7427 value.clear();
    - -
    7429 }
    +
    7293
    +
    7297 template <class T, class _Alloc = std::allocator<T>>
    + +
    7299
    +
    7303 template <class T>
    +
    + +
    7305 {
    +
    7306 public:
    + +
    7308 _In_ const std::shared_ptr<basic_parser<T>>& quote,
    +
    7309 _In_ const std::shared_ptr<basic_parser<T>>& chr,
    +
    7310 _In_ const std::shared_ptr<basic_parser<T>>& escape,
    +
    7311 _In_ const std::shared_ptr<basic_parser<T>>& sol,
    +
    7312 _In_ const std::shared_ptr<basic_parser<T>>& bs,
    +
    7313 _In_ const std::shared_ptr<basic_parser<T>>& ff,
    +
    7314 _In_ const std::shared_ptr<basic_parser<T>>& lf,
    +
    7315 _In_ const std::shared_ptr<basic_parser<T>>& cr,
    +
    7316 _In_ const std::shared_ptr<basic_parser<T>>& htab,
    +
    7317 _In_ const std::shared_ptr<basic_parser<T>>& uni,
    +
    7318 _In_ const std::shared_ptr<basic_integer16<T>>& hex,
    +
    7319 _In_ const std::locale& locale = std::locale()) :
    +
    7320 basic_parser<T>(locale),
    +
    7321 m_quote(quote),
    +
    7322 m_chr(chr),
    +
    7323 m_escape(escape),
    +
    7324 m_sol(sol),
    +
    7325 m_bs(bs),
    +
    7326 m_ff(ff),
    +
    7327 m_lf(lf),
    +
    7328 m_cr(cr),
    +
    7329 m_htab(htab),
    +
    7330 m_uni(uni),
    +
    7331 m_hex(hex)
    +
    7332 {}
    +
    7333
    +
    7334 virtual bool match(
    +
    7335 _In_reads_or_z_(end) const T* text,
    +
    7336 _In_ size_t start = 0,
    +
    7337 _In_ size_t end = (size_t)-1,
    +
    7338 _In_ int flags = match_default)
    +
    7339 {
    +
    7340 _Assume_(text || start >= end);
    +
    7341 this->interval.end = start;
    +
    7342 if (m_quote->match(text, this->interval.end, end, flags)) {
    +
    7343 this->interval.end = m_quote->interval.end;
    +
    7344 value.clear();
    +
    7345 for (;;) {
    +
    7346 if (m_quote->match(text, this->interval.end, end, flags)) {
    +
    7347 this->interval.start = start;
    +
    7348 this->interval.end = m_quote->interval.end;
    +
    7349 return true;
    +
    7350 }
    +
    7351 if (m_escape->match(text, this->interval.end, end, flags)) {
    +
    7352 if (m_quote->match(text, m_escape->interval.end, end, flags)) {
    +
    7353 value += '"'; this->interval.end = m_quote->interval.end;
    +
    7354 continue;
    +
    7355 }
    +
    7356 if (m_sol->match(text, m_escape->interval.end, end, flags)) {
    +
    7357 value += '/'; this->interval.end = m_sol->interval.end;
    +
    7358 continue;
    +
    7359 }
    +
    7360 if (m_bs->match(text, m_escape->interval.end, end, flags)) {
    +
    7361 value += '\b'; this->interval.end = m_bs->interval.end;
    +
    7362 continue;
    +
    7363 }
    +
    7364 if (m_ff->match(text, m_escape->interval.end, end, flags)) {
    +
    7365 value += '\f'; this->interval.end = m_ff->interval.end;
    +
    7366 continue;
    +
    7367 }
    +
    7368 if (m_lf->match(text, m_escape->interval.end, end, flags)) {
    +
    7369 value += '\n'; this->interval.end = m_lf->interval.end;
    +
    7370 continue;
    +
    7371 }
    +
    7372 if (m_cr->match(text, m_escape->interval.end, end, flags)) {
    +
    7373 value += '\r'; this->interval.end = m_cr->interval.end;
    +
    7374 continue;
    +
    7375 }
    +
    7376 if (m_htab->match(text, m_escape->interval.end, end, flags)) {
    +
    7377 value += '\t'; this->interval.end = m_htab->interval.end;
    +
    7378 continue;
    +
    7379 }
    +
    7380 if (
    +
    7381 m_uni->match(text, m_escape->interval.end, end, flags) &&
    +
    7382 m_hex->match(text, m_uni->interval.end, std::min(m_uni->interval.end + 4, end), flags | match_case_insensitive) &&
    +
    7383 m_hex->interval.size() == 4 /* JSON requests 4-digit Unicode sequneces: \u.... */)
    +
    7384 {
    +
    7385 _Assume_(m_hex->value <= 0xffff);
    +
    7386 if (sizeof(T) == 1) {
    +
    7387 if (m_hex->value > 0x7ff) {
    +
    7388 value += (T)(0xe0 | ((m_hex->value >> 12) & 0x0f));
    +
    7389 value += (T)(0x80 | ((m_hex->value >> 6) & 0x3f));
    +
    7390 value += (T)(0x80 | (m_hex->value & 0x3f));
    +
    7391 }
    +
    7392 else if (m_hex->value > 0x7f) {
    +
    7393 value += (T)(0xc0 | ((m_hex->value >> 6) & 0x1f));
    +
    7394 value += (T)(0x80 | (m_hex->value & 0x3f));
    +
    7395 }
    +
    7396 else
    +
    7397 value += (T)(m_hex->value & 0x7f);
    +
    7398 }
    +
    7399 else
    +
    7400 value += (T)m_hex->value;
    +
    7401 this->interval.end = m_hex->interval.end;
    +
    7402 continue;
    +
    7403 }
    +
    7404 if (m_escape->match(text, m_escape->interval.end, end, flags)) {
    +
    7405 value += '\\'; this->interval.end = m_escape->interval.end;
    +
    7406 continue;
    +
    7407 }
    +
    7408 }
    +
    7409 if (m_chr->match(text, this->interval.end, end, flags)) {
    +
    7410 value.Prilepi(text + m_chr->interval.start, m_chr->interval.size());
    +
    7411 this->interval.end = m_chr->interval.end;
    +
    7412 continue;
    +
    7413 }
    +
    7414 break;
    +
    7415 }
    +
    7416 }
    +
    7417 value.clear();
    +
    7418 this->interval.start = (this->interval.end = start) + 1;
    +
    7419 return false;
    +
    7420 }
    +
    7421
    +
    7422 virtual void invalidate()
    +
    7423 {
    +
    7424 value.clear();
    + +
    7426 }
    +
    7427
    +
    7428 public:
    +
    7429 std::basic_string<T> value;
    7430
    -
    7431 public:
    -
    7432 std::basic_string<T> value;
    -
    7433
    -
    7434 protected:
    -
    7435 std::shared_ptr<basic_parser<T>> m_quote;
    -
    7436 std::shared_ptr<basic_parser<T>> m_chr;
    -
    7437 std::shared_ptr<basic_parser<T>> m_escape;
    -
    7438 std::shared_ptr<basic_parser<T>> m_sol;
    -
    7439 std::shared_ptr<basic_parser<T>> m_bs;
    -
    7440 std::shared_ptr<basic_parser<T>> m_ff;
    -
    7441 std::shared_ptr<basic_parser<T>> m_lf;
    -
    7442 std::shared_ptr<basic_parser<T>> m_cr;
    -
    7443 std::shared_ptr<basic_parser<T>> m_htab;
    -
    7444 std::shared_ptr<basic_parser<T>> m_uni;
    -
    7445 std::shared_ptr<basic_integer16<T>> m_hex;
    -
    7446 };
    +
    7431 protected:
    +
    7432 std::shared_ptr<basic_parser<T>> m_quote;
    +
    7433 std::shared_ptr<basic_parser<T>> m_chr;
    +
    7434 std::shared_ptr<basic_parser<T>> m_escape;
    +
    7435 std::shared_ptr<basic_parser<T>> m_sol;
    +
    7436 std::shared_ptr<basic_parser<T>> m_bs;
    +
    7437 std::shared_ptr<basic_parser<T>> m_ff;
    +
    7438 std::shared_ptr<basic_parser<T>> m_lf;
    +
    7439 std::shared_ptr<basic_parser<T>> m_cr;
    +
    7440 std::shared_ptr<basic_parser<T>> m_htab;
    +
    7441 std::shared_ptr<basic_parser<T>> m_uni;
    +
    7442 std::shared_ptr<basic_integer16<T>> m_hex;
    +
    7443 };
    -
    7447
    - - -
    7450#ifdef _UNICODE
    -
    7451 using tjson_string = wjson_string;
    -
    7452#else
    -
    7453 using tjson_string = json_string;
    -
    7454#endif
    -
    7455 }
    -
    7456}
    +
    7444
    + + +
    7447#ifdef _UNICODE
    +
    7448 using tjson_string = wjson_string;
    +
    7449#else
    +
    7450 using tjson_string = json_string;
    +
    7451#endif
    +
    7452 }
    +
    7453}
    +
    7454
    +
    7455#undef ENUM_FLAG_OPERATOR
    +
    7456#undef ENUM_FLAGS
    7457
    -
    7458#undef ENUM_FLAG_OPERATOR
    -
    7459#undef ENUM_FLAGS
    -
    7460
    -
    7461#ifdef _MSC_VER
    -
    7462#pragma warning(pop)
    -
    7463#endif
    -
    Test for angle in d°mm'ss.dddd form.
    Definition parser.hpp:4402
    -
    Test for any code unit.
    Definition parser.hpp:228
    -
    Test for beginning of line.
    Definition parser.hpp:622
    -
    Test for any.
    Definition parser.hpp:1064
    -
    Test for chemical formula.
    Definition parser.hpp:5546
    -
    Test for Creditor Reference.
    Definition parser.hpp:4972
    -
    T reference[22]
    Normalized national reference number.
    Definition parser.hpp:5101
    -
    T check_digits[3]
    Two check digits.
    Definition parser.hpp:5100
    -
    bool is_valid
    Is reference valid per ISO 7064.
    Definition parser.hpp:5102
    -
    Test for any code unit from a given string of code units.
    Definition parser.hpp:727
    -
    Test for specific code unit.
    Definition parser.hpp:298
    -
    Test for date.
    Definition parser.hpp:4032
    -
    Test for valid DNS domain character.
    Definition parser.hpp:2813
    -
    bool allow_on_edge
    Is character allowed at the beginning or an end of a DNS domain?
    Definition parser.hpp:2851
    -
    Test for DNS domain/hostname.
    Definition parser.hpp:2913
    -
    bool m_allow_absolute
    May DNS names end with a dot (absolute name)?
    Definition parser.hpp:2977
    -
    Test for e-mail address.
    Definition parser.hpp:3801
    -
    Test for emoticon.
    Definition parser.hpp:3909
    -
    std::shared_ptr< basic_parser< T > > apex
    apex/eyebrows/halo (e.g. O, 0)
    Definition parser.hpp:3998
    -
    std::shared_ptr< basic_parser< T > > eyes
    eyes (e.g. :, ;, >, |, B)
    Definition parser.hpp:3999
    -
    std::shared_ptr< basic_set< T > > mouth
    mouth (e.g. ), ), (, (, |, P, D, p, d)
    Definition parser.hpp:4001
    -
    std::shared_ptr< basic_parser< T > > nose
    nose (e.g. -, o)
    Definition parser.hpp:4000
    -
    std::shared_ptr< basic_parser< T > > emoticon
    emoticon as a whole (e.g. 😀, 🤔, 😶)
    Definition parser.hpp:3997
    -
    Test for end of line.
    Definition parser.hpp:660
    -
    Test for fraction.
    Definition parser.hpp:1693
    -
    Test for International Bank Account Number.
    Definition parser.hpp:4678
    -
    T bban[31]
    Normalized Basic Bank Account Number.
    Definition parser.hpp:4949
    -
    T country[3]
    ISO 3166-1 alpha-2 country code.
    Definition parser.hpp:4947
    -
    T check_digits[3]
    Two check digits.
    Definition parser.hpp:4948
    -
    bool is_valid
    Is IBAN valid per ISO 7064.
    Definition parser.hpp:4950
    -
    Test for decimal integer.
    Definition parser.hpp:1302
    -
    Test for decimal integer possibly containing thousand separators.
    Definition parser.hpp:1387
    -
    bool has_separators
    Did integer have any separators?
    Definition parser.hpp:1447
    -
    size_t digit_count
    Total number of digits in integer.
    Definition parser.hpp:1446
    -
    Test for hexadecimal integer.
    Definition parser.hpp:1468
    -
    Base class for integer testing.
    Definition parser.hpp:1280
    -
    size_t value
    Calculated value of the numeral.
    Definition parser.hpp:1294
    -
    Test for IPv4 address.
    Definition parser.hpp:2353
    -
    stdex::interval< size_t > components[4]
    Individual component intervals.
    Definition parser.hpp:2468
    -
    struct in_addr value
    IPv4 address value.
    Definition parser.hpp:2469
    -
    Test for IPv6 address.
    Definition parser.hpp:2572
    -
    std::shared_ptr< basic_parser< T > > scope_id
    Scope ID (e.g. NIC index with link-local addresses)
    Definition parser.hpp:2776
    -
    stdex::interval< size_t > components[8]
    Individual component intervals.
    Definition parser.hpp:2774
    -
    struct in6_addr value
    IPv6 address value.
    Definition parser.hpp:2775
    -
    Test for valid IPv6 address scope ID character.
    Definition parser.hpp:2500
    -
    Test for repeating.
    Definition parser.hpp:917
    -
    bool m_greedy
    try to match as long sequence as possible
    Definition parser.hpp:956
    -
    std::shared_ptr< basic_parser< T > > m_el
    repeating element
    Definition parser.hpp:953
    -
    size_t m_min_iterations
    minimum number of iterations
    Definition parser.hpp:954
    -
    size_t m_max_iterations
    maximum number of iterations
    Definition parser.hpp:955
    -
    Test for JSON string.
    Definition parser.hpp:7308
    -
    Test for mixed numeral.
    Definition parser.hpp:1929
    -
    std::shared_ptr< basic_parser< T > > fraction
    fraction
    Definition parser.hpp:2035
    -
    std::shared_ptr< basic_parser< T > > special_sign
    Special sign (e.g. plus-minus '±')
    Definition parser.hpp:2033
    -
    std::shared_ptr< basic_parser< T > > negative_sign
    Negative sign.
    Definition parser.hpp:2032
    -
    std::shared_ptr< basic_parser< T > > positive_sign
    Positive sign.
    Definition parser.hpp:2031
    -
    std::shared_ptr< basic_parser< T > > integer
    Integer part.
    Definition parser.hpp:2034
    -
    Test for monetary numeral.
    Definition parser.hpp:2224
    -
    std::shared_ptr< basic_parser< T > > positive_sign
    Positive sign.
    Definition parser.hpp:2330
    -
    std::shared_ptr< basic_parser< T > > decimal_separator
    Decimal separator.
    Definition parser.hpp:2335
    -
    std::shared_ptr< basic_parser< T > > currency
    Currency part.
    Definition parser.hpp:2333
    -
    std::shared_ptr< basic_parser< T > > decimal
    Decimal part.
    Definition parser.hpp:2336
    -
    std::shared_ptr< basic_parser< T > > integer
    Integer part.
    Definition parser.hpp:2334
    -
    std::shared_ptr< basic_parser< T > > negative_sign
    Negative sign.
    Definition parser.hpp:2331
    -
    std::shared_ptr< basic_parser< T > > special_sign
    Special sign (e.g. plus-minus '±')
    Definition parser.hpp:2332
    -
    "No-op" match
    Definition parser.hpp:196
    -
    Base template for all parsers.
    Definition parser.hpp:77
    -
    interval< size_t > interval
    Region of the last match.
    Definition parser.hpp:176
    -
    Test for permutation.
    Definition parser.hpp:1204
    -
    Test for phone number.
    Definition parser.hpp:4525
    -
    std::basic_string< T > value
    Normalized phone number.
    Definition parser.hpp:4651
    -
    Test for any punctuation code unit.
    Definition parser.hpp:470
    -
    Test for Roman numeral.
    Definition parser.hpp:1577
    -
    Test for scientific numeral.
    Definition parser.hpp:2055
    -
    std::shared_ptr< basic_parser< T > > special_sign
    Special sign (e.g. plus-minus '±')
    Definition parser.hpp:2199
    -
    std::shared_ptr< basic_parser< T > > exponent_symbol
    Exponent symbol (e.g. 'e')
    Definition parser.hpp:2203
    -
    std::shared_ptr< basic_parser< T > > positive_sign
    Positive sign.
    Definition parser.hpp:2197
    -
    std::shared_ptr< basic_parser< T > > negative_sign
    Negative sign.
    Definition parser.hpp:2198
    -
    double value
    Calculated value of the numeral.
    Definition parser.hpp:2207
    -
    std::shared_ptr< basic_parser< T > > negative_exp_sign
    Negative exponent sign (e.g. '-')
    Definition parser.hpp:2205
    -
    std::shared_ptr< basic_integer< T > > decimal
    Decimal part.
    Definition parser.hpp:2202
    -
    std::shared_ptr< basic_parser< T > > positive_exp_sign
    Positive exponent sign (e.g. '+')
    Definition parser.hpp:2204
    -
    std::shared_ptr< basic_integer< T > > exponent
    Exponent part.
    Definition parser.hpp:2206
    -
    std::shared_ptr< basic_parser< T > > decimal_separator
    Decimal separator.
    Definition parser.hpp:2201
    -
    std::shared_ptr< basic_integer< T > > integer
    Integer part.
    Definition parser.hpp:2200
    -
    Test for match score.
    Definition parser.hpp:1756
    -
    Test for sequence.
    Definition parser.hpp:1013
    -
    Definition parser.hpp:695
    -
    Test for SI Reference delimiter.
    Definition parser.hpp:5169
    -
    Test for SI Reference part.
    Definition parser.hpp:5124
    -
    Test for SI Reference.
    Definition parser.hpp:5207
    -
    basic_si_reference_part< T > part3
    Reference data part 3 (P3)
    Definition parser.hpp:5524
    -
    basic_si_reference_part< T > part1
    Reference data part 1 (P1)
    Definition parser.hpp:5522
    -
    bool is_valid
    Is reference valid.
    Definition parser.hpp:5525
    -
    T model[3]
    Reference model.
    Definition parser.hpp:5521
    -
    basic_si_reference_part< T > part2
    Reference data part 2 (P2)
    Definition parser.hpp:5523
    -
    Test for signed numeral.
    Definition parser.hpp:1843
    -
    std::shared_ptr< basic_parser< T > > special_sign
    Special sign (e.g. plus-minus '±')
    Definition parser.hpp:1911
    -
    std::shared_ptr< basic_parser< T > > negative_sign
    Negative sign.
    Definition parser.hpp:1910
    -
    std::shared_ptr< basic_parser< T > > positive_sign
    Positive sign.
    Definition parser.hpp:1909
    -
    std::shared_ptr< basic_parser< T > > number
    Number.
    Definition parser.hpp:1912
    -
    Test for any space code unit.
    Definition parser.hpp:391
    -
    Test for any space or punctuation code unit.
    Definition parser.hpp:544
    -
    Test for any string.
    Definition parser.hpp:1132
    -
    Test for given string.
    Definition parser.hpp:822
    -
    Test for time.
    Definition parser.hpp:4299
    -
    Test for valid URL password character.
    Definition parser.hpp:3095
    -
    Test for valid URL path character.
    Definition parser.hpp:3195
    -
    Test for URL path.
    Definition parser.hpp:3303
    -
    Test for valid URL username character.
    Definition parser.hpp:2996
    -
    Test for URL.
    Definition parser.hpp:3444
    -
    Test for HTTP agent.
    Definition parser.hpp:6831
    -
    Test for HTTP any type.
    Definition parser.hpp:5953
    -
    Test for HTTP asterisk.
    Definition parser.hpp:6595
    - - - - - -
    Test for HTTP header.
    Definition parser.hpp:7154
    -
    Test for HTTP language (RFC1766)
    Definition parser.hpp:6463
    -
    Test for HTTP line break (RFC2616: CRLF | LF)
    Definition parser.hpp:5627
    -
    Test for HTTP media range (RFC2616: media-range)
    Definition parser.hpp:5985
    -
    Test for HTTP media type (RFC2616: media-type)
    Definition parser.hpp:6040
    -
    Test for HTTP parameter (RFC2616: parameter)
    Definition parser.hpp:5898
    -
    http_token name
    Parameter name.
    Definition parser.hpp:5942
    -
    http_value value
    Parameter value.
    Definition parser.hpp:5943
    -
    Test for HTTP protocol.
    Definition parser.hpp:6907
    -
    uint16_t version
    HTTP protocol version: 0x100 = 1.0, 0x101 = 1.1...
    Definition parser.hpp:7009
    -
    Test for HTTP quoted string (RFC2616: quoted-string)
    Definition parser.hpp:5788
    -
    stdex::interval< size_t > content
    String content (without quotes)
    Definition parser.hpp:5844
    -
    Test for HTTP request.
    Definition parser.hpp:7016
    -
    Test for HTTP space (RFC2616: LWS)
    Definition parser.hpp:5663
    -
    Test for HTTP text character (RFC2616: TEXT)
    Definition parser.hpp:5700
    -
    Test for HTTP token (RFC2616: token - tolerates non-ASCII)
    Definition parser.hpp:5734
    -
    Test for HTTP URL parameter.
    Definition parser.hpp:6280
    -
    Test for HTTP URL path segment.
    Definition parser.hpp:6191
    -
    Test for HTTP URL path segment.
    Definition parser.hpp:6224
    -
    std::vector< http_url_path_segment > segments
    Path segments.
    Definition parser.hpp:6273
    -
    Test for HTTP URL port.
    Definition parser.hpp:6135
    -
    Test for HTTP URL server.
    Definition parser.hpp:6098
    -
    Test for HTTP URL.
    Definition parser.hpp:6361
    -
    Collection of HTTP values.
    Definition parser.hpp:7264
    -
    Test for HTTP value (RFC2616: value)
    Definition parser.hpp:5854
    -
    http_quoted_string string
    Value when matched as quoted string.
    Definition parser.hpp:5890
    -
    http_token token
    Value when matched as token.
    Definition parser.hpp:5891
    -
    Test for HTTP weight factor.
    Definition parser.hpp:6526
    -
    float value
    Calculated value of the weight factor.
    Definition parser.hpp:6588
    -
    Test for HTTP weighted value.
    Definition parser.hpp:6618
    -
    Base template for collection-holding parsers.
    Definition parser.hpp:973
    -
    Test for any SGML code point.
    Definition parser.hpp:260
    -
    Test for any SGML code point from a given string of SGML code points.
    Definition parser.hpp:779
    -
    Test for specific SGML code point.
    Definition parser.hpp:347
    -
    Test for valid DNS domain SGML character.
    Definition parser.hpp:2869
    -
    Test for valid IPv6 address scope ID SGML character.
    Definition parser.hpp:2538
    -
    Test for any SGML punctuation code point.
    Definition parser.hpp:511
    -
    Test for any SGML space code point.
    Definition parser.hpp:434
    -
    Test for any SGML space or punctuation code point.
    Definition parser.hpp:587
    -
    Test for SGML given string.
    Definition parser.hpp:869
    -
    Test for valid URL password SGML character.
    Definition parser.hpp:3147
    -
    Test for valid URL path SGML character.
    Definition parser.hpp:3251
    -
    Test for valid URL username SGML character.
    Definition parser.hpp:3047
    +
    7458#ifdef _MSC_VER
    +
    7459#pragma warning(pop)
    +
    7460#endif
    +
    Test for angle in d°mm'ss.dddd form.
    Definition parser.hpp:4399
    +
    Test for any code unit.
    Definition parser.hpp:225
    +
    Test for beginning of line.
    Definition parser.hpp:619
    +
    Test for any.
    Definition parser.hpp:1061
    +
    Test for chemical formula.
    Definition parser.hpp:5543
    +
    Test for Creditor Reference.
    Definition parser.hpp:4969
    +
    T reference[22]
    Normalized national reference number.
    Definition parser.hpp:5098
    +
    T check_digits[3]
    Two check digits.
    Definition parser.hpp:5097
    +
    bool is_valid
    Is reference valid per ISO 7064.
    Definition parser.hpp:5099
    +
    Test for any code unit from a given string of code units.
    Definition parser.hpp:724
    +
    Test for specific code unit.
    Definition parser.hpp:295
    +
    Test for date.
    Definition parser.hpp:4029
    +
    Test for valid DNS domain character.
    Definition parser.hpp:2810
    +
    bool allow_on_edge
    Is character allowed at the beginning or an end of a DNS domain?
    Definition parser.hpp:2848
    +
    Test for DNS domain/hostname.
    Definition parser.hpp:2910
    +
    bool m_allow_absolute
    May DNS names end with a dot (absolute name)?
    Definition parser.hpp:2974
    +
    Test for e-mail address.
    Definition parser.hpp:3798
    +
    Test for emoticon.
    Definition parser.hpp:3906
    +
    std::shared_ptr< basic_parser< T > > apex
    apex/eyebrows/halo (e.g. O, 0)
    Definition parser.hpp:3995
    +
    std::shared_ptr< basic_parser< T > > eyes
    eyes (e.g. :, ;, >, |, B)
    Definition parser.hpp:3996
    +
    std::shared_ptr< basic_set< T > > mouth
    mouth (e.g. ), ), (, (, |, P, D, p, d)
    Definition parser.hpp:3998
    +
    std::shared_ptr< basic_parser< T > > nose
    nose (e.g. -, o)
    Definition parser.hpp:3997
    +
    std::shared_ptr< basic_parser< T > > emoticon
    emoticon as a whole (e.g. 😀, 🤔, 😶)
    Definition parser.hpp:3994
    +
    Test for end of line.
    Definition parser.hpp:657
    +
    Test for fraction.
    Definition parser.hpp:1690
    +
    Test for International Bank Account Number.
    Definition parser.hpp:4675
    +
    T bban[31]
    Normalized Basic Bank Account Number.
    Definition parser.hpp:4946
    +
    T country[3]
    ISO 3166-1 alpha-2 country code.
    Definition parser.hpp:4944
    +
    T check_digits[3]
    Two check digits.
    Definition parser.hpp:4945
    +
    bool is_valid
    Is IBAN valid per ISO 7064.
    Definition parser.hpp:4947
    +
    Test for decimal integer.
    Definition parser.hpp:1299
    +
    Test for decimal integer possibly containing thousand separators.
    Definition parser.hpp:1384
    +
    bool has_separators
    Did integer have any separators?
    Definition parser.hpp:1444
    +
    size_t digit_count
    Total number of digits in integer.
    Definition parser.hpp:1443
    +
    Test for hexadecimal integer.
    Definition parser.hpp:1465
    +
    Base class for integer testing.
    Definition parser.hpp:1277
    +
    size_t value
    Calculated value of the numeral.
    Definition parser.hpp:1291
    +
    Test for IPv4 address.
    Definition parser.hpp:2350
    +
    stdex::interval< size_t > components[4]
    Individual component intervals.
    Definition parser.hpp:2465
    +
    struct in_addr value
    IPv4 address value.
    Definition parser.hpp:2466
    +
    Test for IPv6 address.
    Definition parser.hpp:2569
    +
    std::shared_ptr< basic_parser< T > > scope_id
    Scope ID (e.g. NIC index with link-local addresses)
    Definition parser.hpp:2773
    +
    stdex::interval< size_t > components[8]
    Individual component intervals.
    Definition parser.hpp:2771
    +
    struct in6_addr value
    IPv6 address value.
    Definition parser.hpp:2772
    +
    Test for valid IPv6 address scope ID character.
    Definition parser.hpp:2497
    +
    Test for repeating.
    Definition parser.hpp:914
    +
    bool m_greedy
    try to match as long sequence as possible
    Definition parser.hpp:953
    +
    std::shared_ptr< basic_parser< T > > m_el
    repeating element
    Definition parser.hpp:950
    +
    size_t m_min_iterations
    minimum number of iterations
    Definition parser.hpp:951
    +
    size_t m_max_iterations
    maximum number of iterations
    Definition parser.hpp:952
    +
    Test for JSON string.
    Definition parser.hpp:7305
    +
    Test for mixed numeral.
    Definition parser.hpp:1926
    +
    std::shared_ptr< basic_parser< T > > fraction
    fraction
    Definition parser.hpp:2032
    +
    std::shared_ptr< basic_parser< T > > special_sign
    Special sign (e.g. plus-minus '±')
    Definition parser.hpp:2030
    +
    std::shared_ptr< basic_parser< T > > negative_sign
    Negative sign.
    Definition parser.hpp:2029
    +
    std::shared_ptr< basic_parser< T > > positive_sign
    Positive sign.
    Definition parser.hpp:2028
    +
    std::shared_ptr< basic_parser< T > > integer
    Integer part.
    Definition parser.hpp:2031
    +
    Test for monetary numeral.
    Definition parser.hpp:2221
    +
    std::shared_ptr< basic_parser< T > > positive_sign
    Positive sign.
    Definition parser.hpp:2327
    +
    std::shared_ptr< basic_parser< T > > decimal_separator
    Decimal separator.
    Definition parser.hpp:2332
    +
    std::shared_ptr< basic_parser< T > > currency
    Currency part.
    Definition parser.hpp:2330
    +
    std::shared_ptr< basic_parser< T > > decimal
    Decimal part.
    Definition parser.hpp:2333
    +
    std::shared_ptr< basic_parser< T > > integer
    Integer part.
    Definition parser.hpp:2331
    +
    std::shared_ptr< basic_parser< T > > negative_sign
    Negative sign.
    Definition parser.hpp:2328
    +
    std::shared_ptr< basic_parser< T > > special_sign
    Special sign (e.g. plus-minus '±')
    Definition parser.hpp:2329
    +
    "No-op" match
    Definition parser.hpp:193
    +
    Base template for all parsers.
    Definition parser.hpp:74
    +
    stdex::interval< size_t > interval
    Region of the last match.
    Definition parser.hpp:173
    +
    Test for permutation.
    Definition parser.hpp:1201
    +
    Test for phone number.
    Definition parser.hpp:4522
    +
    std::basic_string< T > value
    Normalized phone number.
    Definition parser.hpp:4648
    +
    Test for any punctuation code unit.
    Definition parser.hpp:467
    +
    Test for Roman numeral.
    Definition parser.hpp:1574
    +
    Test for scientific numeral.
    Definition parser.hpp:2052
    +
    std::shared_ptr< basic_parser< T > > special_sign
    Special sign (e.g. plus-minus '±')
    Definition parser.hpp:2196
    +
    std::shared_ptr< basic_parser< T > > exponent_symbol
    Exponent symbol (e.g. 'e')
    Definition parser.hpp:2200
    +
    std::shared_ptr< basic_parser< T > > positive_sign
    Positive sign.
    Definition parser.hpp:2194
    +
    std::shared_ptr< basic_parser< T > > negative_sign
    Negative sign.
    Definition parser.hpp:2195
    +
    double value
    Calculated value of the numeral.
    Definition parser.hpp:2204
    +
    std::shared_ptr< basic_parser< T > > negative_exp_sign
    Negative exponent sign (e.g. '-')
    Definition parser.hpp:2202
    +
    std::shared_ptr< basic_integer< T > > decimal
    Decimal part.
    Definition parser.hpp:2199
    +
    std::shared_ptr< basic_parser< T > > positive_exp_sign
    Positive exponent sign (e.g. '+')
    Definition parser.hpp:2201
    +
    std::shared_ptr< basic_integer< T > > exponent
    Exponent part.
    Definition parser.hpp:2203
    +
    std::shared_ptr< basic_parser< T > > decimal_separator
    Decimal separator.
    Definition parser.hpp:2198
    +
    std::shared_ptr< basic_integer< T > > integer
    Integer part.
    Definition parser.hpp:2197
    +
    Test for match score.
    Definition parser.hpp:1753
    +
    Test for sequence.
    Definition parser.hpp:1010
    +
    Definition parser.hpp:692
    +
    Test for SI Reference delimiter.
    Definition parser.hpp:5166
    +
    Test for SI Reference part.
    Definition parser.hpp:5121
    +
    Test for SI Reference.
    Definition parser.hpp:5204
    +
    basic_si_reference_part< T > part3
    Reference data part 3 (P3)
    Definition parser.hpp:5521
    +
    basic_si_reference_part< T > part1
    Reference data part 1 (P1)
    Definition parser.hpp:5519
    +
    bool is_valid
    Is reference valid.
    Definition parser.hpp:5522
    +
    T model[3]
    Reference model.
    Definition parser.hpp:5518
    +
    basic_si_reference_part< T > part2
    Reference data part 2 (P2)
    Definition parser.hpp:5520
    +
    Test for signed numeral.
    Definition parser.hpp:1840
    +
    std::shared_ptr< basic_parser< T > > special_sign
    Special sign (e.g. plus-minus '±')
    Definition parser.hpp:1908
    +
    std::shared_ptr< basic_parser< T > > negative_sign
    Negative sign.
    Definition parser.hpp:1907
    +
    std::shared_ptr< basic_parser< T > > positive_sign
    Positive sign.
    Definition parser.hpp:1906
    +
    std::shared_ptr< basic_parser< T > > number
    Number.
    Definition parser.hpp:1909
    +
    Test for any space code unit.
    Definition parser.hpp:388
    +
    Test for any space or punctuation code unit.
    Definition parser.hpp:541
    +
    Test for any string.
    Definition parser.hpp:1129
    +
    Test for given string.
    Definition parser.hpp:819
    +
    Test for time.
    Definition parser.hpp:4296
    +
    Test for valid URL password character.
    Definition parser.hpp:3092
    +
    Test for valid URL path character.
    Definition parser.hpp:3192
    +
    Test for URL path.
    Definition parser.hpp:3300
    +
    Test for valid URL username character.
    Definition parser.hpp:2993
    +
    Test for URL.
    Definition parser.hpp:3441
    +
    Test for HTTP agent.
    Definition parser.hpp:6828
    +
    Test for HTTP any type.
    Definition parser.hpp:5950
    +
    Test for HTTP asterisk.
    Definition parser.hpp:6592
    + + + + + +
    Test for HTTP header.
    Definition parser.hpp:7151
    +
    Test for HTTP language (RFC1766)
    Definition parser.hpp:6460
    +
    Test for HTTP line break (RFC2616: CRLF | LF)
    Definition parser.hpp:5624
    +
    Test for HTTP media range (RFC2616: media-range)
    Definition parser.hpp:5982
    +
    Test for HTTP media type (RFC2616: media-type)
    Definition parser.hpp:6037
    +
    Test for HTTP parameter (RFC2616: parameter)
    Definition parser.hpp:5895
    +
    http_token name
    Parameter name.
    Definition parser.hpp:5939
    +
    http_value value
    Parameter value.
    Definition parser.hpp:5940
    +
    Test for HTTP protocol.
    Definition parser.hpp:6904
    +
    uint16_t version
    HTTP protocol version: 0x100 = 1.0, 0x101 = 1.1...
    Definition parser.hpp:7006
    +
    Test for HTTP quoted string (RFC2616: quoted-string)
    Definition parser.hpp:5785
    +
    stdex::interval< size_t > content
    String content (without quotes)
    Definition parser.hpp:5841
    +
    Test for HTTP request.
    Definition parser.hpp:7013
    +
    Test for HTTP space (RFC2616: LWS)
    Definition parser.hpp:5660
    +
    Test for HTTP text character (RFC2616: TEXT)
    Definition parser.hpp:5697
    +
    Test for HTTP token (RFC2616: token - tolerates non-ASCII)
    Definition parser.hpp:5731
    +
    Test for HTTP URL parameter.
    Definition parser.hpp:6277
    +
    Test for HTTP URL path segment.
    Definition parser.hpp:6188
    +
    Test for HTTP URL path segment.
    Definition parser.hpp:6221
    +
    std::vector< http_url_path_segment > segments
    Path segments.
    Definition parser.hpp:6270
    +
    Test for HTTP URL port.
    Definition parser.hpp:6132
    +
    Test for HTTP URL server.
    Definition parser.hpp:6095
    +
    Test for HTTP URL.
    Definition parser.hpp:6358
    +
    Collection of HTTP values.
    Definition parser.hpp:7261
    +
    Test for HTTP value (RFC2616: value)
    Definition parser.hpp:5851
    +
    http_quoted_string string
    Value when matched as quoted string.
    Definition parser.hpp:5887
    +
    http_token token
    Value when matched as token.
    Definition parser.hpp:5888
    +
    Test for HTTP weight factor.
    Definition parser.hpp:6523
    +
    float value
    Calculated value of the weight factor.
    Definition parser.hpp:6585
    +
    Test for HTTP weighted value.
    Definition parser.hpp:6615
    +
    Base template for collection-holding parsers.
    Definition parser.hpp:970
    +
    Test for any SGML code point.
    Definition parser.hpp:257
    +
    Test for any SGML code point from a given string of SGML code points.
    Definition parser.hpp:776
    +
    Test for specific SGML code point.
    Definition parser.hpp:344
    +
    Test for valid DNS domain SGML character.
    Definition parser.hpp:2866
    +
    Test for valid IPv6 address scope ID SGML character.
    Definition parser.hpp:2535
    +
    Test for any SGML punctuation code point.
    Definition parser.hpp:508
    +
    Test for any SGML space code point.
    Definition parser.hpp:431
    +
    Test for any SGML space or punctuation code point.
    Definition parser.hpp:584
    +
    Test for SGML given string.
    Definition parser.hpp:866
    +
    Test for valid URL password SGML character.
    Definition parser.hpp:3144
    +
    Test for valid URL path SGML character.
    Definition parser.hpp:3248
    +
    Test for valid URL username SGML character.
    Definition parser.hpp:3044
    Numerical interval.
    Definition interval.hpp:18
    T size() const
    Returns interval size.
    Definition interval.hpp:47
    T end
    interval end
    Definition interval.hpp:20
    interval() noexcept
    Constructs an invalid interval.
    Definition interval.hpp:25
    T start
    interval start
    Definition interval.hpp:19
    -
    Definition parser.hpp:7290
    +
    Definition parser.hpp:7287
    diff --git a/pch_8hpp_source.html b/pch_8hpp_source.html index 09374bd2a..88d2cf401 100644 --- a/pch_8hpp_source.html +++ b/pch_8hpp_source.html @@ -118,7 +118,7 @@ $(document).ready(function() { init_codefold(0); });
    diff --git a/progress_8hpp_source.html b/progress_8hpp_source.html index 26ad981bb..ab593d49d 100644 --- a/progress_8hpp_source.html +++ b/progress_8hpp_source.html @@ -182,7 +182,7 @@ $(document).ready(function() { init_codefold(0); });
    130
    131 protected:
    132 std::chrono::nanoseconds m_timeout;
    -
    133 std::chrono::steady_clock::time_point m_last;
    +
    133 std::chrono::system_clock::time_point m_last;
    134 T m_start, m_end, m_value;
    135 };
    @@ -331,7 +331,7 @@ $(document).ready(function() { init_codefold(0); });
    diff --git a/ring_8cpp_source.html b/ring_8cpp_source.html index c70a41b54..6f09743f4 100644 --- a/ring_8cpp_source.html +++ b/ring_8cpp_source.html @@ -144,7 +144,7 @@ $(document).ready(function() { init_codefold(0); });
    diff --git a/ring_8hpp_source.html b/ring_8hpp_source.html index e7f490fea..d5ee2e69e 100644 --- a/ring_8hpp_source.html +++ b/ring_8hpp_source.html @@ -223,7 +223,7 @@ $(document).ready(function() { init_codefold(0); });
    diff --git a/search/all_8.js b/search/all_8.js index a4ee99a4f..801db3148 100644 --- a/search/all_8.js +++ b/search/all_8.js @@ -3,7 +3,7 @@ var searchData= ['id_0',['id',['../classstdex_1_1idrec_1_1record.html#a24e54541a476b01e332290c57a495926',1,'stdex::idrec::record']]], ['integer_1',['integer',['../classstdex_1_1parser_1_1basic__mixed__numeral.html#af42e711d277a70c9624864e5f74a0bfd',1,'stdex::parser::basic_mixed_numeral::integer'],['../classstdex_1_1parser_1_1basic__scientific__numeral.html#aff899e847d2b78df90ab367ef824505a',1,'stdex::parser::basic_scientific_numeral::integer'],['../classstdex_1_1parser_1_1basic__monetary__numeral.html#acdbf4ca7d154c8723e8c318000853cce',1,'stdex::parser::basic_monetary_numeral::integer']]], ['interactive_5fprocess_2',['interactive_process',['../structstdex_1_1sys__info__t.html#ae2a466655022e5df25ddbe56eec8b54f',1,'stdex::sys_info_t']]], - ['interval_3',['interval',['../structstdex_1_1interval.html',1,'stdex::interval< T >'],['../structstdex_1_1interval.html#a41ac8e9fdb33a2dfaae6113006b792d8',1,'stdex::interval::interval()'],['../classstdex_1_1parser_1_1basic__parser.html#a0b46b1904e5af116c34a10087a5bc056',1,'stdex::parser::basic_parser::interval'],['../structstdex_1_1interval.html#a9f6c66e8a3fd15c693011216bb45d6b9',1,'stdex::interval::interval() noexcept'],['../structstdex_1_1interval.html#a100a68cd81867cbf1b275cd5ab5d2160',1,'stdex::interval::interval(T x) noexcept']]], + ['interval_3',['interval',['../structstdex_1_1interval.html',1,'stdex::interval< T >'],['../structstdex_1_1interval.html#a41ac8e9fdb33a2dfaae6113006b792d8',1,'stdex::interval::interval()'],['../classstdex_1_1parser_1_1basic__parser.html#a5e9bd1c618c97e206f943c6eacd1b3aa',1,'stdex::parser::basic_parser::interval'],['../structstdex_1_1interval.html#a9f6c66e8a3fd15c693011216bb45d6b9',1,'stdex::interval::interval() noexcept'],['../structstdex_1_1interval.html#a100a68cd81867cbf1b275cd5ab5d2160',1,'stdex::interval::interval(T x) noexcept']]], ['interval_3c_20fpos_5ft_20_3e_4',['interval< fpos_t >',['../structstdex_1_1interval.html',1,'stdex']]], ['interval_3c_20size_5ft_20_3e_5',['interval< size_t >',['../structstdex_1_1interval.html',1,'stdex']]], ['into_20std_20c_6',['stdex - Random stuff that didn't made it into std C++',['../index.html',1,'']]], diff --git a/search/variables_7.js b/search/variables_7.js index 433fa08ad..2afb54862 100644 --- a/search/variables_7.js +++ b/search/variables_7.js @@ -2,6 +2,6 @@ var searchData= [ ['integer_0',['integer',['../classstdex_1_1parser_1_1basic__mixed__numeral.html#af42e711d277a70c9624864e5f74a0bfd',1,'stdex::parser::basic_mixed_numeral::integer'],['../classstdex_1_1parser_1_1basic__scientific__numeral.html#aff899e847d2b78df90ab367ef824505a',1,'stdex::parser::basic_scientific_numeral::integer'],['../classstdex_1_1parser_1_1basic__monetary__numeral.html#acdbf4ca7d154c8723e8c318000853cce',1,'stdex::parser::basic_monetary_numeral::integer']]], ['interactive_5fprocess_1',['interactive_process',['../structstdex_1_1sys__info__t.html#ae2a466655022e5df25ddbe56eec8b54f',1,'stdex::sys_info_t']]], - ['interval_2',['interval',['../classstdex_1_1parser_1_1basic__parser.html#a0b46b1904e5af116c34a10087a5bc056',1,'stdex::parser::basic_parser']]], + ['interval_2',['interval',['../classstdex_1_1parser_1_1basic__parser.html#a5e9bd1c618c97e206f943c6eacd1b3aa',1,'stdex::parser::basic_parser']]], ['is_5fvalid_3',['is_valid',['../classstdex_1_1parser_1_1basic__iban.html#acfc23c46ecbeef921e7b39a812c07ec7',1,'stdex::parser::basic_iban::is_valid'],['../classstdex_1_1parser_1_1basic__creditor__reference.html#aee8d302b914c5d7d64d2f7ace18d74cc',1,'stdex::parser::basic_creditor_reference::is_valid'],['../classstdex_1_1parser_1_1basic__si__reference.html#a75ec581785b9cfbab1c26ca9e4787b10',1,'stdex::parser::basic_si_reference::is_valid']]] ]; diff --git a/sgml_8cpp_source.html b/sgml_8cpp_source.html index b0d4e99a1..079a1598e 100644 --- a/sgml_8cpp_source.html +++ b/sgml_8cpp_source.html @@ -153,7 +153,7 @@ $(document).ready(function() { init_codefold(0); });
    diff --git a/sgml_8hpp_source.html b/sgml_8hpp_source.html index ed3bcfa2b..5632301c7 100644 --- a/sgml_8hpp_source.html +++ b/sgml_8hpp_source.html @@ -93,686 +93,687 @@ $(document).ready(function() { init_codefold(0); });
    9#include "mapping.hpp"
    10#include "sgml_unicode.hpp"
    11#include "string.hpp"
    -
    12#include <exception>
    -
    13#include <string>
    -
    14
    -
    15namespace stdex
    -
    16{
    -
    18 template <class T>
    -
    19 inline const wchar_t* sgml2uni(_In_reads_or_z_(count) const T* entity, _In_ size_t count)
    -
    20 {
    -
    21 _Assume_(entity && count);
    -
    22 _Assume_(count < 2 || entity[0] != '#'); // No numeric entities
    -
    23
    -
    24 for (size_t i = 0, j = _countof(sgml_unicode); i < j; ) {
    -
    25 size_t m = (i + j) / 2;
    -
    26 if (sgml_unicode[m].sgml[0] < entity[0])
    -
    27 i = m + 1;
    -
    28 else if (sgml_unicode[m].sgml[0] > entity[0])
    -
    29 j = m;
    -
    30 else {
    -
    31 auto r = strncmp<char, T>(sgml_unicode[m].sgml + 1, _countof(sgml_unicode[0].sgml) - 1, entity + 1, count - 1);
    -
    32 if (r < 0)
    -
    33 i = m + 1;
    -
    34 else if (r > 0)
    -
    35 j = m;
    -
    36 else {
    -
    37 for (; i < m && strncmp<char, T>(sgml_unicode[m - 1].sgml, _countof(sgml_unicode[0].sgml), entity, count) == 0; m--);
    -
    38 return sgml_unicode[m].unicode;
    -
    39 }
    -
    40 }
    -
    41 }
    -
    42 return nullptr;
    -
    43 }
    -
    44
    -
    45 template <class T>
    -
    46 inline const T* sgmlend(
    -
    47 _In_reads_or_z_opt_(count) const T* str, _In_ size_t count)
    -
    48 {
    -
    49 _Assume_(str || !count);
    -
    50 for (size_t i = 0; i < count; i++) {
    -
    51 if (str[i] == ';')
    -
    52 return str + i;
    -
    53 if (!str[i] || str[i] == '&' || isspace(str[i]))
    -
    54 break;
    -
    55 }
    -
    56 return nullptr;
    -
    57 }
    -
    59
    -
    60 constexpr int sgml_full = 0x80000000;
    -
    61 constexpr int sgml_quot = 0x00000001;
    -
    62 constexpr int sgml_apos = 0x00000002;
    -
    63 constexpr int sgml_quot_apos = sgml_quot | sgml_apos;
    -
    64 constexpr int sgml_amp = 0x00000004;
    -
    65 constexpr int sgml_lt_gt = 0x00000008;
    -
    66 constexpr int sgml_bsol = 0x00000010;
    -
    67 constexpr int sgml_dollar = 0x00000020;
    -
    68 constexpr int sgml_percnt = 0x00000040;
    -
    69 constexpr int sgml_commat = 0x00000080;
    -
    70 constexpr int sgml_num = 0x00000100;
    -
    71 constexpr int sgml_lpar_rpar = 0x00000200;
    -
    72 constexpr int sgml_lcub_rcub = 0x00000400;
    -
    73 constexpr int sgml_lsqb_rsqb = 0x00000800;
    -
    74 constexpr int sgml_sgml = sgml_amp | sgml_lt_gt;
    -
    75 constexpr int sgml_ml_attrib = sgml_amp | sgml_quot_apos;
    -
    76 constexpr int sgml_c = sgml_amp | sgml_bsol | sgml_quot_apos;
    -
    77 // constexpr int sgml_ajt_lemma = sgml_amp | sgml_quot | sgml_dollar | sgml_percnt;
    -
    78 // constexpr int sgml_ajt_form = sgml_ajt_lemma;
    -
    79 // constexpr int sgml_kolos = sgml_amp | sgml_quot | sgml_dollar | sgml_percnt | sgml_lt_gt | sgml_bsol/* | sgml_commat | sgml_num*/ | sgml_lpar_rpar | sgml_lcub_rcub | sgml_lsqb_rsqb;
    -
    80
    -
    91 template <class T>
    -
    92 inline void sgml2wstrcat(
    -
    93 _Inout_ std::wstring& dst,
    -
    94 _In_reads_or_z_opt_(count_src) const T* src, _In_ size_t count_src,
    -
    95 _In_ int skip = 0,
    -
    96 _In_ const mapping<size_t>& offset = mapping<size_t>(0, 0),
    -
    97 _Inout_opt_ mapping_vector<size_t>* map = nullptr)
    -
    98 {
    -
    99 _Assume_(src || !count_src);
    -
    100
    -
    101 const bool
    -
    102 skip_quot = (skip & sgml_quot) == 0,
    -
    103 skip_apos = (skip & sgml_apos) == 0,
    -
    104 skip_amp = (skip & sgml_amp) == 0,
    -
    105 skip_lt_gt = (skip & sgml_lt_gt) == 0,
    -
    106 skip_bsol = (skip & sgml_bsol) == 0,
    -
    107 skip_dollar = (skip & sgml_dollar) == 0,
    -
    108 skip_percnt = (skip & sgml_percnt) == 0,
    -
    109 skip_commat = (skip & sgml_commat) == 0,
    -
    110 skip_num = (skip & sgml_num) == 0,
    -
    111 skip_lpar_rpar = (skip & sgml_lpar_rpar) == 0,
    -
    112 skip_lcub_rcub = (skip & sgml_lcub_rcub) == 0,
    -
    113 skip_lsqb_rsqb = (skip & sgml_lsqb_rsqb) == 0;
    -
    114
    -
    115 count_src = strnlen(src, count_src);
    -
    116 dst.reserve(dst.size() + count_src);
    -
    117 for (size_t i = 0; i < count_src;) {
    -
    118 if (src[i] == '&') {
    -
    119 auto end = sgmlend(src + i + 1, count_src - i - 1);
    -
    120 if (end) {
    -
    121 const wchar_t* entity_w;
    -
    122 wchar_t chr[3];
    -
    123 size_t n = end - src - i - 1;
    -
    124 if (n >= 2 && src[i + 1] == '#') {
    -
    125 uint32_t unicode;
    -
    126 if (src[i + 2] == 'x' || src[i + 2] == 'X')
    -
    127 unicode = strtou32(src + i + 3, n - 2, nullptr, 16);
    -
    128 else
    -
    129 unicode = strtou32(src + i + 2, n - 1, nullptr, 10);
    -
    130#ifdef _WIN32
    -
    131 if (unicode < 0x10000) {
    -
    132 chr[0] = (wchar_t)unicode;
    -
    133 chr[1] = 0;
    -
    134 }
    -
    135 else {
    -
    136 ucs4_to_surrogate_pair(chr, unicode);
    -
    137 chr[2] = 0;
    -
    138 }
    -
    139#else
    -
    140 chr[0] = (wchar_t)unicode;
    -
    141 chr[1] = 0;
    -
    142#endif
    -
    143 entity_w = chr;
    -
    144 }
    -
    145 else
    -
    146 entity_w = sgml2uni(src + i + 1, n);
    -
    147
    -
    148 if (entity_w &&
    -
    149 (skip_quot || (entity_w[0] != L'"')) &&
    -
    150 (skip_apos || (entity_w[0] != L'\'')) &&
    -
    151 (skip_amp || (entity_w[0] != L'&')) &&
    -
    152 (skip_lt_gt || (entity_w[0] != L'<' && entity_w[0] != L'>')) &&
    -
    153 (skip_bsol || (entity_w[0] != L'\\')) &&
    -
    154 (skip_dollar || (entity_w[0] != L'$')) &&
    -
    155 (skip_percnt || (entity_w[0] != L'%')) &&
    -
    156 (skip_commat || (entity_w[0] != L'@')) &&
    -
    157 (skip_num || (entity_w[0] != L'#')) &&
    -
    158 (skip_lpar_rpar || (entity_w[0] != L'(' && entity_w[0] != L')')) &&
    -
    159 (skip_lcub_rcub || (entity_w[0] != L'{' && entity_w[0] != L'}')) &&
    -
    160 (skip_lsqb_rsqb || (entity_w[0] != L'[' && entity_w[0] != L']')))
    -
    161 {
    -
    162 if (map) map->push_back(mapping<size_t>(offset.from + i, offset.to + dst.size()));
    -
    163 dst.append(entity_w);
    -
    164 i = end - src + 1;
    -
    165 if (map) map->push_back(mapping<size_t>(offset.from + i, offset.to + dst.size()));
    -
    166 continue;
    -
    167 }
    -
    168 }
    -
    169 }
    -
    170 dst.append(1, src[i++]);
    -
    171 }
    -
    172 }
    -
    173
    -
    174 template <class T>
    -
    175 _Deprecated_("Use stdex::sgml2wstrcat")
    -
    176 inline void sgml2wstr(
    -
    177 _Inout_ std::wstring& dst,
    -
    178 _In_reads_or_z_opt_(count_src) const T* src, _In_ size_t count_src,
    -
    179 _In_ int skip = 0,
    -
    180 _In_ const mapping<size_t>& offset = mapping<size_t>(0, 0),
    -
    181 _Inout_opt_ mapping_vector<size_t>* map = nullptr)
    -
    182 {
    -
    183 sgml2wstrcat(dst, src, count_src, skip, offset, map);
    -
    184 }
    -
    185
    -
    195 template <class T>
    -
    196 inline void sgml2wstrcat(
    -
    197 _Inout_ std::wstring& dst,
    -
    198 _In_ const std::basic_string<T>& src,
    -
    199 _In_ int skip = 0,
    -
    200 _In_ const mapping<size_t>& offset = mapping<size_t>(0, 0),
    -
    201 _Inout_opt_ mapping_vector<size_t>* map = nullptr)
    -
    202 {
    -
    203 sgml2wstrcat(dst, src.data(), src.size(), skip, offset, map);
    -
    204 }
    -
    205
    -
    206 template <class T>
    -
    207 _Deprecated_("Use stdex::sgml2wstrcat")
    -
    208 inline void sgml2wstr(
    -
    209 _Inout_ std::wstring& dst,
    -
    210 _In_ const std::basic_string<T>& src,
    -
    211 _In_ int skip = 0,
    -
    212 _In_ const mapping<size_t>& offset = mapping<size_t>(0, 0),
    -
    213 _Inout_opt_ mapping_vector<size_t>* map = nullptr)
    -
    214 {
    -
    215 sgml2wstrcat(dst, src, skip, offset, map);
    -
    216 }
    -
    217
    -
    231 template <class T>
    -
    232 inline size_t sgml2wstrcat(
    -
    233 _Inout_cap_(count_dst) wchar_t* dst, _In_ size_t count_dst,
    -
    234 _In_reads_or_z_opt_(count_src) const T* src, _In_ size_t count_src,
    -
    235 _In_ int skip = 0,
    -
    236 _In_ const mapping<size_t>& offset = mapping<size_t>(0, 0),
    -
    237 _Inout_opt_ mapping_vector<size_t>* map = nullptr)
    -
    238 {
    -
    239 _Assume_(dst || !count_dst);
    -
    240 _Assume_(src || !count_src);
    -
    241
    -
    242 static const std::invalid_argument buffer_overrun("buffer overrun");
    -
    243 const bool
    -
    244 skip_quot = (skip & sgml_quot) == 0,
    -
    245 skip_apos = (skip & sgml_apos) == 0,
    -
    246 skip_amp = (skip & sgml_amp) == 0,
    -
    247 skip_lt_gt = (skip & sgml_lt_gt) == 0,
    -
    248 skip_bsol = (skip & sgml_bsol) == 0,
    -
    249 skip_dollar = (skip & sgml_dollar) == 0,
    -
    250 skip_percnt = (skip & sgml_percnt) == 0,
    -
    251 skip_commat = (skip & sgml_commat) == 0,
    -
    252 skip_num = (skip & sgml_num) == 0,
    -
    253 skip_lpar_rpar = (skip & sgml_lpar_rpar) == 0,
    -
    254 skip_lcub_rcub = (skip & sgml_lcub_rcub) == 0,
    -
    255 skip_lsqb_rsqb = (skip & sgml_lsqb_rsqb) == 0;
    -
    256
    -
    257 size_t j = wcsnlen(dst, count_dst);
    -
    258 count_src = strnlen(src, count_src);
    -
    259 for (size_t i = 0; i < count_src;) {
    -
    260 if (src[i] == '&') {
    -
    261 auto end = sgmlend(src + i + 1, count_src - i - 1);
    -
    262 if (end) {
    -
    263 const wchar_t* entity_w;
    -
    264 wchar_t chr[3];
    -
    265 size_t n = end - src - i - 1;
    -
    266 if (n >= 2 && src[i + 1] == '#') {
    -
    267 uint32_t unicode;
    -
    268 if (src[i + 2] == 'x' || src[i + 2] == 'X')
    -
    269 unicode = strtou32(src + i + 3, n - 2, nullptr, 16);
    -
    270 else
    -
    271 unicode = strtou32(src + i + 2, n - 1, nullptr, 10);
    -
    272#ifdef _WIN32
    -
    273 if (unicode < 0x10000) {
    -
    274 chr[0] = (wchar_t)unicode;
    -
    275 chr[1] = 0;
    -
    276 }
    -
    277 else {
    -
    278 ucs4_to_surrogate_pair(chr, unicode);
    -
    279 chr[2] = 0;
    -
    280 }
    -
    281#else
    -
    282 chr[0] = (wchar_t)unicode;
    -
    283 chr[1] = 0;
    -
    284#endif
    -
    285 entity_w = chr;
    -
    286 }
    -
    287 else
    -
    288 entity_w = sgml2uni(src + i + 1, n);
    -
    289
    -
    290 if (entity_w &&
    -
    291 (skip_quot || (entity_w[0] != L'"')) &&
    -
    292 (skip_apos || (entity_w[0] != L'\'')) &&
    -
    293 (skip_amp || (entity_w[0] != L'&')) &&
    -
    294 (skip_lt_gt || (entity_w[0] != L'<' && entity_w[0] != L'>')) &&
    -
    295 (skip_bsol || (entity_w[0] != L'\\')) &&
    -
    296 (skip_dollar || (entity_w[0] != L'$')) &&
    -
    297 (skip_percnt || (entity_w[0] != L'%')) &&
    -
    298 (skip_commat || (entity_w[0] != L'@')) &&
    -
    299 (skip_num || (entity_w[0] != L'#')) &&
    -
    300 (skip_lpar_rpar || (entity_w[0] != L'(' && entity_w[0] != L')')) &&
    -
    301 (skip_lcub_rcub || (entity_w[0] != L'{' && entity_w[0] != L'}')) &&
    -
    302 (skip_lsqb_rsqb || (entity_w[0] != L'[' && entity_w[0] != L']')))
    -
    303 {
    -
    304 if (map) map->push_back(mapping<size_t>(offset.from + i, offset.to + j));
    -
    305 size_t m = wcslen(entity_w);
    -
    306 if (j + m >= count_dst)
    -
    307 throw buffer_overrun;
    -
    308 memcpy(dst + j, entity_w, m * sizeof(wchar_t)); j += m;
    -
    309 i = end - src + 1;
    -
    310 if (map) map->push_back(mapping<size_t>(offset.from + i, offset.to + j));
    -
    311 continue;
    -
    312 }
    -
    313 }
    -
    314 }
    -
    315 if (j + 1 >= count_dst)
    -
    316 throw buffer_overrun;
    -
    317 dst[j++] = src[i++];
    -
    318 }
    -
    319 if (j >= count_dst)
    -
    320 throw buffer_overrun;
    -
    321 dst[j] = 0;
    -
    322 return j;
    -
    323 }
    -
    324
    -
    325 template <class T>
    -
    326 _Deprecated_("Use stdex::sgml2wstrcat")
    -
    327 inline size_t sgml2wstr(
    -
    328 _Inout_cap_(count_dst) wchar_t* dst, _In_ size_t count_dst,
    -
    329 _In_reads_or_z_opt_(count_src) const T* src, _In_ size_t count_src,
    -
    330 _In_ int skip = 0,
    -
    331 _In_ const mapping<size_t>& offset = mapping<size_t>(0, 0),
    -
    332 _Inout_opt_ mapping_vector<size_t>* map = nullptr)
    -
    333 {
    -
    334 return sgml2wstrcat(dst, count_dst, src, count_src, skip, offset, map);
    -
    335 }
    -
    336
    -
    347 template <class T>
    -
    348 inline void sgml2wstrcpy(
    -
    349 _Inout_ std::wstring& dst,
    -
    350 _In_reads_or_z_opt_(count_src) const T* src, _In_ size_t count_src,
    -
    351 _In_ int skip = 0,
    -
    352 _In_ const mapping<size_t>& offset = mapping<size_t>(0, 0),
    -
    353 _Inout_opt_ mapping_vector<size_t>* map = nullptr)
    -
    354 {
    -
    355 dst.clear();
    -
    356 if (map)
    -
    357 map->clear();
    -
    358 sgml2wstrcat(dst, src, count_src, skip, offset, map);
    -
    359 }
    -
    360
    -
    370 template<class _Elem, class _Traits, class _Ax>
    -
    371 inline void sgml2wstrcpy(
    -
    372 _Inout_ std::wstring& dst,
    -
    373 _In_ const std::basic_string<_Elem, _Traits, _Ax>& src,
    -
    374 _In_ int skip = 0,
    -
    375 _In_ const mapping<size_t>& offset = mapping<size_t>(0, 0),
    -
    376 _Inout_opt_ mapping_vector<size_t>* map = nullptr)
    -
    377 {
    -
    378 sgml2wstrcpy(dst, src.data(), src.size(), skip, offset, map);
    -
    379 }
    -
    380
    -
    394 template <class T>
    -
    395 inline size_t sgml2wstrcpy(
    -
    396 _Inout_cap_(count_dst) wchar_t* dst, _In_ size_t count_dst,
    -
    397 _In_reads_or_z_opt_(count_src) const T* src, _In_ size_t count_src,
    -
    398 _In_ int skip = 0,
    -
    399 _In_ const mapping<size_t>& offset = mapping<size_t>(0, 0),
    -
    400 _Inout_opt_ mapping_vector<size_t>* map = nullptr)
    -
    401 {
    -
    402 _Assume_(dst || !count_dst);
    -
    403 if (count_dst)
    -
    404 dst[0] = 0;
    -
    405 if (map)
    -
    406 map->clear();
    -
    407 return sgml2wstrcat(dst, count_dst, src, count_src, skip, offset, map);
    -
    408 }
    -
    409
    -
    421 template <class T>
    -
    422 inline std::wstring sgml2wstr(
    -
    423 _In_reads_or_z_opt_(count_src) const T* src, _In_ size_t count_src,
    -
    424 _In_ int skip = 0,
    -
    425 _In_ const mapping<size_t>& offset = mapping<size_t>(0, 0),
    -
    426 _Inout_opt_ mapping_vector<size_t>* map = nullptr)
    -
    427 {
    -
    428 std::wstring dst;
    -
    429 sgml2wstrcat(dst, src, count_src, skip, offset, map);
    -
    430 return dst;
    -
    431 }
    -
    432
    -
    443 template <class T>
    -
    444 inline std::wstring sgml2wstr(
    -
    445 _In_ const std::basic_string<T>& src,
    -
    446 _In_ int skip = 0,
    -
    447 _In_ const mapping<size_t>& offset = mapping<size_t>(0, 0),
    -
    448 _Inout_opt_ mapping_vector<size_t>* map = nullptr)
    -
    449 {
    -
    450 return sgml2wstr(src.c_str(), src.size(), skip, offset, map);
    -
    451 }
    -
    452
    -
    454 inline const char* chr2sgml(_In_reads_or_z_(count) const wchar_t* entity, _In_ size_t count)
    -
    455 {
    -
    456 _Assume_(entity && count);
    -
    457
    -
    458 const wchar_t e2 = entity[0];
    -
    459 for (size_t i = 0, j = _countof(unicode_sgml); i < j; ) {
    -
    460 size_t m = (i + j) / 2;
    -
    461 wchar_t e1 = sgml_unicode[unicode_sgml[m]].unicode[0];
    -
    462 if (e1 < e2)
    -
    463 i = m + 1;
    -
    464 else if (e1 > e2)
    -
    465 j = m;
    -
    466 else {
    -
    467 auto r = strncmp(sgml_unicode[unicode_sgml[m]].unicode + 1, _countof(sgml_unicode[0].unicode) - 1, entity + 1, count - 1);
    -
    468 if (r < 0)
    -
    469 i = m + 1;
    -
    470 else if (r > 0)
    -
    471 j = m;
    -
    472 else {
    -
    473 for (; i < m && sgml_unicode[unicode_sgml[m - 1]].unicode[0] == e2 && strncmp(sgml_unicode[unicode_sgml[m - 1]].unicode + 1, _countof(sgml_unicode[0].unicode) - 1, entity + 1, count - 1) == 0; m--);
    -
    474 return sgml_unicode[unicode_sgml[m]].sgml;
    -
    475 }
    -
    476 }
    -
    477 }
    -
    478 return nullptr;
    -
    479 }
    -
    481
    -
    490 inline void wstr2sgmlcat(
    -
    491 _Inout_ std::string& dst,
    -
    492 _In_reads_or_z_opt_(count_src) const wchar_t* src, _In_ size_t count_src,
    -
    493 _In_ size_t what = 0)
    -
    494 {
    -
    495 _Assume_(src || !count_src);
    -
    496
    -
    497 const bool
    -
    498 do_ascii = (what & sgml_full) == 0,
    -
    499 do_quot = (what & sgml_quot) == 0,
    -
    500 do_apos = (what & sgml_apos) == 0,
    -
    501 do_lt_gt = (what & sgml_lt_gt) == 0,
    -
    502 do_bsol = (what & sgml_bsol) == 0,
    -
    503 do_dollar = (what & sgml_dollar) == 0,
    -
    504 do_percnt = (what & sgml_percnt) == 0,
    -
    505 do_commat = (what & sgml_commat) == 0,
    -
    506 do_num = (what & sgml_num) == 0,
    -
    507 do_lpar_rpar = (what & sgml_lpar_rpar) == 0,
    -
    508 do_lcub_rcub = (what & sgml_lcub_rcub) == 0,
    -
    509 do_lsqb_rsqb = (what & sgml_lsqb_rsqb) == 0;
    -
    510
    -
    511 count_src = wcsnlen(src, count_src);
    -
    512 dst.reserve(dst.size() + count_src);
    -
    513 for (size_t i = 0; i < count_src;) {
    -
    514 size_t n = glyphlen(src + i, count_src - i);
    -
    515 if (n == 1 &&
    -
    516 do_ascii && (unsigned int)src[i] < 128 &&
    -
    517 src[i] != L'&' &&
    -
    518 (do_quot || (src[i] != L'"')) &&
    -
    519 (do_apos || (src[i] != L'\'')) &&
    -
    520 (do_lt_gt || (src[i] != L'<' && src[i] != L'>')) &&
    -
    521 (do_bsol || (src[i] != L'\\')) &&
    -
    522 (do_dollar || (src[i] != L'$')) &&
    -
    523 (do_percnt || (src[i] != L'%')) &&
    -
    524 (do_commat || (src[i] != L'@')) &&
    -
    525 (do_num || (src[i] != L'#')) &&
    -
    526 (do_lpar_rpar || (src[i] != L'(' && src[i] != L')')) &&
    -
    527 (do_lcub_rcub || (src[i] != L'{' && src[i] != L'}')) &&
    -
    528 (do_lsqb_rsqb || (src[i] != L'[' && src[i] != L']')))
    -
    529 {
    -
    530 // 7-bit ASCII and no desire to encode it as an SGML entity.
    -
    531 dst.append(1, static_cast<char>(src[i++]));
    -
    532 }
    -
    533 else {
    -
    534 const char* entity = chr2sgml(src + i, n);
    -
    535 if (entity) {
    -
    536 dst.append(1, '&');
    -
    537 dst.append(entity);
    -
    538 dst.append(1, ';');
    -
    539 i += n;
    -
    540 }
    -
    541 else if (n == 1) {
    -
    542 // Trivial character (1 code unit, 1 glyph), no entity available.
    -
    543 if ((unsigned int)src[i] < 128)
    -
    544 dst.append(1, static_cast<char>(src[i++]));
    -
    545 else {
    -
    546 char tmp[3 + 8 + 1 + 1];
    -
    547 snprintf(tmp, _countof(tmp), "&#x%x;", src[i++]);
    -
    548 dst.append(tmp);
    -
    549 }
    -
    550 }
    -
    551 else {
    -
    552 // Non-trivial character. Decompose.
    -
    553 const size_t end = i + n;
    -
    554 while (i < end) {
    -
    555 if ((entity = chr2sgml(src + i, 1)) != nullptr) {
    -
    556 dst.append(1, '&');
    -
    557 dst.append(entity);
    -
    558 dst.append(1, ';');
    -
    559 i++;
    -
    560 }
    -
    561 else if ((unsigned int)src[i] < 128)
    -
    562 dst.append(1, static_cast<char>(src[i++]));
    -
    563 else {
    -
    564 uint32_t unicode;
    -
    565#ifdef _WIN32
    -
    566 if (i + 1 < end && is_surrogate_pair(src + i)) {
    -
    567 unicode = surrogate_pair_to_ucs4(src + i);
    -
    568 i += 2;
    -
    569 }
    -
    570 else
    -
    571#endif
    -
    572 {
    -
    573 unicode = src[i++];
    -
    574 }
    -
    575 char tmp[3 + 8 + 1 + 1];
    -
    576 snprintf(tmp, _countof(tmp), "&#x%x;", unicode);
    -
    577 dst.append(tmp);
    -
    578 }
    -
    579 }
    -
    580 }
    -
    581 }
    -
    582 }
    -
    583 }
    -
    584
    -
    585 _Deprecated_("Use stdex::wstr2sgmlcat")
    -
    586 inline void wstr2sgml(
    -
    587 _Inout_ std::string& dst,
    -
    588 _In_reads_or_z_opt_(count_src) const wchar_t* src, _In_ size_t count_src,
    -
    589 _In_ size_t what = 0)
    -
    590 {
    -
    591 wstr2sgmlcat(dst, src, count_src, what);
    -
    592 }
    -
    593
    -
    601 inline void wstr2sgmlcat(
    -
    602 _Inout_ std::string& dst,
    -
    603 _In_ const std::wstring& src,
    -
    604 _In_ size_t what = 0)
    -
    605 {
    -
    606 wstr2sgmlcat(dst, src.c_str(), src.size(), what);
    -
    607 }
    -
    608
    -
    609 _Deprecated_("Use stdex::wstr2sgmlcat")
    -
    610 inline void wstr2sgml(
    -
    611 _Inout_ std::string& dst,
    -
    612 _In_ const std::wstring& src,
    -
    613 _In_ size_t what = 0)
    -
    614 {
    -
    615 wstr2sgmlcat(dst, src, what);
    -
    616 }
    -
    617
    -
    629 inline size_t wstr2sgmlcat(
    -
    630 _Inout_cap_(count_dst) char* dst, _In_ size_t count_dst,
    -
    631 _In_reads_or_z_opt_(count_src) const wchar_t* src, _In_ size_t count_src,
    -
    632 _In_ size_t what = 0)
    -
    633 {
    -
    634 _Assume_(dst || !count_dst);
    -
    635 _Assume_(src || !count_src);
    -
    636
    -
    637 static const std::invalid_argument buffer_overrun("buffer overrun");
    -
    638 const bool
    -
    639 do_ascii = (what & sgml_full) == 0,
    -
    640 do_quot = (what & sgml_quot) == 0,
    -
    641 do_apos = (what & sgml_apos) == 0,
    -
    642 do_lt_gt = (what & sgml_lt_gt) == 0,
    -
    643 do_bsol = (what & sgml_bsol) == 0,
    -
    644 do_dollar = (what & sgml_dollar) == 0,
    -
    645 do_percnt = (what & sgml_percnt) == 0,
    -
    646 do_commat = (what & sgml_commat) == 0,
    -
    647 do_num = (what & sgml_num) == 0,
    -
    648 do_lpar_rpar = (what & sgml_lpar_rpar) == 0,
    -
    649 do_lcub_rcub = (what & sgml_lcub_rcub) == 0,
    -
    650 do_lsqb_rsqb = (what & sgml_lsqb_rsqb) == 0;
    -
    651
    -
    652 size_t j = strnlen(dst, count_dst);
    -
    653 count_src = wcsnlen(src, count_src);
    -
    654 for (size_t i = 0; i < count_src;) {
    -
    655 size_t n = glyphlen(src + i, count_src - i);
    -
    656 if (n == 1 &&
    -
    657 do_ascii && (unsigned int)src[i] < 128 &&
    -
    658 src[i] != L'&' &&
    -
    659 (do_quot || (src[i] != L'"')) &&
    -
    660 (do_apos || (src[i] != L'\'')) &&
    -
    661 (do_lt_gt || (src[i] != L'<' && src[i] != L'>')) &&
    -
    662 (do_bsol || (src[i] != L'\\')) &&
    -
    663 (do_dollar || (src[i] != L'$')) &&
    -
    664 (do_percnt || (src[i] != L'%')) &&
    -
    665 (do_commat || (src[i] != L'@')) &&
    -
    666 (do_num || (src[i] != L'#')) &&
    -
    667 (do_lpar_rpar || (src[i] != L'(' && src[i] != L')')) &&
    -
    668 (do_lcub_rcub || (src[i] != L'{' && src[i] != L'}')) &&
    -
    669 (do_lsqb_rsqb || (src[i] != L'[' && src[i] != L']')))
    -
    670 {
    -
    671 // 7-bit ASCII and no desire to encode it as an SGML entity.
    -
    672 if (j + 1 >= count_dst)
    -
    673 throw buffer_overrun;
    -
    674 dst[j++] = static_cast<char>(src[i++]);
    -
    675 }
    -
    676 else {
    -
    677 const char* entity = chr2sgml(src + i, n);
    -
    678 if (entity) {
    -
    679 size_t m = strlen(entity);
    -
    680 if (j + m + 2 >= count_dst)
    -
    681 throw buffer_overrun;
    -
    682 dst[j++] = '&';
    -
    683 memcpy(dst + j, entity, m * sizeof(char)); j += m;
    -
    684 dst[j++] = ';';
    -
    685 i += n;
    -
    686 }
    -
    687 else if (n == 1) {
    -
    688 // Trivial character (1 code unit, 1 glyph), no entity available.
    -
    689 if ((unsigned int)src[i] < 128) {
    -
    690 if (j + 1 >= count_dst)
    -
    691 throw buffer_overrun;
    -
    692 dst[j++] = static_cast<char>(src[i++]);
    -
    693 }
    -
    694 else {
    -
    695 char tmp[3 + 8 + 1 + 1];
    -
    696 int m = snprintf(tmp, _countof(tmp), "&#x%x;", src[i++]);
    -
    697 _Assume_(m >= 0);
    -
    698 if (static_cast<size_t>(m) >= count_dst)
    -
    699 throw buffer_overrun;
    -
    700 memcpy(dst + j, tmp, m * sizeof(char)); j += m;
    -
    701 }
    -
    702 }
    -
    703 else {
    -
    704 // Non-trivial character. Decompose.
    -
    705 const size_t end = i + n;
    -
    706 while (i < end) {
    -
    707 if ((entity = chr2sgml(src + i, 1)) != nullptr) {
    -
    708 size_t m = strlen(entity);
    -
    709 if (j + m + 2 >= count_dst)
    -
    710 throw buffer_overrun;
    -
    711 dst[j++] = '&';
    -
    712 memcpy(dst + j, entity, m * sizeof(char)); j += m;
    -
    713 dst[j++] = ';';
    -
    714 i++;
    -
    715 }
    -
    716 else if ((unsigned int)src[i] < 128) {
    -
    717 if (j + 1 >= count_dst)
    -
    718 throw buffer_overrun;
    -
    719 dst[j++] = static_cast<char>(src[i++]);
    -
    720 }
    -
    721 else {
    -
    722 uint32_t unicode;
    -
    723#ifdef _WIN32
    -
    724 if (i + 1 < end && is_surrogate_pair(src + i)) {
    -
    725 unicode = surrogate_pair_to_ucs4(src + i);
    -
    726 i += 2;
    -
    727 }
    -
    728 else
    -
    729#endif
    -
    730 {
    -
    731 unicode = src[i++];
    -
    732 }
    -
    733 char tmp[3 + 8 + 1 + 1];
    -
    734 int m = snprintf(tmp, _countof(tmp), "&#x%x;", unicode);
    -
    735 _Assume_(m >= 0);
    -
    736 if (static_cast<size_t>(m) >= count_dst)
    -
    737 throw buffer_overrun;
    -
    738 memcpy(dst + j, tmp, m * sizeof(char)); j += m;
    -
    739 }
    -
    740 }
    -
    741 }
    -
    742 }
    -
    743 }
    -
    744 if (j >= count_dst)
    -
    745 throw buffer_overrun;
    -
    746 dst[j] = 0;
    -
    747 return j;
    -
    748 }
    -
    749
    -
    750 _Deprecated_("Use stdex::wstr2sgmlcat")
    -
    751 inline size_t wstr2sgml(
    -
    752 _Inout_cap_(count_dst) char* dst, _In_ size_t count_dst,
    -
    753 _In_reads_or_z_opt_(count_src) const wchar_t* src, _In_ size_t count_src,
    -
    754 _In_ size_t what = 0)
    -
    755 {
    -
    756 return wstr2sgmlcat(dst, count_dst, src, count_src, what);
    -
    757 }
    -
    758
    -
    767 inline void wstr2sgmlcpy(
    -
    768 _Inout_ std::string& dst,
    -
    769 _In_reads_or_z_opt_(count_src) const wchar_t* src, _In_ size_t count_src,
    -
    770 _In_ size_t what = 0)
    -
    771 {
    -
    772 dst.clear();
    -
    773 wstr2sgmlcat(dst, src, count_src, what);
    -
    774 }
    -
    775
    -
    783 inline void wstr2sgmlcpy(
    -
    784 _Inout_ std::string& dst,
    -
    785 _In_ const std::wstring& src,
    -
    786 _In_ size_t what = 0)
    -
    787 {
    -
    788 wstr2sgmlcpy(dst, src.data(), src.size(), what);
    -
    789 }
    -
    790
    -
    802 inline size_t wstr2sgmlcpy(
    -
    803 _Inout_cap_(count_dst) char* dst, _In_ size_t count_dst,
    -
    804 _In_reads_or_z_opt_(count_src) const wchar_t* src, _In_ size_t count_src,
    -
    805 _In_ size_t what = 0)
    -
    806 {
    -
    807 _Assume_(dst || !count_dst);
    -
    808 if (count_dst)
    -
    809 dst[0] = 0;
    -
    810 return wstr2sgmlcat(dst, count_dst, src, count_src, what);
    -
    811 }
    -
    812
    -
    822 inline std::string wstr2sgml(
    -
    823 _In_reads_or_z_opt_(count_src) const wchar_t* src, _In_ size_t count_src,
    -
    824 _In_ size_t what = 0)
    -
    825 {
    -
    826 std::string dst;
    -
    827 wstr2sgmlcat(dst, src, count_src, what);
    -
    828 return dst;
    -
    829 }
    -
    830
    -
    839 inline std::string wstr2sgml(
    -
    840 _In_ const std::wstring& src,
    -
    841 _In_ size_t what = 0)
    -
    842 {
    -
    843 return wstr2sgml(src.c_str(), src.size(), what);
    -
    844 }
    -
    845}
    +
    12#include <string.h>
    +
    13#include <exception>
    +
    14#include <string>
    +
    15
    +
    16namespace stdex
    +
    17{
    +
    19 template <class T>
    +
    20 inline const wchar_t* sgml2uni(_In_reads_or_z_(count) const T* entity, _In_ size_t count)
    +
    21 {
    +
    22 _Assume_(entity && count);
    +
    23 _Assume_(count < 2 || entity[0] != '#'); // No numeric entities
    +
    24
    +
    25 for (size_t i = 0, j = _countof(sgml_unicode); i < j; ) {
    +
    26 size_t m = (i + j) / 2;
    +
    27 if (sgml_unicode[m].sgml[0] < entity[0])
    +
    28 i = m + 1;
    +
    29 else if (sgml_unicode[m].sgml[0] > entity[0])
    +
    30 j = m;
    +
    31 else {
    +
    32 auto r = strncmp<char, T>(sgml_unicode[m].sgml + 1, _countof(sgml_unicode[0].sgml) - 1, entity + 1, count - 1);
    +
    33 if (r < 0)
    +
    34 i = m + 1;
    +
    35 else if (r > 0)
    +
    36 j = m;
    +
    37 else {
    +
    38 for (; i < m && strncmp<char, T>(sgml_unicode[m - 1].sgml, _countof(sgml_unicode[0].sgml), entity, count) == 0; m--);
    +
    39 return sgml_unicode[m].unicode;
    +
    40 }
    +
    41 }
    +
    42 }
    +
    43 return nullptr;
    +
    44 }
    +
    45
    +
    46 template <class T>
    +
    47 inline const T* sgmlend(
    +
    48 _In_reads_or_z_opt_(count) const T* str, _In_ size_t count)
    +
    49 {
    +
    50 _Assume_(str || !count);
    +
    51 for (size_t i = 0; i < count; i++) {
    +
    52 if (str[i] == ';')
    +
    53 return str + i;
    +
    54 if (!str[i] || str[i] == '&' || isspace(str[i]))
    +
    55 break;
    +
    56 }
    +
    57 return nullptr;
    +
    58 }
    +
    60
    +
    61 constexpr int sgml_full = 0x80000000;
    +
    62 constexpr int sgml_quot = 0x00000001;
    +
    63 constexpr int sgml_apos = 0x00000002;
    +
    64 constexpr int sgml_quot_apos = sgml_quot | sgml_apos;
    +
    65 constexpr int sgml_amp = 0x00000004;
    +
    66 constexpr int sgml_lt_gt = 0x00000008;
    +
    67 constexpr int sgml_bsol = 0x00000010;
    +
    68 constexpr int sgml_dollar = 0x00000020;
    +
    69 constexpr int sgml_percnt = 0x00000040;
    +
    70 constexpr int sgml_commat = 0x00000080;
    +
    71 constexpr int sgml_num = 0x00000100;
    +
    72 constexpr int sgml_lpar_rpar = 0x00000200;
    +
    73 constexpr int sgml_lcub_rcub = 0x00000400;
    +
    74 constexpr int sgml_lsqb_rsqb = 0x00000800;
    +
    75 constexpr int sgml_sgml = sgml_amp | sgml_lt_gt;
    +
    76 constexpr int sgml_ml_attrib = sgml_amp | sgml_quot_apos;
    +
    77 constexpr int sgml_c = sgml_amp | sgml_bsol | sgml_quot_apos;
    +
    78 // constexpr int sgml_ajt_lemma = sgml_amp | sgml_quot | sgml_dollar | sgml_percnt;
    +
    79 // constexpr int sgml_ajt_form = sgml_ajt_lemma;
    +
    80 // constexpr int sgml_kolos = sgml_amp | sgml_quot | sgml_dollar | sgml_percnt | sgml_lt_gt | sgml_bsol/* | sgml_commat | sgml_num*/ | sgml_lpar_rpar | sgml_lcub_rcub | sgml_lsqb_rsqb;
    +
    81
    +
    92 template <class T>
    +
    93 inline void sgml2wstrcat(
    +
    94 _Inout_ std::wstring& dst,
    +
    95 _In_reads_or_z_opt_(count_src) const T* src, _In_ size_t count_src,
    +
    96 _In_ int skip = 0,
    +
    97 _In_ const mapping<size_t>& offset = mapping<size_t>(0, 0),
    +
    98 _Inout_opt_ mapping_vector<size_t>* map = nullptr)
    +
    99 {
    +
    100 _Assume_(src || !count_src);
    +
    101
    +
    102 const bool
    +
    103 skip_quot = (skip & sgml_quot) == 0,
    +
    104 skip_apos = (skip & sgml_apos) == 0,
    +
    105 skip_amp = (skip & sgml_amp) == 0,
    +
    106 skip_lt_gt = (skip & sgml_lt_gt) == 0,
    +
    107 skip_bsol = (skip & sgml_bsol) == 0,
    +
    108 skip_dollar = (skip & sgml_dollar) == 0,
    +
    109 skip_percnt = (skip & sgml_percnt) == 0,
    +
    110 skip_commat = (skip & sgml_commat) == 0,
    +
    111 skip_num = (skip & sgml_num) == 0,
    +
    112 skip_lpar_rpar = (skip & sgml_lpar_rpar) == 0,
    +
    113 skip_lcub_rcub = (skip & sgml_lcub_rcub) == 0,
    +
    114 skip_lsqb_rsqb = (skip & sgml_lsqb_rsqb) == 0;
    +
    115
    +
    116 count_src = strnlen(src, count_src);
    +
    117 dst.reserve(dst.size() + count_src);
    +
    118 for (size_t i = 0; i < count_src;) {
    +
    119 if (src[i] == '&') {
    +
    120 auto end = sgmlend(src + i + 1, count_src - i - 1);
    +
    121 if (end) {
    +
    122 const wchar_t* entity_w;
    +
    123 wchar_t chr[3];
    +
    124 size_t n = end - src - i - 1;
    +
    125 if (n >= 2 && src[i + 1] == '#') {
    +
    126 uint32_t unicode;
    +
    127 if (src[i + 2] == 'x' || src[i + 2] == 'X')
    +
    128 unicode = strtou32(src + i + 3, n - 2, nullptr, 16);
    +
    129 else
    +
    130 unicode = strtou32(src + i + 2, n - 1, nullptr, 10);
    +
    131#ifdef _WIN32
    +
    132 if (unicode < 0x10000) {
    +
    133 chr[0] = (wchar_t)unicode;
    +
    134 chr[1] = 0;
    +
    135 }
    +
    136 else {
    +
    137 ucs4_to_surrogate_pair(chr, unicode);
    +
    138 chr[2] = 0;
    +
    139 }
    +
    140#else
    +
    141 chr[0] = (wchar_t)unicode;
    +
    142 chr[1] = 0;
    +
    143#endif
    +
    144 entity_w = chr;
    +
    145 }
    +
    146 else
    +
    147 entity_w = sgml2uni(src + i + 1, n);
    +
    148
    +
    149 if (entity_w &&
    +
    150 (skip_quot || (entity_w[0] != L'"')) &&
    +
    151 (skip_apos || (entity_w[0] != L'\'')) &&
    +
    152 (skip_amp || (entity_w[0] != L'&')) &&
    +
    153 (skip_lt_gt || (entity_w[0] != L'<' && entity_w[0] != L'>')) &&
    +
    154 (skip_bsol || (entity_w[0] != L'\\')) &&
    +
    155 (skip_dollar || (entity_w[0] != L'$')) &&
    +
    156 (skip_percnt || (entity_w[0] != L'%')) &&
    +
    157 (skip_commat || (entity_w[0] != L'@')) &&
    +
    158 (skip_num || (entity_w[0] != L'#')) &&
    +
    159 (skip_lpar_rpar || (entity_w[0] != L'(' && entity_w[0] != L')')) &&
    +
    160 (skip_lcub_rcub || (entity_w[0] != L'{' && entity_w[0] != L'}')) &&
    +
    161 (skip_lsqb_rsqb || (entity_w[0] != L'[' && entity_w[0] != L']')))
    +
    162 {
    +
    163 if (map) map->push_back(mapping<size_t>(offset.from + i, offset.to + dst.size()));
    +
    164 dst.append(entity_w);
    +
    165 i = end - src + 1;
    +
    166 if (map) map->push_back(mapping<size_t>(offset.from + i, offset.to + dst.size()));
    +
    167 continue;
    +
    168 }
    +
    169 }
    +
    170 }
    +
    171 dst.append(1, src[i++]);
    +
    172 }
    +
    173 }
    +
    174
    +
    175 template <class T>
    +
    176 _Deprecated_("Use stdex::sgml2wstrcat")
    +
    177 inline void sgml2wstr(
    +
    178 _Inout_ std::wstring& dst,
    +
    179 _In_reads_or_z_opt_(count_src) const T* src, _In_ size_t count_src,
    +
    180 _In_ int skip = 0,
    +
    181 _In_ const mapping<size_t>& offset = mapping<size_t>(0, 0),
    +
    182 _Inout_opt_ mapping_vector<size_t>* map = nullptr)
    +
    183 {
    +
    184 sgml2wstrcat(dst, src, count_src, skip, offset, map);
    +
    185 }
    +
    186
    +
    196 template <class T>
    +
    197 inline void sgml2wstrcat(
    +
    198 _Inout_ std::wstring& dst,
    +
    199 _In_ const std::basic_string<T>& src,
    +
    200 _In_ int skip = 0,
    +
    201 _In_ const mapping<size_t>& offset = mapping<size_t>(0, 0),
    +
    202 _Inout_opt_ mapping_vector<size_t>* map = nullptr)
    +
    203 {
    +
    204 sgml2wstrcat(dst, src.data(), src.size(), skip, offset, map);
    +
    205 }
    +
    206
    +
    207 template <class T>
    +
    208 _Deprecated_("Use stdex::sgml2wstrcat")
    +
    209 inline void sgml2wstr(
    +
    210 _Inout_ std::wstring& dst,
    +
    211 _In_ const std::basic_string<T>& src,
    +
    212 _In_ int skip = 0,
    +
    213 _In_ const mapping<size_t>& offset = mapping<size_t>(0, 0),
    +
    214 _Inout_opt_ mapping_vector<size_t>* map = nullptr)
    +
    215 {
    +
    216 sgml2wstrcat(dst, src, skip, offset, map);
    +
    217 }
    +
    218
    +
    232 template <class T>
    +
    233 inline size_t sgml2wstrcat(
    +
    234 _Inout_cap_(count_dst) wchar_t* dst, _In_ size_t count_dst,
    +
    235 _In_reads_or_z_opt_(count_src) const T* src, _In_ size_t count_src,
    +
    236 _In_ int skip = 0,
    +
    237 _In_ const mapping<size_t>& offset = mapping<size_t>(0, 0),
    +
    238 _Inout_opt_ mapping_vector<size_t>* map = nullptr)
    +
    239 {
    +
    240 _Assume_(dst || !count_dst);
    +
    241 _Assume_(src || !count_src);
    +
    242
    +
    243 static const std::invalid_argument buffer_overrun("buffer overrun");
    +
    244 const bool
    +
    245 skip_quot = (skip & sgml_quot) == 0,
    +
    246 skip_apos = (skip & sgml_apos) == 0,
    +
    247 skip_amp = (skip & sgml_amp) == 0,
    +
    248 skip_lt_gt = (skip & sgml_lt_gt) == 0,
    +
    249 skip_bsol = (skip & sgml_bsol) == 0,
    +
    250 skip_dollar = (skip & sgml_dollar) == 0,
    +
    251 skip_percnt = (skip & sgml_percnt) == 0,
    +
    252 skip_commat = (skip & sgml_commat) == 0,
    +
    253 skip_num = (skip & sgml_num) == 0,
    +
    254 skip_lpar_rpar = (skip & sgml_lpar_rpar) == 0,
    +
    255 skip_lcub_rcub = (skip & sgml_lcub_rcub) == 0,
    +
    256 skip_lsqb_rsqb = (skip & sgml_lsqb_rsqb) == 0;
    +
    257
    +
    258 size_t j = wcsnlen(dst, count_dst);
    +
    259 count_src = strnlen(src, count_src);
    +
    260 for (size_t i = 0; i < count_src;) {
    +
    261 if (src[i] == '&') {
    +
    262 auto end = sgmlend(src + i + 1, count_src - i - 1);
    +
    263 if (end) {
    +
    264 const wchar_t* entity_w;
    +
    265 wchar_t chr[3];
    +
    266 size_t n = end - src - i - 1;
    +
    267 if (n >= 2 && src[i + 1] == '#') {
    +
    268 uint32_t unicode;
    +
    269 if (src[i + 2] == 'x' || src[i + 2] == 'X')
    +
    270 unicode = strtou32(src + i + 3, n - 2, nullptr, 16);
    +
    271 else
    +
    272 unicode = strtou32(src + i + 2, n - 1, nullptr, 10);
    +
    273#ifdef _WIN32
    +
    274 if (unicode < 0x10000) {
    +
    275 chr[0] = (wchar_t)unicode;
    +
    276 chr[1] = 0;
    +
    277 }
    +
    278 else {
    +
    279 ucs4_to_surrogate_pair(chr, unicode);
    +
    280 chr[2] = 0;
    +
    281 }
    +
    282#else
    +
    283 chr[0] = (wchar_t)unicode;
    +
    284 chr[1] = 0;
    +
    285#endif
    +
    286 entity_w = chr;
    +
    287 }
    +
    288 else
    +
    289 entity_w = sgml2uni(src + i + 1, n);
    +
    290
    +
    291 if (entity_w &&
    +
    292 (skip_quot || (entity_w[0] != L'"')) &&
    +
    293 (skip_apos || (entity_w[0] != L'\'')) &&
    +
    294 (skip_amp || (entity_w[0] != L'&')) &&
    +
    295 (skip_lt_gt || (entity_w[0] != L'<' && entity_w[0] != L'>')) &&
    +
    296 (skip_bsol || (entity_w[0] != L'\\')) &&
    +
    297 (skip_dollar || (entity_w[0] != L'$')) &&
    +
    298 (skip_percnt || (entity_w[0] != L'%')) &&
    +
    299 (skip_commat || (entity_w[0] != L'@')) &&
    +
    300 (skip_num || (entity_w[0] != L'#')) &&
    +
    301 (skip_lpar_rpar || (entity_w[0] != L'(' && entity_w[0] != L')')) &&
    +
    302 (skip_lcub_rcub || (entity_w[0] != L'{' && entity_w[0] != L'}')) &&
    +
    303 (skip_lsqb_rsqb || (entity_w[0] != L'[' && entity_w[0] != L']')))
    +
    304 {
    +
    305 if (map) map->push_back(mapping<size_t>(offset.from + i, offset.to + j));
    +
    306 size_t m = wcslen(entity_w);
    +
    307 if (j + m >= count_dst)
    +
    308 throw buffer_overrun;
    +
    309 memcpy(dst + j, entity_w, m * sizeof(wchar_t)); j += m;
    +
    310 i = end - src + 1;
    +
    311 if (map) map->push_back(mapping<size_t>(offset.from + i, offset.to + j));
    +
    312 continue;
    +
    313 }
    +
    314 }
    +
    315 }
    +
    316 if (j + 1 >= count_dst)
    +
    317 throw buffer_overrun;
    +
    318 dst[j++] = src[i++];
    +
    319 }
    +
    320 if (j >= count_dst)
    +
    321 throw buffer_overrun;
    +
    322 dst[j] = 0;
    +
    323 return j;
    +
    324 }
    +
    325
    +
    326 template <class T>
    +
    327 _Deprecated_("Use stdex::sgml2wstrcat")
    +
    328 inline size_t sgml2wstr(
    +
    329 _Inout_cap_(count_dst) wchar_t* dst, _In_ size_t count_dst,
    +
    330 _In_reads_or_z_opt_(count_src) const T* src, _In_ size_t count_src,
    +
    331 _In_ int skip = 0,
    +
    332 _In_ const mapping<size_t>& offset = mapping<size_t>(0, 0),
    +
    333 _Inout_opt_ mapping_vector<size_t>* map = nullptr)
    +
    334 {
    +
    335 return sgml2wstrcat(dst, count_dst, src, count_src, skip, offset, map);
    +
    336 }
    +
    337
    +
    348 template <class T>
    +
    349 inline void sgml2wstrcpy(
    +
    350 _Inout_ std::wstring& dst,
    +
    351 _In_reads_or_z_opt_(count_src) const T* src, _In_ size_t count_src,
    +
    352 _In_ int skip = 0,
    +
    353 _In_ const mapping<size_t>& offset = mapping<size_t>(0, 0),
    +
    354 _Inout_opt_ mapping_vector<size_t>* map = nullptr)
    +
    355 {
    +
    356 dst.clear();
    +
    357 if (map)
    +
    358 map->clear();
    +
    359 sgml2wstrcat(dst, src, count_src, skip, offset, map);
    +
    360 }
    +
    361
    +
    371 template<class _Elem, class _Traits, class _Ax>
    +
    372 inline void sgml2wstrcpy(
    +
    373 _Inout_ std::wstring& dst,
    +
    374 _In_ const std::basic_string<_Elem, _Traits, _Ax>& src,
    +
    375 _In_ int skip = 0,
    +
    376 _In_ const mapping<size_t>& offset = mapping<size_t>(0, 0),
    +
    377 _Inout_opt_ mapping_vector<size_t>* map = nullptr)
    +
    378 {
    +
    379 sgml2wstrcpy(dst, src.data(), src.size(), skip, offset, map);
    +
    380 }
    +
    381
    +
    395 template <class T>
    +
    396 inline size_t sgml2wstrcpy(
    +
    397 _Inout_cap_(count_dst) wchar_t* dst, _In_ size_t count_dst,
    +
    398 _In_reads_or_z_opt_(count_src) const T* src, _In_ size_t count_src,
    +
    399 _In_ int skip = 0,
    +
    400 _In_ const mapping<size_t>& offset = mapping<size_t>(0, 0),
    +
    401 _Inout_opt_ mapping_vector<size_t>* map = nullptr)
    +
    402 {
    +
    403 _Assume_(dst || !count_dst);
    +
    404 if (count_dst)
    +
    405 dst[0] = 0;
    +
    406 if (map)
    +
    407 map->clear();
    +
    408 return sgml2wstrcat(dst, count_dst, src, count_src, skip, offset, map);
    +
    409 }
    +
    410
    +
    422 template <class T>
    +
    423 inline std::wstring sgml2wstr(
    +
    424 _In_reads_or_z_opt_(count_src) const T* src, _In_ size_t count_src,
    +
    425 _In_ int skip = 0,
    +
    426 _In_ const mapping<size_t>& offset = mapping<size_t>(0, 0),
    +
    427 _Inout_opt_ mapping_vector<size_t>* map = nullptr)
    +
    428 {
    +
    429 std::wstring dst;
    +
    430 sgml2wstrcat(dst, src, count_src, skip, offset, map);
    +
    431 return dst;
    +
    432 }
    +
    433
    +
    444 template <class T>
    +
    445 inline std::wstring sgml2wstr(
    +
    446 _In_ const std::basic_string<T>& src,
    +
    447 _In_ int skip = 0,
    +
    448 _In_ const mapping<size_t>& offset = mapping<size_t>(0, 0),
    +
    449 _Inout_opt_ mapping_vector<size_t>* map = nullptr)
    +
    450 {
    +
    451 return sgml2wstr(src.c_str(), src.size(), skip, offset, map);
    +
    452 }
    +
    453
    +
    455 inline const char* chr2sgml(_In_reads_or_z_(count) const wchar_t* entity, _In_ size_t count)
    +
    456 {
    +
    457 _Assume_(entity && count);
    +
    458
    +
    459 const wchar_t e2 = entity[0];
    +
    460 for (size_t i = 0, j = _countof(unicode_sgml); i < j; ) {
    +
    461 size_t m = (i + j) / 2;
    +
    462 wchar_t e1 = sgml_unicode[unicode_sgml[m]].unicode[0];
    +
    463 if (e1 < e2)
    +
    464 i = m + 1;
    +
    465 else if (e1 > e2)
    +
    466 j = m;
    +
    467 else {
    +
    468 auto r = strncmp(sgml_unicode[unicode_sgml[m]].unicode + 1, _countof(sgml_unicode[0].unicode) - 1, entity + 1, count - 1);
    +
    469 if (r < 0)
    +
    470 i = m + 1;
    +
    471 else if (r > 0)
    +
    472 j = m;
    +
    473 else {
    +
    474 for (; i < m && sgml_unicode[unicode_sgml[m - 1]].unicode[0] == e2 && strncmp(sgml_unicode[unicode_sgml[m - 1]].unicode + 1, _countof(sgml_unicode[0].unicode) - 1, entity + 1, count - 1) == 0; m--);
    +
    475 return sgml_unicode[unicode_sgml[m]].sgml;
    +
    476 }
    +
    477 }
    +
    478 }
    +
    479 return nullptr;
    +
    480 }
    +
    482
    +
    491 inline void wstr2sgmlcat(
    +
    492 _Inout_ std::string& dst,
    +
    493 _In_reads_or_z_opt_(count_src) const wchar_t* src, _In_ size_t count_src,
    +
    494 _In_ size_t what = 0)
    +
    495 {
    +
    496 _Assume_(src || !count_src);
    +
    497
    +
    498 const bool
    +
    499 do_ascii = (what & sgml_full) == 0,
    +
    500 do_quot = (what & sgml_quot) == 0,
    +
    501 do_apos = (what & sgml_apos) == 0,
    +
    502 do_lt_gt = (what & sgml_lt_gt) == 0,
    +
    503 do_bsol = (what & sgml_bsol) == 0,
    +
    504 do_dollar = (what & sgml_dollar) == 0,
    +
    505 do_percnt = (what & sgml_percnt) == 0,
    +
    506 do_commat = (what & sgml_commat) == 0,
    +
    507 do_num = (what & sgml_num) == 0,
    +
    508 do_lpar_rpar = (what & sgml_lpar_rpar) == 0,
    +
    509 do_lcub_rcub = (what & sgml_lcub_rcub) == 0,
    +
    510 do_lsqb_rsqb = (what & sgml_lsqb_rsqb) == 0;
    +
    511
    +
    512 count_src = wcsnlen(src, count_src);
    +
    513 dst.reserve(dst.size() + count_src);
    +
    514 for (size_t i = 0; i < count_src;) {
    +
    515 size_t n = glyphlen(src + i, count_src - i);
    +
    516 if (n == 1 &&
    +
    517 do_ascii && (unsigned int)src[i] < 128 &&
    +
    518 src[i] != L'&' &&
    +
    519 (do_quot || (src[i] != L'"')) &&
    +
    520 (do_apos || (src[i] != L'\'')) &&
    +
    521 (do_lt_gt || (src[i] != L'<' && src[i] != L'>')) &&
    +
    522 (do_bsol || (src[i] != L'\\')) &&
    +
    523 (do_dollar || (src[i] != L'$')) &&
    +
    524 (do_percnt || (src[i] != L'%')) &&
    +
    525 (do_commat || (src[i] != L'@')) &&
    +
    526 (do_num || (src[i] != L'#')) &&
    +
    527 (do_lpar_rpar || (src[i] != L'(' && src[i] != L')')) &&
    +
    528 (do_lcub_rcub || (src[i] != L'{' && src[i] != L'}')) &&
    +
    529 (do_lsqb_rsqb || (src[i] != L'[' && src[i] != L']')))
    +
    530 {
    +
    531 // 7-bit ASCII and no desire to encode it as an SGML entity.
    +
    532 dst.append(1, static_cast<char>(src[i++]));
    +
    533 }
    +
    534 else {
    +
    535 const char* entity = chr2sgml(src + i, n);
    +
    536 if (entity) {
    +
    537 dst.append(1, '&');
    +
    538 dst.append(entity);
    +
    539 dst.append(1, ';');
    +
    540 i += n;
    +
    541 }
    +
    542 else if (n == 1) {
    +
    543 // Trivial character (1 code unit, 1 glyph), no entity available.
    +
    544 if ((unsigned int)src[i] < 128)
    +
    545 dst.append(1, static_cast<char>(src[i++]));
    +
    546 else {
    +
    547 char tmp[3 + 8 + 1 + 1];
    +
    548 snprintf(tmp, _countof(tmp), "&#x%x;", src[i++]);
    +
    549 dst.append(tmp);
    +
    550 }
    +
    551 }
    +
    552 else {
    +
    553 // Non-trivial character. Decompose.
    +
    554 const size_t end = i + n;
    +
    555 while (i < end) {
    +
    556 if ((entity = chr2sgml(src + i, 1)) != nullptr) {
    +
    557 dst.append(1, '&');
    +
    558 dst.append(entity);
    +
    559 dst.append(1, ';');
    +
    560 i++;
    +
    561 }
    +
    562 else if ((unsigned int)src[i] < 128)
    +
    563 dst.append(1, static_cast<char>(src[i++]));
    +
    564 else {
    +
    565 uint32_t unicode;
    +
    566#ifdef _WIN32
    +
    567 if (i + 1 < end && is_surrogate_pair(src + i)) {
    +
    568 unicode = surrogate_pair_to_ucs4(src + i);
    +
    569 i += 2;
    +
    570 }
    +
    571 else
    +
    572#endif
    +
    573 {
    +
    574 unicode = src[i++];
    +
    575 }
    +
    576 char tmp[3 + 8 + 1 + 1];
    +
    577 snprintf(tmp, _countof(tmp), "&#x%x;", unicode);
    +
    578 dst.append(tmp);
    +
    579 }
    +
    580 }
    +
    581 }
    +
    582 }
    +
    583 }
    +
    584 }
    +
    585
    +
    586 _Deprecated_("Use stdex::wstr2sgmlcat")
    +
    587 inline void wstr2sgml(
    +
    588 _Inout_ std::string& dst,
    +
    589 _In_reads_or_z_opt_(count_src) const wchar_t* src, _In_ size_t count_src,
    +
    590 _In_ size_t what = 0)
    +
    591 {
    +
    592 wstr2sgmlcat(dst, src, count_src, what);
    +
    593 }
    +
    594
    +
    602 inline void wstr2sgmlcat(
    +
    603 _Inout_ std::string& dst,
    +
    604 _In_ const std::wstring& src,
    +
    605 _In_ size_t what = 0)
    +
    606 {
    +
    607 wstr2sgmlcat(dst, src.c_str(), src.size(), what);
    +
    608 }
    +
    609
    +
    610 _Deprecated_("Use stdex::wstr2sgmlcat")
    +
    611 inline void wstr2sgml(
    +
    612 _Inout_ std::string& dst,
    +
    613 _In_ const std::wstring& src,
    +
    614 _In_ size_t what = 0)
    +
    615 {
    +
    616 wstr2sgmlcat(dst, src, what);
    +
    617 }
    +
    618
    +
    630 inline size_t wstr2sgmlcat(
    +
    631 _Inout_cap_(count_dst) char* dst, _In_ size_t count_dst,
    +
    632 _In_reads_or_z_opt_(count_src) const wchar_t* src, _In_ size_t count_src,
    +
    633 _In_ size_t what = 0)
    +
    634 {
    +
    635 _Assume_(dst || !count_dst);
    +
    636 _Assume_(src || !count_src);
    +
    637
    +
    638 static const std::invalid_argument buffer_overrun("buffer overrun");
    +
    639 const bool
    +
    640 do_ascii = (what & sgml_full) == 0,
    +
    641 do_quot = (what & sgml_quot) == 0,
    +
    642 do_apos = (what & sgml_apos) == 0,
    +
    643 do_lt_gt = (what & sgml_lt_gt) == 0,
    +
    644 do_bsol = (what & sgml_bsol) == 0,
    +
    645 do_dollar = (what & sgml_dollar) == 0,
    +
    646 do_percnt = (what & sgml_percnt) == 0,
    +
    647 do_commat = (what & sgml_commat) == 0,
    +
    648 do_num = (what & sgml_num) == 0,
    +
    649 do_lpar_rpar = (what & sgml_lpar_rpar) == 0,
    +
    650 do_lcub_rcub = (what & sgml_lcub_rcub) == 0,
    +
    651 do_lsqb_rsqb = (what & sgml_lsqb_rsqb) == 0;
    +
    652
    +
    653 size_t j = strnlen(dst, count_dst);
    +
    654 count_src = wcsnlen(src, count_src);
    +
    655 for (size_t i = 0; i < count_src;) {
    +
    656 size_t n = glyphlen(src + i, count_src - i);
    +
    657 if (n == 1 &&
    +
    658 do_ascii && (unsigned int)src[i] < 128 &&
    +
    659 src[i] != L'&' &&
    +
    660 (do_quot || (src[i] != L'"')) &&
    +
    661 (do_apos || (src[i] != L'\'')) &&
    +
    662 (do_lt_gt || (src[i] != L'<' && src[i] != L'>')) &&
    +
    663 (do_bsol || (src[i] != L'\\')) &&
    +
    664 (do_dollar || (src[i] != L'$')) &&
    +
    665 (do_percnt || (src[i] != L'%')) &&
    +
    666 (do_commat || (src[i] != L'@')) &&
    +
    667 (do_num || (src[i] != L'#')) &&
    +
    668 (do_lpar_rpar || (src[i] != L'(' && src[i] != L')')) &&
    +
    669 (do_lcub_rcub || (src[i] != L'{' && src[i] != L'}')) &&
    +
    670 (do_lsqb_rsqb || (src[i] != L'[' && src[i] != L']')))
    +
    671 {
    +
    672 // 7-bit ASCII and no desire to encode it as an SGML entity.
    +
    673 if (j + 1 >= count_dst)
    +
    674 throw buffer_overrun;
    +
    675 dst[j++] = static_cast<char>(src[i++]);
    +
    676 }
    +
    677 else {
    +
    678 const char* entity = chr2sgml(src + i, n);
    +
    679 if (entity) {
    +
    680 size_t m = strlen(entity);
    +
    681 if (j + m + 2 >= count_dst)
    +
    682 throw buffer_overrun;
    +
    683 dst[j++] = '&';
    +
    684 memcpy(dst + j, entity, m * sizeof(char)); j += m;
    +
    685 dst[j++] = ';';
    +
    686 i += n;
    +
    687 }
    +
    688 else if (n == 1) {
    +
    689 // Trivial character (1 code unit, 1 glyph), no entity available.
    +
    690 if ((unsigned int)src[i] < 128) {
    +
    691 if (j + 1 >= count_dst)
    +
    692 throw buffer_overrun;
    +
    693 dst[j++] = static_cast<char>(src[i++]);
    +
    694 }
    +
    695 else {
    +
    696 char tmp[3 + 8 + 1 + 1];
    +
    697 int m = snprintf(tmp, _countof(tmp), "&#x%x;", src[i++]);
    +
    698 _Assume_(m >= 0);
    +
    699 if (static_cast<size_t>(m) >= count_dst)
    +
    700 throw buffer_overrun;
    +
    701 memcpy(dst + j, tmp, m * sizeof(char)); j += m;
    +
    702 }
    +
    703 }
    +
    704 else {
    +
    705 // Non-trivial character. Decompose.
    +
    706 const size_t end = i + n;
    +
    707 while (i < end) {
    +
    708 if ((entity = chr2sgml(src + i, 1)) != nullptr) {
    +
    709 size_t m = strlen(entity);
    +
    710 if (j + m + 2 >= count_dst)
    +
    711 throw buffer_overrun;
    +
    712 dst[j++] = '&';
    +
    713 memcpy(dst + j, entity, m * sizeof(char)); j += m;
    +
    714 dst[j++] = ';';
    +
    715 i++;
    +
    716 }
    +
    717 else if ((unsigned int)src[i] < 128) {
    +
    718 if (j + 1 >= count_dst)
    +
    719 throw buffer_overrun;
    +
    720 dst[j++] = static_cast<char>(src[i++]);
    +
    721 }
    +
    722 else {
    +
    723 uint32_t unicode;
    +
    724#ifdef _WIN32
    +
    725 if (i + 1 < end && is_surrogate_pair(src + i)) {
    +
    726 unicode = surrogate_pair_to_ucs4(src + i);
    +
    727 i += 2;
    +
    728 }
    +
    729 else
    +
    730#endif
    +
    731 {
    +
    732 unicode = src[i++];
    +
    733 }
    +
    734 char tmp[3 + 8 + 1 + 1];
    +
    735 int m = snprintf(tmp, _countof(tmp), "&#x%x;", unicode);
    +
    736 _Assume_(m >= 0);
    +
    737 if (static_cast<size_t>(m) >= count_dst)
    +
    738 throw buffer_overrun;
    +
    739 memcpy(dst + j, tmp, m * sizeof(char)); j += m;
    +
    740 }
    +
    741 }
    +
    742 }
    +
    743 }
    +
    744 }
    +
    745 if (j >= count_dst)
    +
    746 throw buffer_overrun;
    +
    747 dst[j] = 0;
    +
    748 return j;
    +
    749 }
    +
    750
    +
    751 _Deprecated_("Use stdex::wstr2sgmlcat")
    +
    752 inline size_t wstr2sgml(
    +
    753 _Inout_cap_(count_dst) char* dst, _In_ size_t count_dst,
    +
    754 _In_reads_or_z_opt_(count_src) const wchar_t* src, _In_ size_t count_src,
    +
    755 _In_ size_t what = 0)
    +
    756 {
    +
    757 return wstr2sgmlcat(dst, count_dst, src, count_src, what);
    +
    758 }
    +
    759
    +
    768 inline void wstr2sgmlcpy(
    +
    769 _Inout_ std::string& dst,
    +
    770 _In_reads_or_z_opt_(count_src) const wchar_t* src, _In_ size_t count_src,
    +
    771 _In_ size_t what = 0)
    +
    772 {
    +
    773 dst.clear();
    +
    774 wstr2sgmlcat(dst, src, count_src, what);
    +
    775 }
    +
    776
    +
    784 inline void wstr2sgmlcpy(
    +
    785 _Inout_ std::string& dst,
    +
    786 _In_ const std::wstring& src,
    +
    787 _In_ size_t what = 0)
    +
    788 {
    +
    789 wstr2sgmlcpy(dst, src.data(), src.size(), what);
    +
    790 }
    +
    791
    +
    803 inline size_t wstr2sgmlcpy(
    +
    804 _Inout_cap_(count_dst) char* dst, _In_ size_t count_dst,
    +
    805 _In_reads_or_z_opt_(count_src) const wchar_t* src, _In_ size_t count_src,
    +
    806 _In_ size_t what = 0)
    +
    807 {
    +
    808 _Assume_(dst || !count_dst);
    +
    809 if (count_dst)
    +
    810 dst[0] = 0;
    +
    811 return wstr2sgmlcat(dst, count_dst, src, count_src, what);
    +
    812 }
    +
    813
    +
    823 inline std::string wstr2sgml(
    +
    824 _In_reads_or_z_opt_(count_src) const wchar_t* src, _In_ size_t count_src,
    +
    825 _In_ size_t what = 0)
    +
    826 {
    +
    827 std::string dst;
    +
    828 wstr2sgmlcat(dst, src, count_src, what);
    +
    829 return dst;
    +
    830 }
    +
    831
    +
    840 inline std::string wstr2sgml(
    +
    841 _In_ const std::wstring& src,
    +
    842 _In_ size_t what = 0)
    +
    843 {
    +
    844 return wstr2sgml(src.c_str(), src.size(), what);
    +
    845 }
    +
    846}
    diff --git a/sgml__unicode_8hpp_source.html b/sgml__unicode_8hpp_source.html index cbc90359c..b89924c74 100644 --- a/sgml__unicode_8hpp_source.html +++ b/sgml__unicode_8hpp_source.html @@ -3175,7 +3175,7 @@ $(document).ready(function() { init_codefold(0); });
    diff --git a/stream_8cpp_source.html b/stream_8cpp_source.html index 22127cba3..d22919ca8 100644 --- a/stream_8cpp_source.html +++ b/stream_8cpp_source.html @@ -243,21 +243,21 @@ $(document).ready(function() { init_codefold(0); });
    159 }
    160 };
    161}
    -
    Provides read-ahead stream capability.
    Definition stream.hpp:1255
    -
    Provides write-back stream capability.
    Definition stream.hpp:1322
    -
    bool ok() const
    Returns true if the stream state is clean i.e. previous operation was succesful.
    Definition stream.hpp:174
    -
    Buffered read/write stream.
    Definition stream.hpp:1393
    -
    Cached file-system file.
    Definition stream.hpp:3094
    -
    File-system file.
    Definition stream.hpp:2690
    -
    static bool readonly(const stdex::schar_t *filename)
    Checks if file/folder/symlink is read-only.
    Definition stream.hpp:3065
    -
    static bool exists(const stdex::schar_t *filename)
    Checks if file/folder/symlink likely exists.
    Definition stream.hpp:3038
    -
    In-memory file.
    Definition stream.hpp:3171
    -
    Replicates writing of the same data to multiple streams.
    Definition stream.hpp:1086
    -
    void push_back(basic *source)
    Adds stream on the list.
    Definition stream.hpp:1105
    +
    Provides read-ahead stream capability.
    Definition stream.hpp:1256
    +
    Provides write-back stream capability.
    Definition stream.hpp:1323
    +
    bool ok() const
    Returns true if the stream state is clean i.e. previous operation was succesful.
    Definition stream.hpp:175
    +
    Buffered read/write stream.
    Definition stream.hpp:1394
    +
    Cached file-system file.
    Definition stream.hpp:3095
    +
    File-system file.
    Definition stream.hpp:2691
    +
    static bool readonly(const stdex::schar_t *filename)
    Checks if file/folder/symlink is read-only.
    Definition stream.hpp:3066
    +
    static bool exists(const stdex::schar_t *filename)
    Checks if file/folder/symlink likely exists.
    Definition stream.hpp:3039
    +
    In-memory file.
    Definition stream.hpp:3172
    +
    Replicates writing of the same data to multiple streams.
    Definition stream.hpp:1087
    +
    void push_back(basic *source)
    Adds stream on the list.
    Definition stream.hpp:1106
    diff --git a/stream_8hpp_source.html b/stream_8hpp_source.html index 14ce83206..b41423744 100644 --- a/stream_8hpp_source.html +++ b/stream_8hpp_source.html @@ -106,4125 +106,4126 @@ $(document).ready(function() { init_codefold(0); });
    22#else
    23#include <fcntl.h>
    24#include <unistd.h>
    -
    25#include <sys/stat.h>
    -
    26#endif
    -
    27#include <chrono>
    -
    28#include <condition_variable>
    -
    29#include <list>
    -
    30#include <memory>
    -
    31#include <set>
    -
    32#include <string>
    -
    33#include <thread>
    -
    34#include <vector>
    -
    35
    -
    36#if !defined(SET_FILE_OP_TIMES) && defined(RDAT_BELEZI_CAS_DOSTOPA_VER)
    -
    37#define SET_FILE_OP_TIMES 1
    -
    38#pragma message("RDAT_BELEZI_CAS_DOSTOPA_VER is deprecated. Use SET_FILE_OP_TIMES instead.")
    -
    39#elif !defined(SET_FILE_OP_TIMES)
    -
    40#define SET_FILE_OP_TIMES 0
    -
    41#endif
    -
    42#if !defined(CHECK_STREAM_STATE) && defined(RDAT_NE_PREVERJAJ_STANJA_VER)
    -
    43#define CHECK_STREAM_STATE 0
    -
    44#pragma message("RDAT_NE_PREVERJAJ_EOF_VER is deprecated. Use CHECK_STREAM_STATE=0 instead.")
    -
    45#else
    -
    46#define CHECK_STREAM_STATE 1
    -
    47#endif
    -
    48
    -
    49namespace stdex
    -
    50{
    -
    51 namespace stream
    -
    52 {
    -
    56 enum class state_t {
    -
    57 ok = 0,
    -
    58 eof,
    -
    59 fail,
    -
    60 };
    -
    61
    -
    65 using fsize_t = uint64_t;
    -
    66 constexpr fsize_t fsize_max = UINT64_MAX;
    -
    67
    -
    68 constexpr size_t iterate_count = 0x10;
    -
    69 constexpr size_t default_block_size = 0x10000;
    -
    70 constexpr char16_t utf16_bom = u'\ufeff';
    -
    71 constexpr char32_t utf32_bom = U'\ufeff';
    -
    72 constexpr const char utf8_bom[3] = { '\xef', '\xbb', '\xbf' };
    -
    73
    -
    -
    77 class basic
    -
    78 {
    -
    79 public:
    -
    80 basic(_In_ state_t state = state_t::ok) : m_state(state) {}
    -
    81
    -
    82 virtual ~basic() noexcept(false) {}
    -
    83
    -
    -
    95 virtual _Success_(return != 0 || length == 0) size_t read(
    -
    96 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
    -
    97 {
    -
    98 _Unreferenced_(data);
    -
    99 _Unreferenced_(length);
    -
    100 m_state = state_t::fail;
    -
    101 return 0;
    -
    102 }
    -
    -
    103
    -
    -
    113 virtual _Success_(return != 0) size_t write(
    -
    114 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
    -
    115 {
    -
    116 _Unreferenced_(data);
    -
    117 _Unreferenced_(length);
    -
    118 m_state = state_t::fail;
    -
    119 return 0;
    -
    120 }
    -
    -
    121
    -
    -
    125 virtual void flush()
    -
    126 {
    -
    127 m_state = state_t::ok;
    -
    128 }
    -
    -
    129
    -
    -
    133 virtual void close()
    -
    134 {
    -
    135 m_state = state_t::ok;
    -
    136 }
    -
    -
    137
    -
    -
    141 virtual void skip(_In_ fsize_t amount)
    -
    142 {
    -
    143 if (amount == 1)
    -
    144 read_byte();
    -
    145 else if (amount < iterate_count) {
    -
    146 for (size_t i = 0; i < static_cast<size_t>(amount); i++) {
    -
    147 read_byte();
    -
    148 if (!ok()) _Unlikely_
    -
    149 break;
    -
    150 }
    -
    151 }
    -
    152 else {
    -
    153 size_t block = static_cast<size_t>(std::min<fsize_t>(amount, default_block_size));
    -
    154 try {
    -
    155 std::unique_ptr<uint8_t[]> dummy(new uint8_t[block]);
    -
    156 while (amount) {
    -
    157 amount -= read_array(dummy.get(), sizeof(uint8_t), static_cast<size_t>(std::min<fsize_t>(amount, block)));
    -
    158 if (!ok()) _Unlikely_
    -
    159 break;
    -
    160 }
    -
    161 }
    -
    162 catch (const std::bad_alloc&) { m_state = state_t::fail; }
    -
    163 }
    -
    164 }
    -
    -
    165
    -
    169 inline state_t state() const { return m_state; };
    -
    170
    -
    174 inline bool ok() const { return m_state == state_t::ok; };
    -
    175
    -
    -
    183 virtual std::vector<uint8_t> read_remainder(_In_ size_t max_length = SIZE_MAX)
    -
    184 {
    -
    185 std::vector<uint8_t> result;
    -
    186 size_t offset, length;
    -
    187 offset = 0;
    -
    188 length = default_block_size;
    -
    189 while (offset < max_length) {
    -
    190 length = std::min(length, max_length);
    -
    191 try { result.resize(length); }
    -
    192 catch (const std::bad_alloc&) {
    -
    193 m_state = state_t::fail;
    -
    194 return result;
    -
    195 }
    -
    196 auto num_read = read_array(result.data() + offset, sizeof(uint8_t), length - offset);
    -
    197 offset += num_read;
    -
    198 if (!ok()) _Unlikely_
    -
    199 break;
    -
    200 length += default_block_size;
    -
    201 }
    -
    202 result.resize(offset);
    -
    203 return result;
    -
    204 }
    -
    -
    205
    -
    -
    209 inline uint8_t read_byte()
    -
    210 {
    -
    211 uint8_t byte;
    -
    212 if (read_array(&byte, sizeof(byte), 1) == 1)
    -
    213 return byte;
    -
    214 throw std::system_error(sys_error(), std::system_category(), "failed to read");
    -
    215 }
    -
    -
    216
    -
    -
    220 void write_byte(_In_ uint8_t byte, _In_ fsize_t amount = 1)
    -
    221 {
    -
    222 if (amount == 1)
    -
    223 write(&byte, sizeof(uint8_t));
    -
    224 else if (amount < iterate_count) {
    -
    225 for (size_t i = 0; i < static_cast<size_t>(amount); i++) {
    -
    226 write(&byte, sizeof(uint8_t));
    -
    227 if (!ok()) _Unlikely_
    -
    228 break;
    -
    229 }
    -
    230 }
    -
    231 else {
    -
    232 size_t block = static_cast<size_t>(std::min<fsize_t>(amount, default_block_size));
    -
    233 try {
    -
    234 std::unique_ptr<uint8_t[]> dummy(new uint8_t[block]);
    -
    235 memset(dummy.get(), byte, block);
    -
    236 while (amount) {
    -
    237 amount -= write_array(dummy.get(), sizeof(uint8_t), static_cast<size_t>(std::min<fsize_t>(amount, block)));
    -
    238 if (!ok()) _Unlikely_
    -
    239 break;
    -
    240 }
    -
    241 }
    -
    242 catch (const std::bad_alloc&) { m_state = state_t::fail; }
    -
    243 }
    -
    244 }
    -
    -
    245
    -
    257 template <class T>
    -
    -
    258 inline basic& read_data(_Out_ T& data)
    -
    259 {
    -
    260 if (!ok()) _Unlikely_ {
    -
    261 data = 0;
    -
    262 return *this;
    -
    263 }
    -
    264 if (read_array(&data, sizeof(T), 1) == 1)
    -
    265 (void)LE2HE(&data);
    -
    266 else {
    -
    267 data = 0;
    -
    268 if (ok())
    -
    269 m_state = state_t::eof;
    -
    270 }
    -
    271 return *this;
    -
    272 }
    -
    -
    273
    -
    285 template <class T>
    -
    -
    286 inline basic& write_data(_In_ const T data)
    -
    287 {
    -
    288 if (!ok()) _Unlikely_
    -
    289 return *this;
    -
    290#if BYTE_ORDER == BIG_ENDIAN
    -
    291 T data_le = HE2LE(data);
    -
    292 write(&data_le, sizeof(T));
    -
    293#else
    -
    294 write(&data, sizeof(T));
    -
    295#endif
    -
    296 return *this;
    -
    297 }
    -
    -
    298
    -
    304 template<class _Traits = std::char_traits<char>, class _Ax = std::allocator<char>>
    -
    -
    305 inline size_t readln(_Inout_ std::basic_string<char, _Traits, _Ax>& str)
    -
    306 {
    -
    307 str.clear();
    -
    308 return readln_and_attach(str);
    -
    309 }
    -
    -
    310
    -
    316 template<class _Traits = std::char_traits<wchar_t>, class _Ax = std::allocator<wchar_t>>
    -
    -
    317 inline size_t readln(_Inout_ std::basic_string<wchar_t, _Traits, _Ax>& wstr)
    -
    318 {
    -
    319 wstr.clear();
    -
    320 return readln_and_attach(wstr);
    -
    321 }
    -
    -
    322
    -
    328 template<class T_from, class T_to, class _Traits = std::char_traits<T_to>, class _Ax = std::allocator<T_to>>
    -
    -
    329 size_t readln(_Inout_ std::basic_string<T_to, _Traits, _Ax>& wstr, _In_ charset_encoder<T_from, T_to>& encoder)
    -
    330 {
    -
    331 if (encoder.from_encoding() == encoder.to_encoding())
    -
    332 return readln(wstr);
    -
    333 std::string str;
    - -
    335 encoder.strcpy(wstr, str);
    -
    336 return wstr.size();
    -
    337 }
    -
    -
    338
    -
    344 template<class _Elem, class _Traits = std::char_traits<_Elem>, class _Ax = std::allocator<_Elem>>
    -
    -
    345 size_t readln_and_attach(_Inout_ std::basic_string<_Elem, _Traits, _Ax>& str)
    -
    346 {
    -
    347 bool initial = true;
    -
    348 _Elem chr, previous = (_Elem)0;
    -
    349 do {
    -
    350 read_array(&chr, sizeof(_Elem), 1);
    -
    351 if (!initial && !(previous == static_cast<_Elem>('\r') && chr == static_cast<_Elem>('\n')))
    -
    352 str += previous;
    -
    353 else
    -
    354 initial = false;
    -
    355 previous = chr;
    -
    356 } while (ok() && chr != static_cast<_Elem>('\n'));
    -
    357 return str.size();
    -
    358 }
    -
    -
    359
    -
    365 template<class T_from, class T_to, class _Traits = std::char_traits<T_to>, class _Ax = std::allocator<T_to>>
    -
    -
    366 size_t readln_and_attach(_Inout_ std::basic_string<T_to, _Traits, _Ax>& wstr, _In_ charset_encoder<T_from, T_to>& encoder)
    -
    367 {
    -
    368 if (encoder.from_encoding() == encoder.to_encoding())
    -
    369 return readln_and_attach(wstr);
    -
    370 std::string str;
    - -
    372 encoder.strcat(wstr, str);
    -
    373 return wstr.size();
    -
    374 }
    -
    -
    375
    -
    -
    381 size_t read_array(_Out_writes_bytes_(size* count) void* array, _In_ size_t size, _In_ size_t count)
    -
    382 {
    -
    383 for (size_t to_read = mul(size, count);;) {
    -
    384 size_t num_read = read(array, to_read);
    -
    385 to_read -= num_read;
    -
    386 if (!to_read)
    -
    387 return count;
    -
    388 if (!ok()) _Unlikely_
    -
    389 return count - to_read / size;
    -
    390 reinterpret_cast<uint8_t*&>(array) += num_read;
    -
    391 }
    -
    392 }
    -
    -
    393
    -
    -
    399 inline size_t write_array(_In_reads_bytes_opt_(size* count) const void* array, _In_ size_t size, _In_ size_t count)
    -
    400 {
    -
    401 return write(array, mul(size, count)) / size;
    -
    402 }
    -
    -
    403
    -
    412 template <class T_from, class T_to>
    -
    -
    413 size_t write_array(_In_z_ const T_from* wstr, _In_ charset_encoder<T_from, T_to>& encoder)
    -
    414 {
    -
    415 if (!ok()) _Unlikely_
    -
    416 return 0;
    -
    417 size_t num_chars = stdex::strlen(wstr);
    -
    418 if (encoder.from_encoding() == encoder.to_encoding())
    -
    419 return write_array(wstr, sizeof(T_from), num_chars);
    -
    420 std::basic_string<T_to> str(encoder.convert(wstr, num_chars));
    -
    421 return write_array(str.data(), sizeof(T_to), str.size());
    -
    422 }
    -
    -
    423
    -
    433 template <class T_from, class T_to>
    -
    -
    434 size_t write_array(_In_reads_or_z_opt_(num_chars) const T_from* wstr, _In_ size_t num_chars, _In_ charset_encoder<T_from, T_to>& encoder)
    -
    435 {
    -
    436 if (!ok()) _Unlikely_
    -
    437 return 0;
    -
    438 num_chars = stdex::strnlen(wstr, num_chars);
    -
    439 if (encoder.from_encoding() == encoder.to_encoding())
    -
    440 return write_array(wstr, sizeof(T_from), num_chars);
    -
    441 std::basic_string<T_to> str(encoder.convert(wstr, num_chars));
    -
    442 return write_array(str.data(), sizeof(T_to), str.size());
    -
    443 }
    -
    -
    444
    -
    453 template<class T_from, class T_to, class _Traits = std::char_traits<T_from>, class _Ax = std::allocator<T_from>>
    -
    -
    454 size_t write_array(_In_ const std::basic_string<T_from, _Traits, _Ax>& wstr, _In_ charset_encoder<T_from, T_to>& encoder)
    -
    455 {
    -
    456 if (!ok()) _Unlikely_
    -
    457 return 0;
    -
    458 if (encoder.from_encoding() == encoder.to_encoding())
    -
    459 return write_array(wstr.data(), sizeof(T_from), wstr.size());
    -
    460 std::basic_string<T_to> str(encoder.convert(wstr));
    -
    461 return write_array(str.data(), sizeof(T_to), str.size());
    -
    462 }
    -
    -
    463
    -
    475 template<class _Elem, class _Traits = std::char_traits<_Elem>, class _Ax = std::allocator<_Elem>>
    -
    -
    476 inline basic& read_str(_Out_ std::basic_string<_Elem, _Traits, _Ax>& data)
    -
    477 {
    -
    478 data.clear();
    -
    479 if (!ok()) _Unlikely_
    -
    480 return *this;
    -
    481 uint32_t num_chars;
    -
    482 read_data(num_chars);
    -
    483 if (!ok()) _Unlikely_
    -
    484 return *this;
    -
    485 data.reserve(num_chars);
    -
    486 for (;;) {
    -
    487 _Elem buf[0x400];
    -
    488 uint32_t num_read = static_cast<uint32_t>(read_array(buf, sizeof(_Elem), std::min<uint32_t>(num_chars, _countof(buf))));
    -
    489 data.append(buf, buf + num_read);
    -
    490 num_chars -= num_read;
    -
    491 if (!num_chars || !ok())
    -
    492 return *this;
    -
    493 }
    -
    494 }
    -
    -
    495
    -
    507 template <class T>
    -
    -
    508 inline basic& write_str(_In_z_ const T* data)
    -
    509 {
    -
    510 // Stream state will be checked in write_data.
    -
    511 size_t num_chars = stdex::strlen(data);
    -
    512 if (num_chars > UINT32_MAX)
    -
    513 throw std::invalid_argument("string too long");
    -
    514 write_data(static_cast<uint32_t>(num_chars));
    -
    515 if (!ok()) _Unlikely_
    -
    516 return *this;
    -
    517 write_array(data, sizeof(T), num_chars);
    -
    518 return *this;
    -
    519 }
    -
    -
    520
    -
    532 template<class _Elem, class _Traits = std::char_traits<_Elem>, class _Ax = std::allocator<_Elem>>
    -
    -
    533 inline basic& write_str(_In_ const std::basic_string<_Elem, _Traits, _Ax>& data)
    -
    534 {
    -
    535 // Stream state will be checked in write_data.
    -
    536 size_t num_chars = data.size();
    -
    537 if (num_chars > UINT32_MAX)
    -
    538 throw std::invalid_argument("string too long");
    -
    539 write_data(static_cast<uint32_t>(num_chars));
    -
    540 if (!ok()) _Unlikely_
    -
    541 return *this;
    -
    542 write_array(data.data(), sizeof(_Elem), num_chars);
    -
    543 return *this;
    -
    544 }
    -
    -
    545
    -
    546#ifdef _WIN32
    -
    552 size_t write_sa(_In_ LPSAFEARRAY sa)
    -
    553 {
    -
    554 safearray_accessor<void> a(sa);
    -
    555 long ubound, lbound;
    -
    556 if (FAILED(SafeArrayGetUBound(sa, 1, &ubound)) ||
    -
    557 FAILED(SafeArrayGetLBound(sa, 1, &lbound)))
    -
    558 throw std::invalid_argument("SafeArrayGet[UL]Bound failed");
    -
    559 return write(a.data(), static_cast<size_t>(ubound) - lbound + 1);
    -
    560 }
    -
    561#endif
    -
    562
    -
    -
    568 fsize_t write_stream(_Inout_ basic& stream, _In_ fsize_t amount = fsize_max)
    -
    569 {
    -
    570 std::unique_ptr<uint8_t[]> data(new uint8_t[static_cast<size_t>(std::min<fsize_t>(amount, default_block_size))]);
    -
    571 fsize_t num_copied = 0, to_write = amount;
    -
    572 m_state = state_t::ok;
    -
    573 while (to_write) {
    -
    574 size_t num_read = stream.read(data.get(), static_cast<size_t>(std::min<fsize_t>(default_block_size, to_write)));
    -
    575 size_t num_written = write(data.get(), num_read);
    -
    576 num_copied += num_written;
    -
    577 to_write -= num_written;
    -
    578 if (stream.m_state == state_t::eof) {
    -
    579 // EOF is not an error.
    -
    580 m_state = state_t::ok;
    -
    581 break;
    -
    582 }
    -
    583 m_state = stream.m_state;
    -
    584 if (!ok())
    -
    585 break;
    -
    586 }
    -
    587 return num_copied;
    -
    588 }
    -
    -
    589
    -
    -
    593 void write_charset(_In_ charset_id charset)
    -
    594 {
    -
    595 if (charset == charset_id::utf32)
    -
    596 write_data(utf32_bom);
    -
    597 else if (charset == charset_id::utf16)
    -
    598 write_data(utf16_bom);
    -
    599 else if (charset == charset_id::utf8)
    -
    600 write_array(utf8_bom, sizeof(utf8_bom), 1);
    -
    601 }
    -
    -
    602
    -
    -
    608 size_t write_sprintf(_In_z_ _Printf_format_string_params_(2) const char* format, _In_opt_ locale_t locale, ...)
    -
    609 {
    -
    610 va_list params;
    -
    611 va_start(params, locale);
    -
    612 size_t num_chars = write_vsprintf(format, locale, params);
    -
    613 va_end(params);
    -
    614 return num_chars;
    -
    615 }
    -
    -
    616
    -
    -
    622 size_t write_sprintf(_In_z_ _Printf_format_string_params_(2) const wchar_t* format, _In_opt_ locale_t locale, ...)
    -
    623 {
    -
    624 va_list params;
    -
    625 va_start(params, locale);
    -
    626 size_t num_chars = write_vsprintf(format, locale, params);
    -
    627 va_end(params);
    -
    628 return num_chars;
    -
    629 }
    -
    -
    630
    -
    -
    636 size_t write_vsprintf(_In_z_ _Printf_format_string_params_(2) const char* format, _In_opt_ locale_t locale, _In_ va_list params)
    -
    637 {
    -
    638 std::string str;
    -
    639 str.reserve(default_block_size);
    -
    640 vappendf(str, format, locale, params);
    -
    641 return write_array(str.data(), sizeof(char), str.size());
    -
    642 }
    -
    -
    643
    -
    -
    649 size_t write_vsprintf(_In_z_ _Printf_format_string_params_(2) const wchar_t* format, _In_opt_ locale_t locale, _In_ va_list params)
    -
    650 {
    -
    651 std::wstring str;
    -
    652 str.reserve(default_block_size);
    -
    653 vappendf(str, format, locale, params);
    -
    654 return write_array(str.data(), sizeof(wchar_t), str.size());
    -
    655 }
    -
    -
    656
    -
    657 inline basic& operator >>(_Out_ int8_t& data) { return read_data(data); }
    -
    658 inline basic& operator <<(_In_ const int8_t data) { return write_data(data); }
    -
    659 inline basic& operator >>(_Out_ int16_t& data) { return read_data(data); }
    -
    660 inline basic& operator <<(_In_ const int16_t data) { return write_data(data); }
    -
    661 inline basic& operator >>(_Out_ int32_t& data) { return read_data(data); }
    -
    662 inline basic& operator <<(_In_ const int32_t data) { return write_data(data); }
    -
    663 inline basic& operator >>(_Out_ int64_t& data) { return read_data(data); }
    -
    664 inline basic& operator <<(_In_ const int64_t data) { return write_data(data); }
    -
    665 inline basic& operator >>(_Out_ uint8_t& data) { return read_data(data); }
    -
    666 inline basic& operator <<(_In_ const uint8_t data) { return write_data(data); }
    -
    667 inline basic& operator >>(_Out_ uint16_t& data) { return read_data(data); }
    -
    668 inline basic& operator <<(_In_ const uint16_t data) { return write_data(data); }
    -
    669 inline basic& operator >>(_Out_ uint32_t& data) { return read_data(data); }
    -
    670 inline basic& operator <<(_In_ const uint32_t data) { return write_data(data); }
    -
    671 inline basic& operator >>(_Out_ uint64_t& data) { return read_data(data); }
    -
    672 inline basic& operator <<(_In_ const uint64_t data) { return write_data(data); }
    -
    673 inline basic& operator >>(_Out_ float& data) { return read_data(data); }
    -
    674 inline basic& operator <<(_In_ const float data) { return write_data(data); }
    -
    675 inline basic& operator >>(_Out_ double& data) { return read_data(data); }
    -
    676 inline basic& operator <<(_In_ const double data) { return write_data(data); }
    -
    677 inline basic& operator >>(_Out_ char& data) { return read_data(data); }
    -
    678 inline basic& operator <<(_In_ const char data) { return write_data(data); }
    -
    679#ifdef _NATIVE_WCHAR_T_DEFINED
    -
    680 inline basic& operator >>(_Out_ wchar_t& data) { return read_data(data); }
    -
    681 inline basic& operator <<(_In_ const wchar_t data) { return write_data(data); }
    -
    682#endif
    -
    683 template<class _Elem, class _Traits = std::char_traits<_Elem>, class _Ax = std::allocator<_Elem>>
    -
    684 inline basic& operator >>(_Out_ std::basic_string<_Elem, _Traits, _Ax>& data) { return read_str(data); }
    -
    685 template <class T>
    -
    686 inline basic& operator <<(_In_ const T* data) { return write_str(data); }
    -
    687 template<class _Elem, class _Traits = std::char_traits<_Elem>, class _Ax = std::allocator<_Elem>>
    -
    688 inline basic& operator <<(_In_ const std::basic_string<_Elem, _Traits, _Ax>& data) { return write_str(data); }
    -
    689
    -
    690 template <class _Ty, class _Alloc = std::allocator<_Ty>>
    -
    691 basic& operator <<(_In_ const std::vector<_Ty, _Alloc>& data)
    -
    692 {
    -
    693 size_t num = data.size();
    -
    694 if (num > UINT32_MAX) _Unlikely_
    -
    695 throw std::invalid_argument("collection too big");
    -
    696 *this << static_cast<uint32_t>(num);
    -
    697 for (auto& el : data)
    -
    698 *this << el;
    -
    699 return *this;
    -
    700 }
    -
    701
    -
    702 template <class _Ty, class _Alloc = std::allocator<_Ty>>
    -
    703 basic& operator >>(_Out_ std::vector<_Ty, _Alloc>& data)
    -
    704 {
    -
    705 data.clear();
    -
    706 uint32_t num;
    -
    707 *this >> num;
    -
    708 if (!ok()) _Unlikely_
    -
    709 return *this;
    -
    710 data.reserve(num);
    -
    711 for (uint32_t i = 0; i < num; ++i) {
    -
    712 _Ty el;
    -
    713 *this >> el;
    -
    714 if (!ok()) _Unlikely_
    -
    715 return *this;
    -
    716 data.push_back(std::move(el));
    -
    717 }
    -
    718 }
    -
    719
    -
    720 template <class _Kty, class _Pr = std::less<_Kty>, class _Alloc = std::allocator<_Kty>>
    -
    721 basic& operator <<(_In_ const std::set<_Kty, _Pr, _Alloc>& data)
    -
    722 {
    -
    723 size_t num = data.size();
    -
    724 if (num > UINT32_MAX) _Unlikely_
    -
    725 throw std::invalid_argument("collection too big");
    -
    726 *this << static_cast<uint32_t>(num);
    -
    727 for (auto& el : data)
    -
    728 *this << el;
    -
    729 return *this;
    -
    730 }
    -
    731
    -
    732 template <class _Kty, class _Pr = std::less<_Kty>, class _Alloc = std::allocator<_Kty>>
    -
    733 basic& operator >>(_Out_ std::set<_Kty, _Pr, _Alloc>& data)
    -
    734 {
    -
    735 data.clear();
    -
    736 uint32_t num;
    -
    737 *this >> num;
    -
    738 if (!ok()) _Unlikely_
    -
    739 return *this;
    -
    740 for (uint32_t i = 0; i < num; ++i) {
    -
    741 _Kty el;
    -
    742 *this >> el;
    -
    743 if (!ok()) _Unlikely_
    -
    744 return *this;
    -
    745 data.insert(std::move(el));
    -
    746 }
    -
    747 }
    -
    748
    -
    749 template <class _Kty, class _Pr = std::less<_Kty>, class _Alloc = std::allocator<_Kty>>
    -
    750 basic& operator <<(_In_ const std::multiset<_Kty, _Pr, _Alloc>& data)
    -
    751 {
    -
    752 size_t num = data.size();
    -
    753 if (num > UINT32_MAX) _Unlikely_
    -
    754 throw std::invalid_argument("collection too big");
    -
    755 *this << static_cast<uint32_t>(num);
    -
    756 for (auto& el : data)
    -
    757 *this << el;
    -
    758 return *this;
    -
    759 }
    -
    760
    -
    761 template <class _Kty, class _Pr = std::less<_Kty>, class _Alloc = std::allocator<_Kty>>
    -
    762 basic& operator >>(_Out_ std::multiset<_Kty, _Pr, _Alloc>& data)
    -
    763 {
    -
    764 data.clear();
    -
    765 uint32_t num;
    -
    766 *this >> num;
    -
    767 if (!ok()) _Unlikely_
    -
    768 return *this;
    -
    769 for (uint32_t i = 0; i < num; ++i) {
    -
    770 _Kty el;
    -
    771 *this >> el;
    -
    772 if (!ok()) _Unlikely_
    -
    773 return *this;
    -
    774 data.insert(std::move(el));
    -
    775 }
    -
    776 return *this;
    -
    777 }
    -
    778
    -
    779 protected:
    -
    780 state_t m_state;
    -
    781 };
    -
    -
    782
    -
    786 using fpos_t = uint64_t;
    -
    787 constexpr fpos_t fpos_max = UINT64_MAX;
    -
    788 constexpr fpos_t fpos_min = 0;
    -
    789
    -
    793 using foff_t = int64_t;
    -
    794 constexpr foff_t foff_max = INT64_MAX;
    -
    795 constexpr foff_t foff_min = INT64_MIN;
    -
    796
    -
    800 enum class seek_t {
    -
    801#ifdef _WIN32
    -
    802 beg = FILE_BEGIN,
    -
    803 cur = FILE_CURRENT,
    -
    804 end = FILE_END
    -
    805#else
    -
    806 beg = SEEK_SET,
    -
    807 cur = SEEK_CUR,
    -
    808 end = SEEK_END
    -
    809#endif
    -
    810 };
    -
    811
    -
    812#if _HAS_CXX20
    -
    813 using clock = std::chrono::file_clock;
    -
    814#else
    -
    815 using clock = std::chrono::system_clock;
    -
    816#endif
    -
    817 using time_point = std::chrono::time_point<clock>;
    -
    818
    -
    -
    822 class basic_file : virtual public basic
    -
    823 {
    -
    824 public:
    -
    -
    825 virtual std::vector<uint8_t> read_remainder(_In_ size_t max_length = SIZE_MAX)
    -
    826 {
    -
    827 size_t length = std::min<size_t>(max_length, static_cast<size_t>(size() - tell()));
    -
    828 std::vector<uint8_t> result;
    -
    829 try { result.resize(length); }
    -
    830 catch (const std::bad_alloc&) {
    -
    831 m_state = state_t::fail;
    -
    832 return result;
    -
    833 }
    -
    834 result.resize(read_array(result.data(), sizeof(uint8_t), length));
    -
    835 return result;
    -
    836 }
    -
    -
    837
    -
    843 virtual fpos_t seek(_In_ foff_t offset, _In_ seek_t how = seek_t::beg) = 0;
    -
    844
    -
    850 inline fpos_t seekbeg(_In_ fpos_t offset) { return seek(offset, seek_t::beg); }
    -
    851
    -
    857 inline fpos_t seekcur(_In_ foff_t offset) { return seek(offset, seek_t::cur); }
    -
    858
    -
    864 inline fpos_t seekend(_In_ foff_t offset) { return seek(offset, seek_t::end); }
    -
    865
    -
    -
    866 virtual void skip(_In_ fsize_t amount)
    -
    867 {
    -
    868 seek(amount, seek_t::cur);
    -
    869 }
    -
    -
    870
    -
    877 virtual fpos_t tell() const = 0;
    -
    878
    -
    -
    882 virtual void lock(_In_ fpos_t offset, _In_ fsize_t length)
    -
    883 {
    -
    884 _Unreferenced_(offset);
    -
    885 _Unreferenced_(length);
    -
    886 throw std::domain_error("not implemented");
    -
    887 }
    -
    -
    888
    -
    -
    892 virtual void unlock(_In_ fpos_t offset, _In_ fsize_t length)
    -
    893 {
    -
    894 _Unreferenced_(offset);
    -
    895 _Unreferenced_(length);
    -
    896 throw std::domain_error("not implemented");
    -
    897 }
    -
    -
    898
    -
    903 virtual fsize_t size() = 0;
    -
    904
    -
    908 virtual void truncate() = 0;
    -
    909
    -
    -
    913 virtual time_point ctime() const
    -
    914 {
    -
    915 return time_point::min();
    -
    916 }
    -
    -
    917
    -
    -
    921 virtual time_point atime() const
    -
    922 {
    -
    923 return time_point::min();
    -
    924 }
    -
    -
    925
    -
    -
    929 virtual time_point mtime() const
    -
    930 {
    -
    931 return time_point::min();
    -
    932 }
    -
    -
    933
    -
    -
    937 virtual void set_ctime(time_point date)
    -
    938 {
    -
    939 _Unreferenced_(date);
    -
    940 throw std::domain_error("not implemented");
    -
    941 }
    -
    -
    942
    -
    -
    946 virtual void set_atime(time_point date)
    -
    947 {
    -
    948 _Unreferenced_(date);
    -
    949 throw std::domain_error("not implemented");
    -
    950 }
    -
    -
    951
    -
    -
    955 virtual void set_mtime(time_point date)
    -
    956 {
    -
    957 _Unreferenced_(date);
    -
    958 throw std::domain_error("not implemented");
    -
    959 }
    -
    -
    960
    -
    961#ifdef _WIN32
    -
    965 LPSAFEARRAY read_sa()
    -
    966 {
    -
    967 _Assume_(size() <= SIZE_MAX);
    -
    968 size_t length = static_cast<size_t>(size());
    -
    969 std::unique_ptr<SAFEARRAY, SafeArrayDestroy_delete> sa(SafeArrayCreateVector(VT_UI1, 0, (ULONG)length));
    -
    970 if (!sa) _Unlikely_
    -
    971 throw std::runtime_error("SafeArrayCreateVector failed");
    -
    972 safearray_accessor<void> a(sa.get());
    -
    973 if (seek(0) != 0) _Unlikely_
    -
    974 throw std::system_error(sys_error(), std::system_category(), "failed to seek");
    -
    975 if (read_array(a.data(), 1, length) != length)
    -
    976 throw std::system_error(sys_error(), std::system_category(), "failed to read");
    -
    977 return sa.release();
    -
    978 }
    -
    979#endif
    -
    980
    -
    -
    986 charset_id read_charset(_In_ charset_id default_charset = charset_id::system)
    -
    987 {
    -
    988 if (seek(0) != 0) _Unlikely_
    -
    989 throw std::system_error(sys_error(), std::system_category(), "failed to seek");
    -
    990 char32_t id_utf32;
    -
    991 read_array(&id_utf32, sizeof(char32_t), 1);
    -
    992 if (ok() && id_utf32 == utf32_bom)
    -
    993 return charset_id::utf32;
    -
    994
    -
    995 if (seek(0) != 0) _Unlikely_
    -
    996 throw std::system_error(sys_error(), std::system_category(), "failed to seek");
    -
    997 char16_t id_utf16;
    -
    998 read_array(&id_utf16, sizeof(char16_t), 1);
    -
    999 if (ok() && id_utf16 == utf16_bom)
    -
    1000 return charset_id::utf16;
    -
    1001
    -
    1002 if (seek(0) != 0) _Unlikely_
    -
    1003 throw std::system_error(sys_error(), std::system_category(), "failed to seek");
    -
    1004 char id_utf8[3] = { 0 };
    -
    1005 read_array(id_utf8, sizeof(id_utf8), 1);
    -
    1006 if (ok() && strncmp(id_utf8, _countof(id_utf8), utf8_bom, _countof(utf8_bom)) == 0)
    -
    1007 return charset_id::utf8;
    -
    1008
    -
    1009 if (seek(0) != 0) _Unlikely_
    -
    1010 throw std::system_error(sys_error(), std::system_category(), "failed to seek");
    -
    1011 return default_charset;
    -
    1012 }
    -
    -
    1013 };
    -
    -
    1014
    -
    -
    1020 class converter : public basic
    -
    1021 {
    -
    1022 protected:
    -
    1024#pragma warning(suppress: 26495) // The delayed init call will finish initializing the class.
    -
    1025 explicit converter() : basic(state_t::fail) {}
    -
    1026
    -
    1027 void init(_Inout_ basic& source)
    -
    1028 {
    -
    1029 m_source = &source;
    -
    1030 init();
    -
    1031 }
    -
    1032
    -
    1033 void init()
    -
    1034 {
    -
    1035 m_state = m_source->state();
    -
    1036 }
    -
    1037
    -
    1038 void done()
    -
    1039 {
    -
    1040 m_source = nullptr;
    -
    1041 }
    -
    1043
    -
    1044 public:
    -
    1045 converter(_Inout_ basic& source) :
    -
    1046 basic(source.state()),
    -
    1047 m_source(&source)
    -
    1048 {}
    -
    1049
    -
    -
    1050 virtual _Success_(return != 0 || length == 0) size_t read(
    -
    1051 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
    -
    1052 {
    -
    1053 size_t num_read = m_source->read(data, length);
    -
    1054 m_state = m_source->state();
    -
    1055 return num_read;
    -
    1056 }
    -
    -
    1057
    -
    -
    1058 virtual _Success_(return != 0) size_t write(
    -
    1059 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
    -
    1060 {
    -
    1061 size_t num_written = m_source->write(data, length);
    -
    1062 m_state = m_source->state();
    -
    1063 return num_written;
    -
    1064 }
    -
    -
    1065
    -
    -
    1066 virtual void close()
    -
    1067 {
    -
    1068 m_source->close();
    -
    1069 m_state = m_source->state();
    -
    1070 }
    -
    -
    1071
    -
    -
    1072 virtual void flush()
    -
    1073 {
    -
    1074 m_source->flush();
    -
    1075 m_state = m_source->state();
    -
    1076 }
    -
    -
    1077
    -
    1078 protected:
    -
    1079 basic* m_source;
    -
    1080 };
    -
    -
    1081
    -
    -
    1085 class replicator : public basic
    -
    1086 {
    -
    1087 public:
    -
    1088 virtual ~replicator()
    -
    1089 {
    -
    1090 for (auto w = m_workers.begin(), w_end = m_workers.end(); w != w_end; ++w) {
    -
    1091 auto _w = w->get();
    -
    1092 {
    -
    1093 const std::lock_guard<std::mutex> lk(_w->mutex);
    -
    1094 _w->op = worker::op_t::quit;
    -
    1095 }
    -
    1096 _w->cv.notify_one();
    -
    1097 }
    -
    1098 for (auto w = m_workers.begin(), w_end = m_workers.end(); w != w_end; ++w)
    -
    1099 w->get()->join();
    -
    1100 }
    -
    1101
    -
    -
    1105 void push_back(_In_ basic* source)
    -
    1106 {
    -
    1107 m_workers.push_back(std::unique_ptr<worker>(new worker(source)));
    -
    1108 }
    -
    -
    1109
    -
    -
    1113 void remove(basic* source)
    -
    1114 {
    -
    1115 for (auto w = m_workers.begin(), w_end = m_workers.end(); w != w_end; ++w) {
    -
    1116 auto _w = w->get();
    -
    1117 if (_w->source == source) {
    -
    1118 {
    -
    1119 const std::lock_guard<std::mutex> lk(_w->mutex);
    -
    1120 _w->op = worker::op_t::quit;
    -
    1121 }
    -
    1122 _w->cv.notify_one();
    -
    1123 _w->join();
    -
    1124 m_workers.erase(w);
    -
    1125 return;
    -
    1126 }
    -
    1127 }
    -
    1128 }
    -
    -
    1129
    -
    -
    1130 virtual _Success_(return != 0) size_t write(
    -
    1131 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
    -
    1132 {
    -
    1133 for (auto w = m_workers.begin(), w_end = m_workers.end(); w != w_end; ++w) {
    -
    1134 auto _w = w->get();
    -
    1135 {
    -
    1136 const std::lock_guard<std::mutex> lk(_w->mutex);
    -
    1137 _w->op = worker::op_t::write;
    -
    1138 _w->data = data;
    -
    1139 _w->length = length;
    -
    1140 }
    -
    1141 _w->cv.notify_one();
    -
    1142 }
    -
    1143 size_t num_written = length;
    -
    1144 m_state = state_t::ok;
    -
    1145 for (auto w = m_workers.begin(), w_end = m_workers.end(); w != w_end; ++w) {
    -
    1146 auto _w = w->get();
    -
    1147 std::unique_lock<std::mutex> lk(_w->mutex);
    -
    1148 _w->cv.wait(lk, [&] {return _w->op == worker::op_t::noop; });
    -
    1149 if (_w->num_written < num_written)
    -
    1150 num_written = _w->num_written;
    -
    1151 if (ok() && !_w->source->ok())
    -
    1152 m_state = _w->source->state();
    -
    1153 }
    -
    1154 return num_written;
    -
    1155 }
    -
    -
    1156
    -
    -
    1157 virtual void close()
    -
    1158 {
    -
    1159 foreach_worker(worker::op_t::close);
    -
    1160 }
    -
    -
    1161
    -
    -
    1162 virtual void flush()
    -
    1163 {
    -
    1164 foreach_worker(worker::op_t::flush);
    -
    1165 }
    -
    -
    1166
    -
    1167 protected:
    -
    -
    1168 class worker : public std::thread
    -
    1169 {
    -
    1170 public:
    -
    1171 worker(_In_ basic* _source) :
    -
    1172 source(_source),
    -
    1173 op(op_t::noop),
    -
    1174 data(nullptr),
    -
    1175 length(0),
    -
    1176 num_written(0)
    -
    1177 {
    -
    1178 *static_cast<std::thread*>(this) = std::thread([](_Inout_ worker& w) { w.process_op(); }, std::ref(*this));
    -
    1179 }
    -
    1180
    -
    1181 protected:
    -
    1182 void process_op()
    -
    1183 {
    -
    1184 for (;;) {
    -
    1185 std::unique_lock<std::mutex> lk(mutex);
    -
    1186 cv.wait(lk, [&] {return op != op_t::noop; });
    -
    1187 switch (op) {
    -
    1188 case op_t::quit:
    -
    1189 return;
    -
    1190 case op_t::write:
    -
    1191 num_written = source->write(data, length);
    -
    1192 break;
    -
    1193 case op_t::close:
    -
    1194 source->close();
    -
    1195 break;
    -
    1196 case op_t::flush:
    -
    1197 source->flush();
    -
    1198 break;
    -
    1199 case op_t::noop:;
    -
    1200 }
    -
    1201 op = op_t::noop;
    -
    1202 lk.unlock();
    -
    1203 cv.notify_one();
    -
    1204 }
    -
    1205 }
    -
    1206
    -
    1207 public:
    -
    1208 basic* source;
    -
    1209 enum class op_t {
    -
    1210 noop = 0,
    -
    1211 quit,
    -
    1212 write,
    -
    1213 close,
    -
    1214 flush,
    -
    1215 } op;
    -
    1216 const void* data;
    -
    1217 size_t length;
    - -
    1219 std::mutex mutex;
    -
    1220 std::condition_variable cv;
    -
    1221 };
    -
    -
    1222
    -
    1223 void foreach_worker(_In_ worker::op_t op)
    -
    1224 {
    -
    1225 for (auto w = m_workers.begin(), w_end = m_workers.end(); w != w_end; ++w) {
    -
    1226 auto _w = w->get();
    -
    1227 {
    -
    1228 const std::lock_guard<std::mutex> lk(_w->mutex);
    -
    1229 _w->op = op;
    -
    1230 }
    -
    1231 _w->cv.notify_one();
    -
    1232 }
    -
    1233 m_state = state_t::ok;
    -
    1234 for (auto w = m_workers.begin(), w_end = m_workers.end(); w != w_end; ++w) {
    -
    1235 auto _w = w->get();
    -
    1236 std::unique_lock<std::mutex> lk(_w->mutex);
    -
    1237 _w->cv.wait(lk, [&] {return _w->op == worker::op_t::noop; });
    -
    1238 if (ok())
    -
    1239 m_state = _w->source->state();
    -
    1240 }
    -
    1241 }
    -
    1242
    -
    1243 std::list<std::unique_ptr<worker>> m_workers;
    -
    1244 };
    -
    -
    1245
    -
    1246 constexpr size_t default_async_limit = 0x100000;
    -
    1247
    -
    1253 template <size_t CAPACITY = default_async_limit>
    -
    - -
    1255 {
    -
    1256 public:
    -
    1257 async_reader(_Inout_ basic& source) :
    -
    1258 converter(source),
    -
    1259 m_worker([](_Inout_ async_reader& w) { w.process(); }, std::ref(*this))
    -
    1260 {}
    -
    1261
    -
    1262 virtual ~async_reader()
    -
    1263 {
    -
    1264 m_ring.quit();
    -
    1265 m_worker.join();
    -
    1266 }
    -
    1267
    -
    1268#pragma warning(suppress: 6101) // See [1] below
    -
    -
    1269 virtual _Success_(return != 0 || length == 0) size_t read(
    -
    1270 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
    -
    1271 {
    -
    1272 _Assume_(data || !length);
    -
    1273 for (size_t to_read = length;;) {
    -
    1274 uint8_t* ptr; size_t num_read;
    -
    1275 std::tie(ptr, num_read) = m_ring.front();
    -
    1276 if (!ptr) _Unlikely_ {
    -
    1277 m_state = to_read < length || !length ? state_t::ok : m_source->state();
    -
    1278 return length - to_read; // [1] Code analysis misses `length - to_read` bytes were written to data in previous loop iterations.
    -
    1279 }
    -
    1280 if (to_read < num_read)
    -
    1281 num_read = to_read;
    -
    1282 memcpy(data, ptr, num_read);
    -
    1283 m_ring.pop(num_read);
    -
    1284 to_read -= num_read;
    -
    1285 if (!to_read) {
    -
    1286 m_state = state_t::ok;
    -
    1287 return length;
    -
    1288 }
    -
    1289 reinterpret_cast<uint8_t*&>(data) += num_read;
    -
    1290 }
    -
    1291 }
    -
    -
    1292
    -
    1293 protected:
    -
    1294 void process()
    -
    1295 {
    -
    1296 for (;;) {
    -
    1297 uint8_t* ptr; size_t num_write;
    -
    1298 std::tie(ptr, num_write) = m_ring.back();
    -
    1299 if (!ptr) _Unlikely_
    -
    1300 break;
    -
    1301 num_write = m_source->read(ptr, num_write);
    -
    1302 m_ring.push(num_write);
    -
    1303 if (!m_source->ok()) {
    -
    1304 m_ring.quit();
    -
    1305 break;
    -
    1306 }
    -
    1307 }
    -
    1308 }
    -
    1309
    -
    1310 protected:
    -
    1311 ring<uint8_t, CAPACITY> m_ring;
    -
    1312 std::thread m_worker;
    -
    1313 };
    -
    -
    1314
    -
    1320 template <size_t CAPACITY = default_async_limit>
    -
    - -
    1322 {
    -
    1323 public:
    -
    1324 async_writer(_Inout_ basic& source) :
    -
    1325 converter(source),
    -
    1326 m_worker([](_Inout_ async_writer& w) { w.process(); }, std::ref(*this))
    -
    1327 {}
    -
    1328
    -
    1329 virtual ~async_writer()
    -
    1330 {
    -
    1331 m_ring.quit();
    -
    1332 m_worker.join();
    -
    1333 }
    -
    1334
    -
    -
    1335 virtual _Success_(return != 0) size_t write(
    -
    1336 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
    -
    1337 {
    -
    1338 _Assume_(data || !length);
    -
    1339 for (size_t to_write = length;;) {
    -
    1340 uint8_t* ptr; size_t num_write;
    -
    1341 std::tie(ptr, num_write) = m_ring.back();
    -
    1342 if (!ptr) _Unlikely_ {
    -
    1343 m_state = state_t::fail;
    -
    1344 return length - to_write;
    -
    1345 }
    -
    1346 if (to_write < num_write)
    -
    1347 num_write = to_write;
    -
    1348 memcpy(ptr, data, num_write);
    -
    1349 m_ring.push(num_write);
    -
    1350 to_write -= num_write;
    -
    1351 if (!to_write) {
    -
    1352 m_state = state_t::ok;
    -
    1353 return length;
    -
    1354 }
    -
    1355 reinterpret_cast<const uint8_t*&>(data) += num_write;
    -
    1356 }
    -
    1357 }
    -
    -
    1358
    -
    -
    1359 virtual void flush()
    -
    1360 {
    -
    1361 m_ring.sync();
    - -
    1363 }
    -
    -
    1364
    -
    1365 protected:
    -
    1366 void process()
    -
    1367 {
    -
    1368 for (;;) {
    -
    1369 uint8_t* ptr; size_t num_read;
    -
    1370 std::tie(ptr, num_read) = m_ring.front();
    -
    1371 if (!ptr)
    -
    1372 break;
    -
    1373 num_read = m_source->write(ptr, num_read);
    -
    1374 m_ring.pop(num_read);
    -
    1375 if (!m_source->ok()) {
    -
    1376 m_ring.quit();
    -
    1377 break;
    -
    1378 }
    -
    1379 }
    -
    1380 }
    -
    1381
    -
    1382 protected:
    -
    1383 ring<uint8_t, CAPACITY> m_ring;
    -
    1384 std::thread m_worker;
    -
    1385 };
    -
    -
    1386
    -
    1387 constexpr size_t default_buffer_size = 0x400;
    -
    1388
    -
    -
    1392 class buffer : public converter
    -
    1393 {
    -
    1394 protected:
    -
    1396 explicit buffer(_In_ size_t read_buffer_size = default_buffer_size, _In_ size_t write_buffer_size = default_buffer_size) :
    -
    1397 converter(),
    -
    1398 m_read_buffer(read_buffer_size),
    -
    1399 m_write_buffer(write_buffer_size)
    -
    1400 {}
    -
    1401
    -
    1402 void done()
    -
    1403 {
    -
    1404 if (m_source)
    -
    1405 flush_write();
    -
    1406 converter::done();
    -
    1407 }
    -
    1409
    -
    1410 public:
    -
    1411 buffer(_Inout_ basic& source, _In_ size_t read_buffer_size = default_buffer_size, _In_ size_t write_buffer_size = default_buffer_size) :
    -
    1412 converter(source),
    -
    1413 m_read_buffer(read_buffer_size),
    -
    1414 m_write_buffer(write_buffer_size)
    -
    1415 {}
    -
    1416
    -
    1417 virtual ~buffer()
    -
    1418 {
    -
    1419 if (m_source)
    -
    1420 flush_write();
    -
    1421 }
    -
    1422
    -
    -
    1423 virtual _Success_(return != 0 || length == 0) size_t read(
    -
    1424 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
    -
    1425 {
    -
    1426 _Assume_(data || !length);
    -
    1427 for (size_t to_read = length;;) {
    -
    1428 size_t buffer_size = m_read_buffer.tail - m_read_buffer.head;
    -
    1429 if (to_read <= buffer_size) {
    -
    1430 memcpy(data, m_read_buffer.data + m_read_buffer.head, to_read);
    -
    1431 m_read_buffer.head += to_read;
    -
    1432 m_state = state_t::ok;
    -
    1433 return length;
    -
    1434 }
    -
    1435 if (buffer_size) {
    -
    1436 memcpy(data, m_read_buffer.data + m_read_buffer.head, buffer_size);
    -
    1437 reinterpret_cast<uint8_t*&>(data) += buffer_size;
    -
    1438 to_read -= buffer_size;
    -
    1439 }
    -
    1440 m_read_buffer.head = 0;
    -
    1441 if (to_read > m_read_buffer.capacity) {
    -
    1442 // When needing to read more data than buffer capacity, bypass the buffer.
    -
    1443 m_read_buffer.tail = 0;
    -
    1444 to_read -= m_source->read(data, to_read);
    -
    1445 m_state = to_read < length ? state_t::ok : m_source->state();
    -
    1446 return length - to_read;
    -
    1447 }
    -
    1448 m_read_buffer.tail = m_source->read(m_read_buffer.data, m_read_buffer.capacity);
    -
    1449 if (m_read_buffer.tail < m_read_buffer.capacity && m_read_buffer.tail < to_read) _Unlikely_ {
    -
    1450 memcpy(data, m_read_buffer.data, m_read_buffer.tail);
    -
    1451 m_read_buffer.head = m_read_buffer.tail;
    -
    1452 to_read -= m_read_buffer.tail;
    -
    1453 m_state = to_read < length ? state_t::ok : m_source->state();
    -
    1454 return length - to_read;
    -
    1455 }
    -
    1456 }
    -
    1457 }
    -
    -
    1458
    -
    -
    1459 virtual _Success_(return != 0) size_t write(
    -
    1460 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
    -
    1461 {
    -
    1462 _Assume_(data || !length);
    -
    1463 if (!length) _Unlikely_ {
    -
    1464 // Pass null writes (zero-byte length). Null write operations have special meaning with with Windows pipes.
    -
    1465 flush_write();
    -
    1466 if (!ok()) _Unlikely_
    -
    1467 return 0;
    -
    1468 converter::write(nullptr, 0);
    -
    1469 return 0;
    -
    1470 }
    -
    1471
    -
    1472 for (size_t to_write = length;;) {
    -
    1473 size_t available_buffer = m_write_buffer.capacity - m_write_buffer.tail;
    -
    1474 if (to_write <= available_buffer) {
    -
    1475 memcpy(m_write_buffer.data + m_write_buffer.tail, data, to_write);
    -
    1476 m_write_buffer.tail += to_write;
    -
    1477 m_state = state_t::ok;
    -
    1478 return length;
    -
    1479 }
    -
    1480 if (available_buffer) {
    -
    1481 memcpy(m_write_buffer.data + m_write_buffer.tail, data, available_buffer);
    -
    1482 reinterpret_cast<const uint8_t*&>(data) += available_buffer;
    -
    1483 to_write -= available_buffer;
    -
    1484 m_write_buffer.tail += available_buffer;
    -
    1485 }
    -
    1486 size_t buffer_size = m_write_buffer.tail - m_write_buffer.head;
    -
    1487 if (buffer_size) {
    -
    1488 m_write_buffer.head += converter::write(m_write_buffer.data + m_write_buffer.head, buffer_size);
    -
    1489 if (m_write_buffer.head == m_write_buffer.tail)
    -
    1490 m_write_buffer.head = m_write_buffer.tail = 0;
    -
    1491 else
    -
    1492 return length - to_write;
    -
    1493 }
    -
    1494 if (to_write > m_write_buffer.capacity) {
    -
    1495 // When needing to write more data than buffer capacity, bypass the buffer.
    -
    1496 to_write -= converter::write(data, to_write);
    -
    1497 return length - to_write;
    -
    1498 }
    -
    1499 }
    -
    1500 }
    -
    -
    1501
    -
    -
    1502 virtual void flush()
    -
    1503 {
    -
    1504 flush_write();
    -
    1505 if (ok())
    - -
    1507 }
    -
    -
    1508
    -
    1509 protected:
    -
    1510 void flush_write()
    -
    1511 {
    -
    1512 size_t buffer_size = m_write_buffer.tail - m_write_buffer.head;
    -
    1513 if (buffer_size) {
    -
    1514 m_write_buffer.head += m_source->write(m_write_buffer.data + m_write_buffer.head, buffer_size);
    -
    1515 if (m_write_buffer.head == m_write_buffer.tail) {
    -
    1516 m_write_buffer.head = 0;
    -
    1517 m_write_buffer.tail = 0;
    -
    1518 }
    -
    1519 else {
    -
    1520 m_state = m_source->state();
    -
    1521 return;
    -
    1522 }
    -
    1523 }
    -
    1524 m_state = state_t::ok;
    -
    1525 }
    -
    1526
    -
    -
    1527 struct buffer_t {
    -
    1528 uint8_t* data;
    -
    1529 size_t head, tail, capacity;
    -
    1530
    -
    1531 buffer_t(_In_ size_t buffer_size) :
    -
    1532 head(0),
    -
    1533 tail(0),
    -
    1534 capacity(buffer_size),
    -
    1535 data(buffer_size ? new uint8_t[buffer_size] : nullptr)
    -
    1536 {}
    -
    1537
    -
    1538 ~buffer_t()
    -
    1539 {
    -
    1540 if (data)
    -
    1541 delete[] data;
    -
    1542 }
    -
    1543 } m_read_buffer, m_write_buffer;
    -
    -
    1544 };
    -
    -
    1545
    -
    -
    1549 class limiter : public converter
    -
    1550 {
    -
    1551 public:
    -
    1552 limiter(_Inout_ basic& source, _In_ fsize_t _read_limit = 0, _In_ fsize_t _write_limit = 0) :
    -
    1553 converter(source),
    -
    1554 read_limit(_read_limit),
    -
    1555 write_limit(_write_limit)
    -
    1556 {}
    -
    1557
    -
    -
    1558 virtual _Success_(return != 0 || length == 0) size_t read(
    -
    1559 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
    -
    1560 {
    -
    1561 size_t num_read;
    -
    1562 if (read_limit == fsize_max)
    -
    1563 num_read = converter::read(data, length);
    -
    1564 else if (length <= read_limit) {
    -
    1565 num_read = converter::read(data, length);
    -
    1566 read_limit -= num_read;
    -
    1567 }
    -
    1568 else if (length && !read_limit) {
    -
    1569 num_read = 0;
    -
    1570 m_state = state_t::eof;
    -
    1571 }
    -
    1572 else {
    -
    1573 num_read = converter::read(data, static_cast<size_t>(read_limit));
    -
    1574 read_limit -= num_read;
    -
    1575 }
    -
    1576 return num_read;
    -
    1577 }
    -
    -
    1578
    -
    -
    1579 virtual _Success_(return != 0) size_t write(
    -
    1580 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
    -
    1581 {
    -
    1582 size_t num_written;
    -
    1583 if (write_limit == fsize_max)
    -
    1584 num_written = converter::write(data, length);
    -
    1585 else if (length <= write_limit) {
    -
    1586 num_written = converter::write(data, length);
    -
    1587 write_limit -= num_written;
    -
    1588 }
    -
    1589 else if (length && !write_limit) {
    -
    1590 num_written = 0;
    -
    1591 m_state = state_t::fail;
    -
    1592 }
    -
    1593 else {
    -
    1594 num_written = converter::write(data, static_cast<size_t>(write_limit));
    -
    1595 write_limit -= num_written;
    -
    1596 }
    -
    1597 return num_written;
    -
    1598 }
    -
    -
    1599
    -
    1600 public:
    -
    1601 fsize_t
    - - -
    1604 };
    -
    -
    1605
    -
    -
    1609 class window : public limiter
    -
    1610 {
    -
    1611 public:
    -
    1612 window(_Inout_ basic& source, _In_ fpos_t _read_offset = 0, _In_ fsize_t read_limit = fsize_max, _In_ fpos_t _write_offset = 0, _In_ fsize_t write_limit = fsize_max) :
    -
    1613 limiter(source, read_limit, write_limit),
    -
    1614 read_offset(_read_offset),
    -
    1615 write_offset(_write_offset)
    -
    1616 {}
    -
    1617
    -
    -
    1618 virtual _Success_(return != 0 || length == 0) size_t read(
    -
    1619 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
    -
    1620 {
    -
    1621 if (read_offset) {
    -
    1622 m_source->skip(read_offset);
    -
    1623 m_state = m_source->state();
    -
    1624 if (!ok()) _Unlikely_
    -
    1625 return 0;
    -
    1626 read_offset = 0;
    -
    1627 }
    -
    1628 size_t num_read;
    -
    1629 if (read_limit == fsize_max)
    -
    1630 num_read = converter::read(data, length);
    -
    1631 else if (length <= read_limit) {
    -
    1632 num_read = converter::read(data, length);
    -
    1633 read_limit -= num_read;
    -
    1634 }
    -
    1635 else if (length && !read_limit) {
    -
    1636 num_read = 0;
    -
    1637 m_source->skip(length);
    -
    1638 m_state = state_t::eof;
    -
    1639 }
    -
    1640 else {
    -
    1641 num_read = converter::read(data, static_cast<size_t>(read_limit));
    -
    1642 read_limit -= num_read;
    -
    1643 }
    -
    1644 return num_read;
    -
    1645 }
    -
    -
    1646
    -
    -
    1647 virtual _Success_(return != 0) size_t write(
    -
    1648 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
    -
    1649 {
    -
    1650 size_t num_skipped, num_written;
    -
    1651 if (length <= write_offset) {
    -
    1652 write_offset -= length;
    -
    1653 m_state = state_t::ok;
    -
    1654 return length;
    -
    1655 }
    -
    1656 if (write_offset) {
    -
    1657 reinterpret_cast<const uint8_t*&>(data) += static_cast<size_t>(write_offset);
    -
    1658 length -= static_cast<size_t>(write_offset);
    -
    1659 num_skipped = static_cast<size_t>(write_offset);
    -
    1660 write_offset = 0;
    -
    1661 }
    -
    1662 else
    -
    1663 num_skipped = 0;
    -
    1664 if (write_limit == fsize_max)
    -
    1665 num_written = converter::write(data, length);
    -
    1666 else if (length <= write_limit) {
    -
    1667 num_written = converter::write(data, length);
    -
    1668 write_limit -= num_written;
    -
    1669 }
    -
    1670 else if (length && !write_limit) {
    -
    1671 num_skipped += length;
    -
    1672 num_written = 0;
    -
    1673 m_state = state_t::ok;
    -
    1674 }
    -
    1675 else {
    -
    1676 num_skipped += length - static_cast<size_t>(write_limit);
    -
    1677 num_written = converter::write(data, static_cast<size_t>(write_limit));
    -
    1678 write_limit -= num_written;
    -
    1679 }
    -
    1680 return num_skipped + num_written;
    -
    1681 }
    -
    -
    1682
    -
    1683 public:
    -
    1684 fpos_t
    - - -
    1687 };
    -
    -
    1688
    -
    - -
    1693 {
    -
    1694 public:
    -
    1695 file_window(_Inout_ basic_file& source, fpos_t offset = 0, fsize_t length = 0) :
    -
    1696 basic(source.state()),
    -
    1697 m_source(source),
    -
    1698 m_offset(source.tell()),
    -
    1699 m_region(offset, offset + length)
    -
    1700 {}
    -
    1701
    -
    -
    1702 virtual _Success_(return != 0 || length == 0) size_t read(
    -
    1703 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
    -
    1704 {
    -
    1705 _Assume_(data || !length);
    -
    1706 if (m_region.contains(m_offset)) {
    -
    1707 size_t num_read = m_source.read(data, static_cast<size_t>(std::min<fpos_t>(length, m_region.end - m_offset)));
    -
    1708 m_state = m_source.state();
    -
    1709 m_offset += num_read;
    -
    1710 return num_read;
    -
    1711 }
    -
    1712 m_state = length ? state_t::eof : state_t::ok;
    -
    1713 return 0;
    -
    1714 }
    -
    -
    1715
    -
    -
    1716 virtual _Success_(return != 0) size_t write(
    -
    1717 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
    -
    1718 {
    -
    1719 _Assume_(data || !length);
    -
    1720 if (m_region.contains(m_offset)) {
    -
    1721 size_t num_written = m_source.write(data, static_cast<size_t>(std::min<fpos_t>(length, m_region.end - m_offset)));
    -
    1722 m_state = m_source.state();
    -
    1723 m_offset += num_written;
    -
    1724 return num_written;
    -
    1725 }
    -
    1726 m_state = state_t::fail;
    -
    1727 return 0;
    -
    1728 }
    -
    -
    1729
    -
    -
    1730 virtual void close()
    -
    1731 {
    -
    1732 m_source.close();
    -
    1733 m_state = m_source.state();
    -
    1734 }
    -
    -
    1735
    -
    -
    1736 virtual void flush()
    -
    1737 {
    -
    1738 m_source.flush();
    -
    1739 m_state = m_source.state();
    -
    1740 }
    -
    -
    1741
    -
    -
    1742 virtual fpos_t seek(_In_ foff_t offset, _In_ seek_t how = seek_t::beg)
    -
    1743 {
    -
    1744 m_offset = m_source.seek(offset, how);
    -
    1745 m_state = m_source.state();
    -
    1746 return ok() ? m_offset - m_region.start : fpos_max;
    -
    1747 }
    -
    -
    1748
    -
    -
    1749 virtual void skip(_In_ fsize_t amount)
    -
    1750 {
    -
    1751 m_source.skip(amount);
    -
    1752 m_state = m_source.state();
    -
    1753 }
    -
    -
    1754
    -
    -
    1755 virtual fpos_t tell() const
    -
    1756 {
    -
    1757 fpos_t offset = m_source.tell();
    -
    1758 return m_region.contains(offset) ? offset - m_region.start : fpos_max;
    -
    1759 }
    -
    -
    1760
    -
    -
    1761 virtual void lock(_In_ fpos_t offset, _In_ fsize_t length)
    -
    1762 {
    -
    1763 if (m_region.contains(offset)) {
    -
    1764 m_source.lock(m_region.start + offset, std::min<fsize_t>(length, m_region.end - offset));
    -
    1765 m_state = m_source.state();
    -
    1766 }
    -
    1767 else
    -
    1768 m_state = state_t::fail;
    -
    1769 }
    -
    -
    1770
    -
    -
    1771 virtual void unlock(_In_ fpos_t offset, _In_ fsize_t length)
    -
    1772 {
    -
    1773 if (m_region.contains(offset)) {
    -
    1774 m_source.unlock(m_region.start + offset, std::min<fsize_t>(length, m_region.end - offset));
    -
    1775 m_state = m_source.state();
    -
    1776 }
    -
    1777 else
    -
    1778 m_state = state_t::fail;
    -
    1779 }
    -
    -
    1780
    -
    -
    1781 virtual fsize_t size()
    -
    1782 {
    -
    1783 return m_region.size();
    -
    1784 }
    -
    -
    1785
    -
    -
    1786 virtual void truncate()
    -
    1787 {
    -
    1788 m_state = state_t::fail;
    -
    1789 }
    -
    -
    1790
    -
    1791 protected:
    -
    1792 basic_file& m_source;
    -
    1793 fpos_t m_offset;
    -
    1794 interval<fpos_t> m_region;
    -
    1795 };
    -
    -
    1796
    -
    1797 constexpr size_t default_cache_size = 0x1000;
    -
    1798
    -
    -
    1802 class cache : public basic_file
    -
    1803 {
    -
    1804 protected:
    -
    1806#pragma warning(suppress: 26495) // The delayed init call will finish initializing the class.
    -
    1807 explicit cache(_In_ size_t cache_size = default_cache_size) :
    -
    1808 basic(state_t::fail),
    -
    1809 m_cache(cache_size)
    -
    1810 {}
    -
    1811
    -
    1812 void init(_Inout_ basic_file& source)
    -
    1813 {
    -
    1814 m_source = &source;
    -
    1815 init();
    -
    1816 }
    -
    1817
    -
    1818 void init()
    -
    1819 {
    -
    1820 m_state = m_source->state();
    -
    1821 m_offset = m_source->tell();
    -
    1822#if SET_FILE_OP_TIMES
    -
    1823 m_atime = m_source->atime();
    -
    1824 m_mtime = m_source->mtime();
    -
    1825#endif
    -
    1826 }
    -
    1827
    -
    1828 void done()
    -
    1829 {
    -
    1830 if (m_source) {
    -
    1831 flush_cache();
    -
    1832 if (!ok()) _Unlikely_
    -
    1833 throw std::system_error(sys_error(), std::system_category(), "failed to flush cache"); // Data loss occured
    -
    1834 m_source->seek(m_offset);
    -
    1835#if SET_FILE_OP_TIMES
    -
    1836 m_source->set_atime(m_atime);
    -
    1837 m_source->set_mtime(m_mtime);
    -
    1838#endif
    -
    1839 m_source = nullptr;
    -
    1840 }
    -
    1841 }
    -
    1843
    -
    1844 public:
    -
    1845 cache(_Inout_ basic_file& source, _In_ size_t cache_size = default_cache_size) :
    -
    1846 basic(source.state()),
    -
    1847 m_source(&source),
    -
    1848 m_cache(cache_size),
    -
    1849 m_offset(source.tell())
    -
    1850#if SET_FILE_OP_TIMES
    -
    1851 , m_atime(source.atime())
    -
    1852 , m_mtime(source.mtime())
    -
    1853#endif
    -
    1854 {}
    -
    1855
    -
    1856 virtual ~cache() noexcept(false)
    -
    1857 {
    -
    1858 if (m_source) {
    -
    1859 flush_cache();
    -
    1860 if (!ok()) _Unlikely_
    -
    1861 throw std::system_error(sys_error(), std::system_category(), "failed to flush cache"); // Data loss occured
    -
    1862 m_source->seek(m_offset);
    -
    1863#if SET_FILE_OP_TIMES
    -
    1864 m_source->set_atime(m_atime);
    -
    1865 m_source->set_mtime(m_mtime);
    -
    1866#endif
    -
    1867 }
    -
    1868 }
    -
    1869
    -
    -
    1870 virtual _Success_(return != 0 || length == 0) size_t read(
    -
    1871 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
    -
    1872 {
    -
    1873 _Assume_(data || !length);
    -
    1874#if SET_FILE_OP_TIMES
    -
    1875 m_atime = time_point::now();
    -
    1876#endif
    -
    1877 for (size_t to_read = length;;) {
    -
    1878 if (m_cache.status != cache_t::cache_t::status_t::empty) {
    -
    1879 if (m_cache.region.contains(m_offset)) {
    -
    1880 size_t remaining_cache = static_cast<size_t>(m_cache.region.end - m_offset);
    -
    1881 if (to_read <= remaining_cache) {
    -
    1882 memcpy(data, m_cache.data + static_cast<size_t>(m_offset - m_cache.region.start), to_read);
    -
    1883 m_offset += to_read;
    -
    1884 m_state = state_t::ok;
    -
    1885 return length;
    -
    1886 }
    -
    1887 memcpy(data, m_cache.data + static_cast<size_t>(m_offset - m_cache.region.start), remaining_cache);
    -
    1888 reinterpret_cast<uint8_t*&>(data) += remaining_cache;
    -
    1889 to_read -= remaining_cache;
    -
    1890 m_offset += remaining_cache;
    -
    1891 }
    -
    1892 flush_cache();
    -
    1893 if (!ok()) _Unlikely_ {
    -
    1894 if (to_read < length)
    -
    1895 m_state = state_t::ok;
    -
    1896 return length - to_read;
    -
    1897 }
    -
    1898 }
    -
    1899 {
    -
    1900 fpos_t end_max = m_offset + to_read;
    -
    1901 if (m_offset / m_cache.capacity < end_max / m_cache.capacity) {
    -
    1902 // Read spans multiple cache blocks. Bypass cache to the last block.
    -
    1903 m_source->seek(m_offset);
    -
    1904 if (!m_source->ok()) _Unlikely_ {
    -
    1905 m_state = to_read < length ? state_t::ok : state_t::fail;
    -
    1906 return length - to_read;
    -
    1907 }
    -
    1908 size_t num_read = m_source->read(data, to_read - static_cast<size_t>(end_max % m_cache.capacity));
    -
    1909 m_offset += num_read;
    -
    1910 to_read -= num_read;
    -
    1911 if (!to_read) {
    -
    1912 m_state = state_t::ok;
    -
    1913 return length;
    -
    1914 }
    -
    1915 reinterpret_cast<uint8_t*&>(data) += num_read;
    -
    1916 m_state = m_source->state();
    -
    1917 if (!ok()) {
    -
    1918 if (to_read < length)
    -
    1919 m_state = state_t::ok;
    -
    1920 return length - to_read;
    -
    1921 }
    -
    1922 }
    -
    1923 }
    -
    1924 load_cache(m_offset);
    -
    1925 if (!ok() || m_cache.region.end <= m_offset) _Unlikely_ {
    -
    1926 m_state = to_read < length ? state_t::ok : state_t::fail;
    -
    1927 return length - to_read;
    -
    1928 }
    -
    1929 }
    -
    1930 }
    -
    -
    1931
    -
    -
    1932 virtual _Success_(return != 0) size_t write(
    -
    1933 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
    -
    1934 {
    -
    1935 _Assume_(data || !length);
    -
    1936#if SET_FILE_OP_TIMES
    -
    1937 m_atime = m_mtime = time_point::now();
    -
    1938#endif
    -
    1939 for (size_t to_write = length;;) {
    -
    1940 if (m_cache.status != cache_t::cache_t::status_t::empty) {
    -
    1941 fpos_t end_max = m_cache.region.start + m_cache.capacity;
    -
    1942 if (m_cache.region.start <= m_offset && m_offset < end_max) {
    -
    1943 size_t remaining_cache = static_cast<size_t>(end_max - m_offset);
    -
    1944 if (to_write <= remaining_cache) {
    -
    1945 memcpy(m_cache.data + static_cast<size_t>(m_offset - m_cache.region.start), data, to_write);
    -
    1946 m_offset += to_write;
    -
    1947 m_cache.status = cache_t::cache_t::status_t::dirty;
    -
    1948 m_cache.region.end = std::max(m_cache.region.end, m_offset);
    -
    1949 m_state = state_t::ok;
    -
    1950 return length;
    -
    1951 }
    -
    1952 memcpy(m_cache.data + static_cast<size_t>(m_offset - m_cache.region.start), data, remaining_cache);
    -
    1953 reinterpret_cast<const uint8_t*&>(data) += remaining_cache;
    -
    1954 to_write -= remaining_cache;
    -
    1955 m_offset += remaining_cache;
    -
    1956 m_cache.status = cache_t::cache_t::status_t::dirty;
    -
    1957 m_cache.region.end = end_max;
    -
    1958 }
    -
    1959 flush_cache();
    -
    1960 if (!ok()) _Unlikely_
    -
    1961 return length - to_write;
    -
    1962 }
    -
    1963 {
    -
    1964 fpos_t end_max = m_offset + to_write;
    -
    1965 if (m_offset / m_cache.capacity < end_max / m_cache.capacity) {
    -
    1966 // Write spans multiple cache blocks. Bypass cache to the last block.
    -
    1967 m_source->seek(m_offset);
    -
    1968 if (!ok()) _Unlikely_
    -
    1969 return length - to_write;
    -
    1970 size_t num_written = m_source->write(data, to_write - static_cast<size_t>(end_max % m_cache.capacity));
    -
    1971 m_offset += num_written;
    -
    1972 m_state = m_source->state();
    -
    1973 to_write -= num_written;
    -
    1974 if (!to_write || !ok())
    -
    1975 return length - to_write;
    -
    1976 reinterpret_cast<const uint8_t*&>(data) += num_written;
    -
    1977 }
    -
    1978 }
    -
    1979 load_cache(m_offset);
    -
    1980 if (!ok()) _Unlikely_
    -
    1981 return length - to_write;
    -
    1982 }
    -
    1983 }
    -
    -
    1984
    -
    -
    1985 virtual void close()
    -
    1986 {
    -
    1987 invalidate_cache();
    -
    1988 if (!ok()) _Unlikely_
    -
    1989 throw std::system_error(sys_error(), std::system_category(), "failed to flush cache"); // Data loss occured
    -
    1990 m_source->close();
    -
    1991 m_state = m_source->state();
    -
    1992 }
    -
    -
    1993
    -
    -
    1994 virtual void flush()
    -
    1995 {
    -
    1996#if SET_FILE_OP_TIMES
    -
    1997 m_atime = m_mtime = time_point::min();
    -
    1998#endif
    -
    1999 flush_cache();
    -
    2000 if (!ok()) _Unlikely_
    -
    2001 return;
    -
    2002 m_source->flush();
    -
    2003 }
    -
    -
    2004
    -
    -
    2005 virtual fpos_t seek(_In_ foff_t offset, _In_ seek_t how = seek_t::beg)
    -
    2006 {
    -
    2007 m_state = state_t::ok;
    -
    2008 switch (how) {
    -
    2009 case seek_t::beg:
    -
    2010 return m_offset = offset;
    -
    2011 case seek_t::cur:
    -
    2012 return m_offset += offset;
    -
    2013 case seek_t::end:
    -
    2014 return m_offset = size() + offset;
    -
    2015 default:
    -
    2016 throw std::invalid_argument("unknown seek origin");
    -
    2017 }
    -
    2018 }
    -
    -
    2019
    -
    -
    2020 virtual fpos_t tell() const
    -
    2021 {
    -
    2022 return m_offset;
    -
    2023 }
    -
    -
    2024
    -
    -
    2025 virtual void lock(_In_ fpos_t offset, _In_ fsize_t length)
    -
    2026 {
    -
    2027 m_source->lock(offset, length);
    -
    2028 m_state = m_source->state();
    -
    2029 }
    -
    -
    2030
    -
    -
    2031 virtual void unlock(_In_ fpos_t offset, _In_ fsize_t length)
    -
    2032 {
    -
    2033 m_source->unlock(offset, length);
    -
    2034 m_state = m_source->state();
    -
    2035 }
    -
    -
    2036
    -
    -
    2037 virtual fsize_t size()
    -
    2038 {
    -
    2039 return m_cache.status != cache_t::cache_t::status_t::empty ?
    -
    2040 std::max(m_source->size(), m_cache.region.end) :
    -
    2041 m_source->size();
    -
    2042 }
    -
    -
    2043
    -
    -
    2044 virtual void truncate()
    -
    2045 {
    -
    2046#if SET_FILE_OP_TIMES
    -
    2047 m_atime = m_mtime = time_point::now();
    -
    2048#endif
    -
    2049 m_source->seek(m_offset);
    -
    2050 if (m_cache.region.end <= m_offset) {
    -
    2051 // Truncation does not affect cache.
    -
    2052 }
    -
    2053 else if (m_cache.region.start <= m_offset) {
    -
    2054 // Truncation truncates cache.
    -
    2055 m_cache.region.end = m_offset;
    -
    2056 }
    -
    2057 else {
    -
    2058 // Truncation invalidates cache.
    -
    2059 m_cache.status = cache_t::cache_t::status_t::empty;
    -
    2060 }
    -
    2061 m_source->truncate();
    -
    2062 m_state = m_source->state();
    -
    2063 }
    -
    -
    2064
    -
    -
    2065 virtual time_point ctime() const
    -
    2066 {
    -
    2067 return m_source->ctime();
    -
    2068 }
    -
    -
    2069
    -
    -
    2070 virtual time_point atime() const
    -
    2071 {
    -
    2072#if SET_FILE_OP_TIMES
    -
    2073 return std::max(m_atime, m_source->atime());
    -
    2074#else
    -
    2075 return m_source->atime();
    -
    2076#endif
    -
    2077 }
    -
    -
    2078
    -
    -
    2079 virtual time_point mtime() const
    -
    2080 {
    -
    2081#if SET_FILE_OP_TIMES
    -
    2082 return std::max(m_mtime, m_source->mtime());
    -
    2083#else
    -
    2084 return m_source->mtime();
    -
    2085#endif
    -
    2086 }
    -
    -
    2087
    -
    -
    2088 virtual void set_ctime(time_point date)
    -
    2089 {
    -
    2090 m_source->set_ctime(date);
    -
    2091 }
    -
    -
    2092
    -
    -
    2093 virtual void set_atime(time_point date)
    -
    2094 {
    -
    2095#if SET_FILE_OP_TIMES
    -
    2096 m_atime = date;
    -
    2097#endif
    -
    2098 m_source->set_atime(date);
    -
    2099 }
    -
    -
    2100
    -
    -
    2101 virtual void set_mtime(time_point date)
    -
    2102 {
    -
    2103#if SET_FILE_OP_TIMES
    -
    2104 m_mtime = date;
    -
    2105#endif
    -
    2106 m_source->set_mtime(date);
    -
    2107 }
    -
    -
    2108
    -
    2109 protected:
    -
    2111 void flush_cache()
    -
    2112 {
    -
    2113 if (m_cache.status != cache_t::cache_t::status_t::dirty)
    -
    2114 m_state = state_t::ok;
    -
    2115 else if (!m_cache.region.empty()) {
    -
    2116 write_cache();
    -
    2117 if (ok())
    -
    2118 m_cache.status = cache_t::cache_t::status_t::loaded;
    -
    2119 }
    -
    2120 else {
    -
    2121 m_state = state_t::ok;
    -
    2122 m_cache.status = cache_t::cache_t::status_t::loaded;
    -
    2123 }
    -
    2124 }
    -
    2125
    -
    2126 void invalidate_cache()
    -
    2127 {
    -
    2128 if (m_cache.status == cache_t::cache_t::status_t::dirty && !m_cache.region.empty()) {
    -
    2129 write_cache();
    -
    2130 if (!ok()) _Unlikely_
    -
    2131 return;
    -
    2132 } else
    -
    2133 m_state = state_t::ok;
    -
    2134 m_cache.status = cache_t::cache_t::status_t::empty;
    -
    2135 }
    -
    2136
    -
    2137 void load_cache(_In_ fpos_t start)
    -
    2138 {
    -
    2139 _Assume_(m_cache.status != cache_t::cache_t::status_t::dirty);
    -
    2140 start -= start % m_cache.capacity; // Align to cache block size.
    -
    2141 m_source->seek(m_cache.region.start = start);
    -
    2142 if (m_source->ok()) {
    -
    2143 m_cache.region.end = start + m_source->read(m_cache.data, m_cache.capacity);
    -
    2144 m_cache.status = cache_t::cache_t::status_t::loaded;
    -
    2145 m_state = state_t::ok; // Regardless the read failure, we still might have cached some data.
    -
    2146 }
    -
    2147 else
    -
    2148 m_state = state_t::fail;
    -
    2149 }
    -
    2150
    -
    2151 void write_cache()
    -
    2152 {
    -
    2153 _Assume_(m_cache.status == cache_t::cache_t::status_t::dirty);
    -
    2154 m_source->seek(m_cache.region.start);
    -
    2155 m_source->write(m_cache.data, static_cast<size_t>(m_cache.region.size()));
    -
    2156 m_state = m_source->state();
    -
    2157 }
    -
    2158
    -
    2159 basic_file* m_source;
    -
    2160 struct cache_t {
    -
    2161 uint8_t* data;
    -
    2162 size_t capacity;
    -
    2163 enum class status_t {
    -
    2164 empty = 0,
    -
    2165 loaded,
    -
    2166 dirty,
    -
    2167 } status;
    -
    2168 interval<fpos_t> region;
    -
    2169
    -
    2170 cache_t(_In_ size_t _capacity) :
    -
    2171 data(new uint8_t[_capacity]),
    -
    2172 capacity(_capacity),
    -
    2173 status(status_t::empty),
    -
    2174 region(0)
    -
    2175 {}
    -
    2176
    -
    2177 ~cache_t()
    -
    2178 {
    -
    2179 delete[] data;
    -
    2180 }
    -
    2181 } m_cache;
    -
    2182 fpos_t m_offset;
    -
    2183#if SET_FILE_OP_TIMES
    -
    2184 time_point
    -
    2185 m_atime,
    -
    2186 m_mtime;
    -
    2187#endif
    -
    2189 };
    -
    -
    2190
    -
    -
    2194 class basic_sys : virtual public basic, public sys_object
    -
    2195 {
    -
    2196 public:
    -
    2197 basic_sys(_In_opt_ sys_handle h = invalid_handle, _In_ state_t state = state_t::ok) :
    -
    2198 basic(state),
    -
    2199 sys_object(h)
    -
    2200 {}
    -
    2201
    -
    -
    2202 virtual _Success_(return != 0 || length == 0) size_t read(
    -
    2203 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
    -
    2204 {
    -
    2205 _Assume_(data || !length);
    -
    2206 // Windows Server 2003 and Windows XP: Pipe write operations across a network are limited in size per write.
    -
    2207 // The amount varies per platform. For x86 platforms it's 63.97 MB. For x64 platforms it's 31.97 MB. For Itanium
    -
    2208 // it's 63.95 MB. For more information regarding pipes, see the Remarks section.
    -
    2209 size_t
    -
    2210#if defined(_WIN64)
    -
    2211 block_size = 0x1F80000;
    -
    2212#elif defined(_WIN32)
    -
    2213 block_size = 0x3f00000;
    -
    2214#else
    -
    2215 block_size = SSIZE_MAX;
    -
    2216#endif
    -
    2217 for (size_t to_read = length;;) {
    -
    2218#ifdef _WIN32
    -
    2219 // ReadFile() might raise exception (e.g. STATUS_FILE_BAD_FORMAT/0xE0000002).
    -
    2220 BOOL succeeded;
    -
    2221 DWORD num_read;
    -
    2222 __try { succeeded = ReadFile(m_h, data, static_cast<DWORD>(std::min<size_t>(to_read, block_size)), &num_read, nullptr); }
    -
    2223 __except (EXCEPTION_EXECUTE_HANDLER) { succeeded = FALSE; SetLastError(ERROR_UNHANDLED_EXCEPTION); num_read = 0; }
    -
    2224 if (!succeeded && GetLastError() == ERROR_NO_SYSTEM_RESOURCES && block_size > default_block_size) _Unlikely_ {
    -
    2225 // Error "Insufficient system resources exist to complete the requested service." occurs
    -
    2226 // ocasionally, when attempting to read too much data at once (e.g. over \\TSClient).
    -
    2227 block_size = default_block_size;
    -
    2228 continue;
    -
    2229 }
    -
    2230 if (!succeeded) _Unlikely_
    -
    2231#else
    -
    2232 ssize_t num_read = ::read(m_h, data, static_cast<ssize_t>(std::min<size_t>(to_read, block_size)));
    -
    2233 if (num_read < 0) _Unlikely_
    -
    2234#endif
    -
    2235 {
    -
    2236 m_state = to_read < length ? state_t::ok : state_t::fail;
    -
    2237 return length - to_read;
    -
    2238 }
    -
    2239 if (!num_read) _Unlikely_ {
    -
    2240 m_state = to_read < length || !length ? state_t::ok : state_t::eof;
    -
    2241 return length - to_read;
    -
    2242 }
    -
    2243 to_read -= num_read;
    -
    2244 if (!to_read) {
    -
    2245 m_state = state_t::ok;
    -
    2246 return length;
    -
    2247 }
    -
    2248 reinterpret_cast<uint8_t*&>(data) += num_read;
    -
    2249 }
    -
    2250 }
    -
    -
    2251
    -
    -
    2252 virtual _Success_(return != 0) size_t write(
    -
    2253 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
    -
    2254 {
    -
    2255 // Windows Server 2003 and Windows XP: Pipe write operations across a network are limited in size per write.
    -
    2256 // The amount varies per platform. For x86 platforms it's 63.97 MB. For x64 platforms it's 31.97 MB. For Itanium
    -
    2257 // it's 63.95 MB. For more information regarding pipes, see the Remarks section.
    -
    2258 constexpr size_t
    -
    2259#if defined(_WIN64)
    -
    2260 block_size = 0x1F80000;
    -
    2261#elif defined(_WIN32)
    -
    2262 block_size = 0x3f00000;
    -
    2263#else
    -
    2264 block_size = SSIZE_MAX;
    -
    2265#endif
    -
    2266 for (size_t to_write = length;;) {
    -
    2267#ifdef _WIN32
    -
    2268 // ReadFile() might raise an exception. Be cautious with WriteFile() too.
    -
    2269 BOOL succeeded;
    -
    2270 DWORD num_written;
    -
    2271 __try { succeeded = WriteFile(m_h, data, static_cast<DWORD>(std::min<size_t>(to_write, block_size)), &num_written, nullptr); }
    -
    2272 __except (EXCEPTION_EXECUTE_HANDLER) { succeeded = FALSE; SetLastError(ERROR_UNHANDLED_EXCEPTION); num_written = 0; }
    -
    2273 to_write -= num_written;
    -
    2274 if (!to_write) {
    -
    2275 m_state = state_t::ok;
    -
    2276 return length;
    -
    2277 }
    -
    2278 reinterpret_cast<const uint8_t*&>(data) += num_written;
    -
    2279 if (!succeeded) _Unlikely_ {
    -
    2280 m_state = state_t::fail;
    -
    2281 return length - to_write;
    -
    2282 }
    -
    2283#else
    -
    2284 ssize_t num_written = ::write(m_h, data, static_cast<ssize_t>(std::min<size_t>(to_write, block_size)));
    -
    2285 if (num_written < 0) _Unlikely_ {
    -
    2286 m_state = state_t::fail;
    -
    2287 return length - to_write;
    -
    2288 }
    -
    2289 to_write -= num_written;
    -
    2290 if (!to_write) {
    -
    2291 m_state = state_t::ok;
    -
    2292 return length;
    -
    2293 }
    -
    2294 reinterpret_cast<const uint8_t*&>(data) += num_written;
    -
    2295#endif
    -
    2296 }
    -
    2297 }
    -
    -
    2298
    -
    -
    2299 virtual void close()
    -
    2300 {
    -
    2301 try {
    - -
    2303 m_state = state_t::ok;
    -
    2304 }
    -
    2305 catch (...) {
    -
    2306 m_state = state_t::fail;
    -
    2307 }
    -
    2308 }
    -
    -
    2309
    -
    -
    2310 virtual void flush()
    -
    2311 {
    -
    2312#ifdef _WIN32
    -
    2313 m_state = FlushFileBuffers(m_h) ? state_t::ok : state_t::fail;
    -
    2314#else
    -
    2315 m_state = fsync(m_h) >= 0 ? state_t::ok : state_t::fail;
    -
    2316#endif
    -
    2317 }
    -
    -
    2318 };
    -
    -
    2319
    -
    -
    2323 class buffered_sys : public buffer
    -
    2324 {
    -
    2325 public:
    -
    2326 buffered_sys(_In_opt_ sys_handle h = invalid_handle, size_t read_buffer_size = default_buffer_size, size_t write_buffer_size = default_buffer_size) :
    -
    2327 buffer(read_buffer_size, write_buffer_size),
    -
    2328 m_source(h)
    -
    2329 {
    -
    2330 init(m_source);
    -
    2331 }
    -
    2332
    -
    2333 virtual ~buffered_sys()
    -
    2334 {
    -
    2335 done();
    -
    2336 }
    -
    2337
    -
    2338 protected:
    -
    2339 basic_sys m_source;
    -
    2340 };
    -
    -
    2341
    -
    -
    2345 class socket : public basic
    -
    2346 {
    -
    2347 public:
    -
    2348 socket(_In_opt_ SOCKET h = INVALID_SOCKET, _In_ state_t state = state_t::ok) :
    -
    2349 basic(state),
    -
    2350 m_h(h)
    -
    2351 {}
    -
    2352
    -
    2353 private:
    -
    2354 socket(_In_ const socket& other);
    -
    2355 socket& operator =(_In_ const socket& other);
    -
    2356
    -
    2357 public:
    -
    2358 socket(_Inout_ socket&& other) noexcept : m_h(other.m_h)
    -
    2359 {
    -
    2360 other.m_h = INVALID_SOCKET;
    -
    2361 }
    -
    2362
    -
    2363 socket& operator =(_Inout_ socket&& other) noexcept
    -
    2364 {
    -
    2365 if (this != std::addressof(other)) {
    -
    2366 if (m_h != INVALID_SOCKET)
    -
    2367 closesocket(m_h);
    -
    2368 m_h = other.m_h;
    -
    2369 other.m_h = INVALID_SOCKET;
    -
    2370 }
    -
    2371 return *this;
    -
    2372 }
    -
    2373
    -
    -
    2381 socket(_In_ int af, _In_ int type, _In_ int protocol)
    -
    2382 {
    -
    2383 m_h = ::socket(af, type, protocol);
    -
    2384 if (m_h == INVALID_SOCKET) _Unlikely_
    -
    2385 m_state = state_t::fail;
    -
    2386 }
    -
    -
    2387
    -
    2388 virtual ~socket()
    -
    2389 {
    -
    2390 if (m_h != INVALID_SOCKET)
    -
    2391 closesocket(m_h);
    -
    2392 }
    -
    2393
    -
    2397 inline operator bool() const noexcept { return m_h != INVALID_SOCKET; }
    -
    2398
    -
    2402 inline SOCKET get() const noexcept { return m_h; }
    -
    2403
    -
    -
    2404 virtual _Success_(return != 0 || length == 0) size_t read(
    -
    2405 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
    -
    2406 {
    -
    2407 _Assume_(data || !length);
    -
    2408 constexpr int block_size = 0x10000000;
    -
    2409 for (size_t to_read = length;;) {
    -
    2410 int num_read = recv(m_h, reinterpret_cast<char*>(data), static_cast<int>(std::min<size_t>(to_read, block_size)), 0);
    -
    2411 if (num_read == SOCKET_ERROR) _Unlikely_ {
    -
    2412 m_state = to_read < length ? state_t::ok : state_t::fail;
    -
    2413 return length - to_read;
    -
    2414 }
    -
    2415 if (!num_read) {
    -
    2416 m_state = to_read < length || !length ? state_t::ok : state_t::eof;
    -
    2417 return length - to_read;
    -
    2418 }
    -
    2419 to_read -= num_read;
    -
    2420 if (!to_read) {
    -
    2421 m_state = state_t::ok;
    -
    2422 return length;
    -
    2423 }
    -
    2424 reinterpret_cast<uint8_t*&>(data) += num_read;
    -
    2425 }
    -
    2426 }
    -
    -
    2427
    -
    -
    2428 virtual _Success_(return != 0) size_t write(
    -
    2429 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
    -
    2430 {
    -
    2431 _Assume_(data || !length);
    -
    2432 constexpr int block_size = 0x10000000;
    -
    2433 for (size_t to_write = length;;) {
    -
    2434 int num_written = send(m_h, reinterpret_cast<const char*>(data), static_cast<int>(std::min<size_t>(to_write, block_size)), 0);
    -
    2435 if (num_written == SOCKET_ERROR) _Unlikely_ {
    -
    2436 m_state = state_t::fail;
    -
    2437 return length - to_write;
    -
    2438 }
    -
    2439 to_write -= num_written;
    -
    2440 if (!to_write) {
    -
    2441 m_state = state_t::ok;
    -
    2442 return length;
    -
    2443 }
    -
    2444 reinterpret_cast<const uint8_t*&>(data) += num_written;
    -
    2445 }
    -
    2446 }
    -
    -
    2447
    -
    -
    2448 virtual void close()
    -
    2449 {
    -
    2450 if (m_h != INVALID_SOCKET) {
    -
    2451 closesocket(m_h);
    -
    2452 m_h = INVALID_SOCKET;
    -
    2453 }
    -
    2454 m_state = state_t::ok;
    -
    2455 }
    -
    -
    2456
    -
    2457 protected:
    -
    2458 SOCKET m_h;
    -
    2459 };
    -
    -
    2460
    -
    2461#ifdef _WIN32
    -
    2465 class sequential_stream : public basic
    -
    2466 {
    -
    2467 public:
    -
    2468 sequential_stream(_In_ ISequentialStream* source) : m_source(source)
    -
    2469 {
    -
    2470 m_source->AddRef();
    -
    2471 }
    -
    2472
    -
    2473 virtual ~sequential_stream()
    -
    2474 {
    -
    2475 m_source->Release();
    -
    2476 }
    -
    2477
    -
    2478 virtual _Success_(return != 0 || length == 0) size_t read(
    -
    2479 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
    -
    2480 {
    -
    2481 _Assume_(data || !length);
    -
    2482 for (size_t to_read = length;;) {
    -
    2483 HRESULT hr;
    -
    2484 ULONG num_read = 0;
    -
    2485 __try { hr = m_source->Read(data, (ULONG)std::min<size_t>(to_read, ULONG_MAX), &num_read); }
    -
    2486 __except (EXCEPTION_EXECUTE_HANDLER) { hr = E_FAIL; }
    -
    2487 if (FAILED(hr)) _Unlikely_ {
    -
    2488 m_state = to_read < length ? state_t::ok : state_t::fail;
    -
    2489 return length - to_read;
    -
    2490 }
    -
    2491 to_read -= num_read;
    -
    2492 if (hr == S_FALSE) _Unlikely_ {
    -
    2493 m_state = to_read < length || !length ? state_t::ok : state_t::eof;
    -
    2494 return length - to_read;
    -
    2495 }
    -
    2496 if (!to_read) {
    -
    2497 m_state = state_t::ok;
    -
    2498 return length;
    -
    2499 }
    -
    2500 reinterpret_cast<uint8_t*&>(data) += num_read;
    -
    2501 }
    -
    2502 }
    -
    2503
    -
    2504 virtual _Success_(return != 0) size_t write(
    -
    2505 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
    -
    2506 {
    -
    2507 _Assume_(data || !length);
    -
    2508 for (size_t to_write = length;;) {
    -
    2509 HRESULT hr;
    -
    2510 ULONG num_written = 0;
    -
    2511 __try { hr = m_source->Write(data, static_cast<ULONG>(std::min<size_t>(to_write, ULONG_MAX)), &num_written); }
    -
    2512 __except (EXCEPTION_EXECUTE_HANDLER) { hr = E_FAIL; }
    -
    2513 // In abscence of documentation whether num_written gets set when FAILED(hr) (i.e. partially succesful writes),
    -
    2514 // assume write failed completely.
    -
    2515 if (FAILED(hr)) _Unlikely_ {
    -
    2516 m_state = state_t::fail;
    -
    2517 return length - to_write;
    -
    2518 }
    -
    2519 to_write -= num_written;
    -
    2520 if (!to_write) {
    -
    2521 m_state = state_t::ok;
    -
    2522 return length;
    -
    2523 }
    -
    2524 reinterpret_cast<const uint8_t*&>(data) += num_written;
    -
    2525 }
    -
    2526 }
    -
    2527
    -
    2528 protected:
    -
    2529 ISequentialStream* m_source;
    -
    2530 };
    -
    2531
    -
    2535 class asp : public basic
    -
    2536 {
    -
    2537 public:
    -
    2538 asp(_In_opt_ IRequest* request, _In_opt_ IResponse* response) :
    -
    2539 m_request(request),
    -
    2540 m_response(response)
    -
    2541 {
    -
    2542 if (m_request)
    -
    2543 m_request->AddRef();
    -
    2544 if (m_response)
    -
    2545 m_response->AddRef();
    -
    2546 }
    -
    2547
    -
    2548 virtual ~asp()
    -
    2549 {
    -
    2550 if (m_request)
    -
    2551 m_request->Release();
    -
    2552 if (m_response)
    -
    2553 m_response->Release();
    -
    2554 }
    -
    2555
    -
    2556 virtual _Success_(return != 0 || length == 0) size_t read(
    -
    2557 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
    -
    2558 {
    -
    2559 _Assume_(data || !length);
    -
    2560 if (!m_request) _Unlikely_ {
    -
    2561 m_state = state_t::fail;
    -
    2562 return 0;
    -
    2563 }
    -
    2564 for (size_t to_read = length;;) {
    -
    2565 VARIANT var_amount, var_data;
    -
    2566 V_VT(&var_amount) = VT_I4;
    -
    2567 V_I4(&var_amount) = (LONG)std::min<size_t>(to_read, LONG_MAX);
    -
    2568 V_VT(&var_data) = VT_EMPTY;
    -
    2569 HRESULT hr = [&]() {
    -
    2570 __try { return m_request->BinaryRead(&var_amount, &var_data); }
    -
    2571 __except (EXCEPTION_EXECUTE_HANDLER) { return E_FAIL; }
    -
    2572 }();
    -
    2573 if (FAILED(hr)) _Unlikely_ {
    -
    2574 m_state = to_read < length ? state_t::ok : state_t::fail;
    -
    2575 return length - to_read;
    -
    2576 }
    -
    2577 _Assume_(V_VT(&var_amount) == VT_I4);
    -
    2578 _Assume_(V_VT(&var_data) == (VT_ARRAY | VT_UI1));
    -
    2579 std::unique_ptr<SAFEARRAY, SafeArrayDestroy_delete> sa(V_ARRAY(&var_data));
    -
    2580 if (!V_I4(&var_amount)) _Unlikely_ {
    -
    2581 m_state = to_read < length || !length ? state_t::ok : state_t::eof;
    -
    2582 return length - to_read;
    -
    2583 }
    -
    2584 safearray_accessor<uint8_t> a(sa.get());
    -
    2585 memcpy(data, a.data(), V_I4(&var_amount));
    -
    2586 to_read -= V_I4(&var_amount);
    -
    2587 if (!to_read) {
    -
    2588 m_state = state_t::ok;
    -
    2589 return length;
    -
    2590 }
    -
    2591 reinterpret_cast<uint8_t*&>(data) += V_I4(&var_amount);
    -
    2592 }
    -
    2593 }
    -
    2594
    -
    2595 virtual _Success_(return != 0) size_t write(
    -
    2596 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
    -
    2597 {
    -
    2598 if (!m_response) {
    -
    2599 m_state = state_t::fail;
    -
    2600 return 0;
    -
    2601 }
    -
    2602 for (size_t to_write = length;;) {
    -
    2603 UINT num_written = static_cast<UINT>(std::min<size_t>(to_write, UINT_MAX));
    -
    2604 std::unique_ptr<OLECHAR, SysFreeString_delete> bstr_data(SysAllocStringByteLen(reinterpret_cast<LPCSTR>(data), num_written));
    -
    2605 VARIANT var_data;
    -
    2606 V_VT(&var_data) = VT_BSTR;
    -
    2607 V_BSTR(&var_data) = bstr_data.get();
    -
    2608 HRESULT hr = [&]() {
    -
    2609 __try { return m_response->BinaryWrite(var_data); }
    -
    2610 __except (EXCEPTION_EXECUTE_HANDLER) { return E_FAIL; }
    -
    2611 }();
    -
    2612 if (FAILED(hr)) _Unlikely_ {
    -
    2613 m_state = state_t::fail;
    -
    2614 return length - to_write;
    -
    2615 }
    -
    2616 to_write -= num_written;
    -
    2617 if (!to_write) {
    -
    2618 m_state = state_t::ok;
    -
    2619 return length;
    -
    2620 }
    -
    2621 reinterpret_cast<const uint8_t*&>(data) += num_written;
    -
    2622 }
    -
    2623 }
    -
    2624
    -
    2625 virtual void close()
    -
    2626 {
    -
    2627 if (m_response) {
    -
    2628 __try { m_response->End(); }
    -
    2629 __except (EXCEPTION_EXECUTE_HANDLER) {}
    -
    2630 }
    -
    2631 m_state = state_t::ok;
    -
    2632 }
    -
    2633
    -
    2634 virtual void flush()
    -
    2635 {
    -
    2636 if (m_response) {
    -
    2637 HRESULT hr;
    -
    2638 __try { hr = m_response->Flush(); }
    -
    2639 __except (EXCEPTION_EXECUTE_HANDLER) { hr = E_FAIL; }
    -
    2640 m_state = SUCCEEDED(hr) ? state_t::ok : state_t::fail;
    -
    2641 }
    -
    2642 }
    -
    2643
    -
    2644 protected:
    -
    2645 IRequest* m_request;
    -
    2646 IResponse* m_response;
    -
    2647 };
    -
    2648#endif
    -
    2649
    -
    2653 enum mode_t
    -
    2654 {
    -
    2655 mode_for_reading = 1 << 0,
    -
    2656 mode_for_writing = 1 << 1,
    -
    2657 mode_for_chmod = 1 << 2,
    -
    2658
    -
    2659 mode_open_existing = 0 << 3,
    -
    2660 mode_truncate_existing = 1 << 3,
    -
    2661 mode_preserve_existing = 2 << 3,
    -
    2662 mode_create_new = 3 << 3,
    -
    2663 mode_create = 4 << 3,
    -
    2664 mode_disposition_mask = 7 << 3,
    -
    2665
    -
    2666 mode_append = 1 << 6,
    -
    2667 mode_text = 0,
    -
    2668 mode_binary = 1 << 7,
    -
    2669
    -
    2670 share_none = 0,
    -
    2671 share_reading = 1 << 8,
    -
    2672 share_writing = 1 << 9,
    -
    2673 share_deleting = 1 << 10,
    -
    2674 share_all = share_reading | share_writing | share_deleting, // Allow others all operations on our file
    -
    2675
    -
    2676 inherit_handle = 1 << 11,
    -
    2677
    -
    2678 hint_write_thru = 1 << 12,
    -
    2679 hint_no_buffering = 1 << 13,
    -
    2680 hint_random_access = 1 << 14,
    -
    2681 hint_sequential_access = 1 << 15,
    -
    2682 };
    -
    2683
    -
    2684#pragma warning(push)
    -
    2685#pragma warning(disable: 4250)
    -
    -
    2689 class file : virtual public basic_file, virtual public basic_sys
    -
    2690 {
    -
    2691 public:
    -
    2692 file(_In_opt_ sys_handle h = invalid_handle, _In_ state_t state = state_t::ok) : basic_sys(h, state) {}
    -
    2693
    -
    -
    2700 file(_In_z_ const schar_t* filename, _In_ int mode)
    -
    2701 {
    -
    2702 open(filename, mode);
    -
    2703 }
    -
    -
    2704
    -
    2711 inline file(_In_ const stdex::sstring& filename, _In_ int mode) : file(filename.c_str(), mode) {}
    -
    2712
    -
    -
    2719 void open(_In_z_ const schar_t* filename, _In_ int mode)
    -
    2720 {
    -
    2721 if (m_h != invalid_handle)
    -
    2722 close();
    -
    2723
    -
    2724#ifdef _WIN32
    -
    2725 DWORD dwDesiredAccess = 0;
    -
    2726 if (mode & mode_for_reading) dwDesiredAccess |= GENERIC_READ;
    -
    2727 if (mode & mode_for_writing) dwDesiredAccess |= GENERIC_WRITE;
    -
    2728 if (mode & mode_for_chmod) dwDesiredAccess |= FILE_WRITE_ATTRIBUTES;
    -
    2729
    -
    2730 DWORD dwShareMode = 0;
    -
    2731 if (mode & share_reading) dwShareMode |= FILE_SHARE_READ;
    -
    2732 if (mode & share_writing) dwShareMode |= FILE_SHARE_WRITE;
    -
    2733 if (mode & share_deleting) dwShareMode |= FILE_SHARE_DELETE;
    -
    2734
    -
    2735 SECURITY_ATTRIBUTES sa = { sizeof(SECURITY_ATTRIBUTES) };
    -
    2736 sa.bInheritHandle = mode & inherit_handle ? true : false;
    -
    2737
    -
    2738 DWORD dwCreationDisposition;
    -
    2739 switch (mode & mode_disposition_mask) {
    -
    2740 case mode_open_existing: dwCreationDisposition = OPEN_EXISTING; break;
    -
    2741 case mode_truncate_existing: dwCreationDisposition = TRUNCATE_EXISTING; break;
    -
    2742 case mode_preserve_existing: dwCreationDisposition = OPEN_ALWAYS; break;
    -
    2743 case mode_create_new: dwCreationDisposition = CREATE_NEW; break;
    -
    2744 case mode_create: dwCreationDisposition = CREATE_ALWAYS; break;
    -
    2745 default: throw std::invalid_argument("invalid mode");
    -
    2746 }
    -
    2747
    -
    2748 DWORD dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL;
    -
    2749 if (mode & hint_write_thru) dwFlagsAndAttributes |= FILE_FLAG_WRITE_THROUGH;
    -
    2750 if (mode & hint_no_buffering) dwFlagsAndAttributes |= FILE_FLAG_NO_BUFFERING;
    -
    2751 if (mode & hint_random_access) dwFlagsAndAttributes |= FILE_FLAG_RANDOM_ACCESS;
    -
    2752 if (mode & hint_sequential_access) dwFlagsAndAttributes |= FILE_FLAG_SEQUENTIAL_SCAN;
    -
    2753
    -
    2754 m_h = CreateFile(filename, dwDesiredAccess, dwShareMode, &sa, dwCreationDisposition, dwFlagsAndAttributes, NULL);
    -
    2755#else
    -
    2756 int flags = 0;
    -
    2757 switch (mode & (mode_for_reading | mode_for_writing)) {
    -
    2758 case mode_for_reading: flags |= O_RDONLY; break;
    -
    2759 case mode_for_writing: flags |= O_WRONLY; break;
    -
    2760 case mode_for_reading | mode_for_writing: flags |= O_RDWR; break;
    -
    2761 }
    -
    2762 switch (mode & mode_disposition_mask) {
    -
    2763 case mode_open_existing: break;
    -
    2764 case mode_truncate_existing: flags |= O_TRUNC; break;
    -
    2765 case mode_preserve_existing: flags |= O_CREAT; break;
    -
    2766 case mode_create_new: flags |= O_CREAT | O_EXCL; break;
    -
    2767 case mode_create: flags |= O_CREAT | O_TRUNC; break;
    -
    2768 default: throw std::invalid_argument("invalid mode");
    -
    2769 }
    -
    2770 if (mode & hint_write_thru) flags |= O_DSYNC;
    -
    2771#ifndef __APPLE__
    -
    2772 if (mode & hint_no_buffering) flags |= O_RSYNC;
    -
    2773#endif
    -
    2774
    -
    2775 m_h = ::open(filename, flags, DEFFILEMODE);
    -
    2776#endif
    -
    2777 if (m_h != invalid_handle) {
    -
    2778 m_state = state_t::ok;
    -
    2779 if (mode & mode_append)
    -
    2780 seek(0, seek_t::end);
    -
    2781 }
    -
    2782 else
    -
    2783 m_state = state_t::fail;
    -
    2784 }
    -
    -
    2785
    -
    -
    2792 inline void open(_In_ const stdex::sstring& filename, _In_ int mode)
    -
    2793 {
    -
    2794 open(filename.c_str(), mode);
    -
    2795 }
    -
    -
    2796
    -
    -
    2797 virtual fpos_t seek(_In_ foff_t offset, _In_ seek_t how = seek_t::beg)
    -
    2798 {
    -
    2799#ifdef _WIN32
    -
    2800 LARGE_INTEGER li;
    -
    2801 li.QuadPart = offset;
    -
    2802 li.LowPart = SetFilePointer(m_h, li.LowPart, &li.HighPart, static_cast<DWORD>(how));
    -
    2803 if (li.LowPart != 0xFFFFFFFF || GetLastError() == NO_ERROR) {
    -
    2804 m_state = state_t::ok;
    -
    2805 return li.QuadPart;
    -
    2806 }
    -
    2807#else
    -
    2808 off64_t result = lseek64(m_h, offset, static_cast<int>(how));
    -
    2809 if (result >= 0) {
    -
    2810 m_state = state_t::ok;
    -
    2811 return result;
    -
    2812 }
    -
    2813#endif
    -
    2814 m_state = state_t::fail;
    -
    2815 return fpos_max;
    -
    2816 }
    -
    -
    2817
    -
    -
    2818 virtual fpos_t tell() const
    -
    2819 {
    -
    2820 if (m_h != invalid_handle) {
    -
    2821#ifdef _WIN32
    -
    2822 LARGE_INTEGER li;
    -
    2823 li.QuadPart = 0;
    -
    2824 li.LowPart = SetFilePointer(m_h, 0, &li.HighPart, FILE_CURRENT);
    -
    2825 if (li.LowPart != 0xFFFFFFFF || GetLastError() == NO_ERROR)
    -
    2826 return li.QuadPart;
    -
    2827#else
    -
    2828 off64_t result = lseek64(m_h, 0, SEEK_CUR);
    -
    2829 if (result >= 0)
    -
    2830 return result;
    -
    2831#endif
    -
    2832 }
    -
    2833 return fpos_max;
    -
    2834 }
    -
    -
    2835
    -
    -
    2836 virtual void lock(_In_ fpos_t offset, _In_ fsize_t length)
    -
    2837 {
    -
    2838#ifdef _WIN32
    -
    2839 LARGE_INTEGER liOffset;
    -
    2840 LARGE_INTEGER liSize;
    -
    2841 liOffset.QuadPart = offset;
    -
    2842 liSize.QuadPart = length;
    -
    2843 if (LockFile(m_h, liOffset.LowPart, liOffset.HighPart, liSize.LowPart, liSize.HighPart)) {
    -
    2844 m_state = state_t::ok;
    -
    2845 return;
    -
    2846 }
    -
    2847#else
    -
    2848 off64_t orig = lseek64(m_h, 0, SEEK_CUR);
    -
    2849 if (orig >= 0) {
    -
    2850 m_state = lseek64(m_h, offset, SEEK_SET) >= 0 && lockf64(m_h, F_LOCK, length) >= 0 ? state_t::ok : state_t::fail;
    -
    2851 lseek64(m_h, orig, SEEK_SET);
    -
    2852 m_state = state_t::ok;
    -
    2853 return;
    -
    2854 }
    -
    2855#endif
    -
    2856 m_state = state_t::fail;
    -
    2857 }
    -
    -
    2858
    -
    -
    2859 virtual void unlock(_In_ fpos_t offset, _In_ fsize_t length)
    -
    2860 {
    -
    2861#ifdef _WIN32
    -
    2862 LARGE_INTEGER liOffset;
    -
    2863 LARGE_INTEGER liSize;
    -
    2864 liOffset.QuadPart = offset;
    -
    2865 liSize.QuadPart = length;
    -
    2866 if (UnlockFile(m_h, liOffset.LowPart, liOffset.HighPart, liSize.LowPart, liSize.HighPart)) {
    -
    2867 m_state = state_t::ok;
    -
    2868 return;
    -
    2869 }
    -
    2870#else
    -
    2871 off64_t orig = lseek64(m_h, 0, SEEK_CUR);
    -
    2872 if (orig >= 0) {
    -
    2873 if (lseek64(m_h, offset, SEEK_SET) >= 0 && lockf64(m_h, F_ULOCK, length) >= 0) {
    -
    2874 lseek64(m_h, orig, SEEK_SET);
    -
    2875 m_state = state_t::ok;
    -
    2876 return;
    -
    2877 }
    -
    2878 lseek64(m_h, orig, SEEK_SET);
    -
    2879 }
    -
    2880#endif
    -
    2881 m_state = state_t::fail;
    -
    2882 }
    -
    -
    2883
    -
    -
    2884 virtual fsize_t size()
    -
    2885 {
    -
    2886#ifdef _WIN32
    -
    2887 LARGE_INTEGER li;
    -
    2888 li.LowPart = GetFileSize(m_h, (LPDWORD)&li.HighPart);
    -
    2889 if (li.LowPart == 0xFFFFFFFF && GetLastError() != NO_ERROR)
    -
    2890 li.QuadPart = -1;
    -
    2891 return li.QuadPart;
    -
    2892#else
    -
    2893 off64_t length = -1, orig = lseek64(m_h, 0, SEEK_CUR);
    -
    2894 if (orig >= 0) {
    -
    2895 length = lseek64(m_h, 0, SEEK_END);
    -
    2896 lseek64(m_h, orig, SEEK_SET);
    -
    2897 }
    -
    2898 return length;
    -
    2899#endif
    -
    2900 }
    -
    -
    2901
    -
    -
    2902 virtual void truncate()
    -
    2903 {
    -
    2904#ifdef _WIN32
    -
    2905 if (SetEndOfFile(m_h)) {
    -
    2906 m_state = state_t::ok;
    -
    2907 return;
    -
    2908 }
    -
    2909#else
    -
    2910 off64_t length = lseek64(m_h, 0, SEEK_CUR);
    -
    2911 if (length >= 0 && ftruncate64(m_h, length) >= 0) {
    -
    2912 m_state = state_t::ok;
    -
    2913 return;
    -
    2914 }
    -
    2915#endif
    -
    2916 m_state = state_t::fail;
    -
    2917 }
    -
    -
    2918
    -
    2919#ifdef _WIN32
    -
    2920 static inline time_point ft2tp(_In_ const FILETIME& ft)
    -
    2921 {
    -
    2922#if _HAS_CXX20
    -
    2923 uint64_t t = (static_cast<int64_t>(ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
    -
    2924#else
    -
    2925 uint64_t t = ((static_cast<int64_t>(ft.dwHighDateTime) << 32) | ft.dwLowDateTime) - 116444736000000000ll;
    -
    2926#endif
    -
    2927 return time_point(time_point::duration(t));
    -
    2928 }
    -
    2929
    -
    2930 static inline void tp2ft(_In_ time_point tp, _Out_ FILETIME& ft)
    -
    2931 {
    -
    2932#if _HAS_CXX20
    -
    2933 uint64_t t = tp.time_since_epoch().count();
    -
    2934#else
    -
    2935 uint64_t t = tp.time_since_epoch().count() + 116444736000000000ll;
    -
    2936#endif
    -
    2937 ft.dwHighDateTime = static_cast<DWORD>((t >> 32) & 0xffffffff);
    -
    2938 ft.dwLowDateTime = static_cast<DWORD>(t & 0xffffffff);
    -
    2939 }
    -
    2940#endif
    -
    2941
    -
    -
    2942 virtual time_point ctime() const
    -
    2943 {
    -
    2944#ifdef _WIN32
    -
    2945 FILETIME ft;
    -
    2946 if (GetFileTime(m_h, &ft, nullptr, nullptr))
    -
    2947 return ft2tp(ft);
    -
    2948#endif
    -
    2949 return time_point::min();
    -
    2950 }
    -
    -
    2951
    -
    -
    2952 virtual time_point atime() const
    -
    2953 {
    -
    2954#ifdef _WIN32
    -
    2955 FILETIME ft;
    -
    2956 if (GetFileTime(m_h, nullptr, &ft, nullptr))
    -
    2957 return ft2tp(ft);
    -
    2958#else
    -
    2959 struct stat buf;
    -
    2960 if (fstat(m_h, &buf) >= 0)
    -
    2961 return clock::from_time_t(buf.st_atime);
    -
    2962#endif
    -
    2963 return time_point::min();
    -
    2964 }
    -
    -
    2965
    -
    -
    2966 virtual time_point mtime() const
    -
    2967 {
    -
    2968#ifdef _WIN32
    -
    2969 FILETIME ft;
    -
    2970 if (GetFileTime(m_h, nullptr, nullptr, &ft))
    -
    2971 return ft2tp(ft);
    -
    2972#else
    -
    2973 struct stat buf;
    -
    2974 if (fstat(m_h, &buf) >= 0)
    -
    2975 return clock::from_time_t(buf.st_mtime);
    -
    2976#endif
    -
    2977 return time_point::min();
    -
    2978 }
    -
    -
    2979
    -
    -
    2980 virtual void set_ctime(time_point date)
    -
    2981 {
    -
    2982 _Assume_(m_h != invalid_handle);
    -
    2983#ifdef _WIN32
    -
    2984 FILETIME ft;
    -
    2985 tp2ft(date, ft);
    -
    2986 if (SetFileTime(m_h, &ft, nullptr, nullptr))
    -
    2987 return;
    -
    2988 throw std::system_error(GetLastError(), std::system_category(), "SetFileTime failed");
    -
    2989#else
    -
    2990 throw std::runtime_error("not supported");
    -
    2991#endif
    -
    2992 }
    -
    -
    2993
    -
    -
    2994 virtual void set_atime(time_point date)
    -
    2995 {
    -
    2996 _Assume_(m_h != invalid_handle);
    -
    2997#ifdef _WIN32
    -
    2998 FILETIME ft;
    -
    2999 tp2ft(date, ft);
    -
    3000 if (SetFileTime(m_h, nullptr, &ft, nullptr))
    -
    3001 return;
    -
    3002 throw std::system_error(GetLastError(), std::system_category(), "SetFileTime failed");
    -
    3003#else
    -
    3004 struct timespec ts[2] = {
    -
    3005 { date.time_since_epoch().count(), 0 },
    -
    3006 { 0, UTIME_OMIT },
    -
    3007 };
    -
    3008 if (futimens(m_h, ts) >= 0)
    -
    3009 return;
    -
    3010 throw std::system_error(errno, std::system_category(), "futimens failed");
    -
    3011#endif
    -
    3012 }
    -
    -
    3013
    -
    -
    3014 virtual void set_mtime(time_point date)
    -
    3015 {
    -
    3016#ifdef _WIN32
    -
    3017 FILETIME ft;
    -
    3018 tp2ft(date, ft);
    -
    3019 if (SetFileTime(m_h, nullptr, nullptr, &ft))
    -
    3020 return;
    -
    3021 throw std::system_error(GetLastError(), std::system_category(), "SetFileTime failed");
    -
    3022#else
    -
    3023 struct timespec ts[2] = {
    -
    3024 { 0, UTIME_OMIT },
    -
    3025 { date.time_since_epoch().count(), 0 },
    -
    3026 };
    -
    3027 if (futimens(m_h, ts) >= 0)
    -
    3028 return;
    -
    3029 throw std::system_error(errno, std::system_category(), "futimens failed");
    -
    3030#endif
    -
    3031 }
    -
    -
    3032
    -
    -
    3038 static bool exists(_In_z_ const stdex::schar_t* filename)
    -
    3039 {
    -
    3040#ifdef _WIN32
    -
    3041 return GetFileAttributes(filename) != INVALID_FILE_ATTRIBUTES;
    -
    3042#else
    -
    3043 struct stat s;
    -
    3044 return stat(filename, &s) == 0;
    -
    3045#endif
    -
    3046 }
    -
    -
    3047
    -
    -
    3053 static inline bool exists(_In_ const stdex::sstring& filename)
    -
    3054 {
    -
    3055 return exists(filename.c_str());
    -
    3056 }
    -
    -
    3057
    -
    -
    3065 static bool readonly(_In_z_ const stdex::schar_t* filename)
    -
    3066 {
    -
    3067#ifdef _WIN32
    -
    3068 DWORD dwAttr = GetFileAttributes(filename);
    -
    3069 return dwAttr != INVALID_FILE_ATTRIBUTES && (dwAttr & FILE_ATTRIBUTE_READONLY) != 0;
    -
    3070#else
    -
    3071 struct stat s;
    -
    3072 return stat(filename, &s) == 0 && (s.st_mode & (S_IWUSR|S_IWGRP|S_IWOTH)) == 0;
    -
    3073#endif
    -
    3074 }
    -
    -
    3075
    -
    -
    3083 static inline bool readonly(_In_ const stdex::sstring& filename)
    -
    3084 {
    -
    3085 return readonly(filename.c_str());
    -
    3086 }
    -
    -
    3087 };
    -
    -
    3088#pragma warning(pop)
    -
    3089
    -
    -
    3093 class cached_file : public cache
    -
    3094 {
    -
    3095 public:
    -
    3096 cached_file(_In_opt_ sys_handle h = invalid_handle, _In_ state_t state = state_t::ok, _In_ size_t cache_size = default_cache_size) :
    -
    3097 cache(cache_size),
    -
    3098 m_source(h, state)
    -
    3099 {
    -
    3100 init(m_source);
    -
    3101 }
    -
    3102
    -
    -
    3110 cached_file(_In_z_ const schar_t* filename, _In_ int mode, _In_ size_t cache_size = default_cache_size) :
    -
    3111 cache(cache_size),
    -
    3112 m_source(filename, mode & mode_for_writing ? mode | mode_for_reading : mode)
    -
    3113 {
    -
    3114 init(m_source);
    -
    3115 }
    -
    -
    3116
    -
    3124 inline cached_file(_In_ const stdex::sstring& filename, _In_ int mode, _In_ size_t cache_size = default_cache_size) : cached_file(filename.c_str(), mode, cache_size) {}
    -
    3125
    -
    3126 virtual ~cached_file()
    -
    3127 {
    -
    3128 done();
    -
    3129 }
    -
    3130
    -
    -
    3137 void open(_In_z_ const schar_t* filename, _In_ int mode)
    -
    3138 {
    -
    3139 invalidate_cache();
    -
    3140 if (!ok()) _Unlikely_{
    -
    3141 m_state = state_t::fail;
    -
    3142 return;
    -
    3143 }
    -
    3144 m_source.open(filename, mode & mode_for_writing ? mode | mode_for_reading : mode);
    -
    3145 if (m_source.ok()) {
    -
    3146 init();
    -
    3147 return;
    -
    3148 }
    -
    3149 m_state = state_t::fail;
    -
    3150 }
    -
    -
    3151
    -
    -
    3158 inline void open(_In_ const stdex::sstring& filename, _In_ int mode)
    -
    3159 {
    -
    3160 open(filename.c_str(), mode);
    -
    3161 }
    -
    -
    3162
    -
    3163 protected:
    -
    3164 file m_source;
    -
    3165 };
    -
    -
    3166
    -
    - -
    3171 {
    -
    3172 public:
    -
    3173 memory_file(_In_ state_t state = state_t::ok) :
    -
    3174 basic(state),
    -
    3175 m_data(nullptr),
    -
    3176 m_offset(0),
    -
    3177 m_size(0),
    -
    3178 m_reserved(0),
    -
    3179 m_manage(true)
    -
    3180 {
    -
    3181#if SET_FILE_OP_TIMES
    -
    3182 m_ctime = m_atime = m_mtime = time_point::now();
    -
    3183#endif
    -
    3184 }
    -
    3185
    -
    -
    3192 memory_file(_In_ size_t size, _In_ state_t state = state_t::ok) :
    -
    3193 basic(state),
    -
    3194 m_data(reinterpret_cast<uint8_t*>(malloc(size))),
    -
    3195 m_offset(0),
    -
    3196 m_size(0),
    - -
    3198 m_manage(true)
    -
    3199 {
    -
    3200 if (!m_data)
    -
    3201 throw std::bad_alloc();
    -
    3202#if SET_FILE_OP_TIMES
    -
    3203 m_ctime = m_atime = m_mtime = time_point::now();
    -
    3204#endif
    -
    3205 }
    -
    -
    3206
    -
    -
    3216 memory_file(_Inout_ void* data, _In_ size_t size, _In_ size_t reserved, _In_ bool manage = false, _In_ state_t state = state_t::ok) :
    -
    3217 basic(state),
    -
    3218 m_data(reinterpret_cast<uint8_t*>(data)),
    -
    3219 m_offset(0),
    -
    3220 m_size(size),
    -
    3221 m_reserved(reserved),
    -
    3222 m_manage(manage)
    -
    3223 {
    -
    3224 _Assume_(data || !size);
    -
    3225 _Assume_(reserved >= size);
    -
    3226#if SET_FILE_OP_TIMES
    -
    3227 m_ctime = m_atime = m_mtime = time_point::now();
    -
    3228#endif
    -
    3229 }
    -
    -
    3230
    -
    -
    3239 memory_file(_Inout_ void* data, _In_ size_t size, _In_ bool manage = false, _In_ state_t state = state_t::ok) :
    -
    3240 memory_file(data, size, size, manage, state)
    -
    3241 {}
    -
    -
    3242
    -
    -
    3249 memory_file(_In_z_ const schar_t* filename, _In_ int mode) : memory_file()
    -
    3250 {
    -
    3251 load(filename, mode);
    -
    3252 }
    -
    -
    3253
    -
    3260 inline memory_file(_In_ const stdex::sstring& filename, _In_ int mode) : memory_file(filename.c_str(), mode) {}
    -
    3261
    -
    3262 virtual ~memory_file()
    -
    3263 {
    -
    3264 if (m_manage && m_data)
    -
    3265 free(m_data);
    -
    3266 }
    -
    3267
    -
    -
    3274 void reserve(_In_ size_t required, _In_ bool tight = false) noexcept
    -
    3275 {
    -
    3276 if (required <= m_reserved && (!tight || required >= m_reserved)) {
    -
    3277 m_state = state_t::ok;
    -
    3278 return;
    -
    3279 }
    -
    3280 if (!m_manage) {
    -
    3281 m_state = state_t::fail;
    -
    3282 return;
    -
    3283 }
    -
    3284 size_t reserved = tight ? required : ((required + required / 4 + (default_block_size - 1)) / default_block_size) * default_block_size;
    -
    3285 auto data = reinterpret_cast<uint8_t*>(realloc(m_data, reserved));
    -
    3286 if (!data && reserved) _Unlikely_ {
    -
    3287 m_state = state_t::fail;
    -
    3288 return;
    -
    3289 }
    -
    3290 m_data = data;
    -
    3291 if (reserved < m_size)
    -
    3292 m_size = reserved;
    -
    3293 m_reserved = reserved;
    -
    3294 m_state = state_t::ok;
    -
    3295 }
    -
    -
    3296
    -
    -
    3303 void load(_In_z_ const schar_t* filename, _In_ int mode)
    -
    3304 {
    -
    3305 file f(filename, (mode & ~hint_random_access) | mode_for_reading | hint_sequential_access);
    -
    3306 if (!f.ok()) {
    -
    3307 m_state = state_t::fail;
    -
    3308 return;
    -
    3309 }
    -
    3310 fsize_t size = f.size();
    -
    3311 if (size > SIZE_MAX) {
    -
    3312 m_state = state_t::fail;
    -
    3313 return;
    -
    3314 }
    -
    3315 reserve(static_cast<size_t>(size), true);
    -
    3316 if (!ok()) _Unlikely_ {
    -
    3317 return;
    -
    3318 }
    -
    3319 m_offset = m_size = 0;
    -
    3320 write_stream(f);
    -
    3321 if (ok())
    -
    3322 m_offset = 0;
    -
    3323#if SET_FILE_OP_TIMES
    -
    3324 m_ctime = f.ctime();
    -
    3325 m_atime = f.atime();
    -
    3326 m_mtime = f.mtime();
    -
    3327#endif
    -
    3328 }
    -
    -
    3329
    -
    -
    3336 inline void load(_In_ const stdex::sstring& filename, _In_ int mode)
    -
    3337 {
    -
    3338 load(filename.c_str(), mode);
    -
    3339 }
    -
    -
    3340
    -
    -
    3347 void save(_In_z_ const schar_t* filename, _In_ int mode)
    -
    3348 {
    -
    3349 file f(filename, (mode & ~hint_random_access) | mode_for_writing | hint_sequential_access);
    -
    3350 if (!f.ok()) {
    -
    3351 m_state = state_t::fail;
    -
    3352 return;
    -
    3353 }
    -
    3354 f.write(m_data, m_size);
    -
    3355 if (!f.ok()) {
    -
    3356 m_state = state_t::fail;
    -
    3357 return;
    -
    3358 }
    -
    3359 f.truncate();
    -
    3360#if SET_FILE_OP_TIMES
    -
    3361 f.set_ctime(m_ctime);
    -
    3362 f.set_atime(m_atime);
    -
    3363 f.set_mtime(m_mtime);
    -
    3364#endif
    -
    3365 }
    -
    -
    3366
    -
    -
    3373 inline void save(_In_ const stdex::sstring& filename, _In_ int mode)
    -
    3374 {
    -
    3375 save(filename.c_str(), mode);
    -
    3376 }
    -
    -
    3377
    -
    3381 inline const void* data() const { return m_data; }
    -
    3382
    -
    -
    3383 virtual _Success_(return != 0 || length == 0) size_t read(
    -
    3384 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
    -
    3385 {
    -
    3386 _Assume_(data || !length);
    -
    3387#if SET_FILE_OP_TIMES
    -
    3388 m_atime = time_point::now();
    -
    3389#endif
    -
    3390 size_t available = m_size - m_offset;
    -
    3391 if (length <= available) {
    -
    3392 memcpy(data, m_data + m_offset, length);
    -
    3393 m_offset += length;
    -
    3394 m_state = state_t::ok;
    -
    3395 return length;
    -
    3396 }
    -
    3397 if (length && !available) {
    -
    3398 m_state = state_t::eof;
    -
    3399 return 0;
    -
    3400 }
    -
    3401 memcpy(data, m_data + m_offset, available);
    -
    3402 m_offset += available;
    -
    3403 m_state = state_t::ok;
    -
    3404 return available;
    -
    3405 }
    -
    -
    3406
    -
    3421 template <class T>
    -
    -
    3422 inline memory_file& read_data(_Out_ T& data)
    -
    3423 {
    -
    3424#if SET_FILE_OP_TIMES
    -
    3425 m_atime = time_point::now();
    -
    3426#endif
    -
    3427 if (CHECK_STREAM_STATE && !ok()) _Unlikely_ {
    -
    3428 data = 0;
    -
    3429 return *this;
    -
    3430 }
    -
    3431 size_t end_offset = m_offset + sizeof(T);
    -
    3432 if (end_offset <= m_size) {
    -
    3433 data = LE2HE(*reinterpret_cast<T*>(m_data + m_offset));
    -
    3434 m_offset = end_offset;
    -
    3435#if !CHECK_STREAM_STATE
    -
    3436 m_state = state_t::ok;
    -
    3437#endif
    -
    3438 }
    -
    3439 else {
    -
    3440 data = 0;
    -
    3441 m_offset = m_size;
    -
    3442 m_state = state_t::eof;
    -
    3443 }
    -
    3444 return *this;
    -
    3445 }
    -
    -
    3446
    -
    3461 template<class _Elem, class _Traits = std::char_traits<_Elem>, class _Ax = std::allocator<_Elem>>
    -
    -
    3462 memory_file& read_str(_Inout_ std::basic_string<_Elem, _Traits, _Ax>&data)
    -
    3463 {
    -
    3464#if SET_FILE_OP_TIMES
    -
    3465 m_atime = time_point::now();
    -
    3466#endif
    -
    3467 if (CHECK_STREAM_STATE && !ok()) _Unlikely_ {
    -
    3468 data.clear();
    -
    3469 return *this;
    -
    3470 }
    -
    3471 size_t end_offset = m_offset + sizeof(uint32_t);
    -
    3472 if (end_offset <= m_size) {
    -
    3473 uint32_t num_chars = LE2HE(*reinterpret_cast<uint32_t*>(m_data + m_offset));
    -
    3474 m_offset = end_offset;
    -
    3475 end_offset = stdex::add(m_offset, stdex::mul(num_chars, sizeof(_Elem)));
    -
    3476 _Elem* start = reinterpret_cast<_Elem*>(m_data + m_offset);
    -
    3477 if (end_offset <= m_size) {
    -
    3478 data.assign(start, start + num_chars);
    -
    3479 m_offset = end_offset;
    -
    3480#if !CHECK_STREAM_STATE
    -
    3481 m_state = state_t::ok;
    -
    3482#endif
    -
    3483 return *this;
    -
    3484 }
    -
    3485 if (end_offset <= m_size)
    -
    3486 data.assign(start, reinterpret_cast<_Elem*>(m_data + m_size));
    -
    3487 }
    -
    3488 m_offset = m_size;
    -
    3489 m_state = state_t::eof;
    -
    3490 return *this;
    -
    3491 }
    -
    -
    3492
    -
    -
    3493 virtual _Success_(return != 0) size_t write(
    -
    3494 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
    -
    3495 {
    -
    3496 _Assume_(data || !length);
    -
    3497#if SET_FILE_OP_TIMES
    -
    3498 m_atime = m_mtime = time_point::now();
    -
    3499#endif
    -
    3500 size_t end_offset = m_offset + length;
    -
    3501 if (end_offset > m_reserved) {
    -
    3502 reserve(end_offset);
    -
    3503 if (!ok()) _Unlikely_
    -
    3504 return 0;
    -
    3505 }
    -
    3506 memcpy(m_data + m_offset, data, length);
    -
    3507 m_offset = end_offset;
    -
    3508 if (m_offset > m_size)
    -
    3509 m_size = m_offset;
    -
    3510 m_state = state_t::ok;
    -
    3511 return length;
    -
    3512 }
    -
    -
    3513
    -
    -
    3517 void write_byte(_In_ uint8_t byte, _In_ size_t amount = 1)
    -
    3518 {
    -
    3519#if SET_FILE_OP_TIMES
    -
    3520 m_atime = m_mtime = time_point::now();
    -
    3521#endif
    -
    3522 size_t end_offset = m_offset + amount;
    -
    3523 if (end_offset > m_reserved) {
    -
    3524 reserve(end_offset);
    -
    3525 if (!ok()) _Unlikely_
    -
    3526 return;
    -
    3527 }
    -
    3528 memset(m_data + m_offset, byte, amount);
    -
    3529 m_offset = end_offset;
    -
    3530 if (m_offset > m_size)
    -
    3531 m_size = m_offset;
    -
    3532 m_state = state_t::ok;
    -
    3533 }
    -
    -
    3534
    -
    3549 template <class T>
    -
    -
    3550 inline memory_file& write_data(const T data)
    -
    3551 {
    -
    3552#if SET_FILE_OP_TIMES
    -
    3553 m_atime = m_mtime = time_point::now();
    -
    3554#endif
    -
    3555 if (CHECK_STREAM_STATE && !ok()) _Unlikely_
    -
    3556 return *this;
    -
    3557 size_t end_offset = m_offset + sizeof(T);
    -
    3558 if (end_offset > m_reserved) {
    -
    3559 reserve(end_offset);
    -
    3560 if (!ok()) _Unlikely_
    -
    3561 return *this;
    -
    3562 }
    -
    3563 (*reinterpret_cast<T*>(m_data + m_offset)) = HE2LE(data);
    -
    3564 m_offset = end_offset;
    -
    3565 if (m_offset > m_size)
    -
    3566 m_size = m_offset;
    -
    3567#if !CHECK_STREAM_STATE
    -
    3568 m_state = state_t::ok;
    -
    3569#endif
    -
    3570 return *this;
    -
    3571 }
    -
    -
    3572
    -
    3587 template <class T>
    -
    -
    3588 inline memory_file& write_str(_In_z_ const T * data)
    -
    3589 {
    -
    3590#if SET_FILE_OP_TIMES
    -
    3591 m_atime = m_mtime = time_point::now();
    -
    3592#endif
    -
    3593 if (CHECK_STREAM_STATE && !ok()) _Unlikely_
    -
    3594 return *this;
    -
    3595 size_t num_chars = stdex::strlen(data);
    -
    3596 if (num_chars > UINT32_MAX)
    -
    3597 throw std::invalid_argument("string too long");
    -
    3598 size_t size_chars = num_chars * sizeof(T);
    -
    3599 size_t size = sizeof(uint32_t) + size_chars;
    -
    3600 size_t end_offset = m_offset + size;
    -
    3601 if (end_offset > m_reserved) {
    -
    3602 reserve(end_offset);
    -
    3603 if (!ok()) _Unlikely_
    -
    3604 return *this;
    -
    3605 }
    -
    3606 auto p = m_data + m_offset;
    -
    3607 *reinterpret_cast<uint32_t*>(p) = HE2LE((uint32_t)num_chars);
    -
    3608 memcpy(p + sizeof(uint32_t), data, size_chars);
    -
    3609 m_offset = end_offset;
    -
    3610 if (m_offset > m_size)
    -
    3611 m_size = m_offset;
    -
    3612#if !CHECK_STREAM_STATE
    -
    3613 m_state = state_t::ok;
    -
    3614#endif
    -
    3615 return *this;
    -
    3616 }
    -
    -
    3617
    -
    3632 template<class _Elem, class _Traits = std::char_traits<_Elem>, class _Ax = std::allocator<_Elem>>
    -
    -
    3633 inline memory_file& write_str(_In_ const std::basic_string<_Elem, _Traits, _Ax>& data)
    -
    3634 {
    -
    3635#if SET_FILE_OP_TIMES
    -
    3636 m_atime = m_mtime = time_point::now();
    -
    3637#endif
    -
    3638 if (CHECK_STREAM_STATE && !ok()) _Unlikely_
    -
    3639 return *this;
    -
    3640 size_t num_chars = data.size();
    -
    3641 if (num_chars > UINT32_MAX)
    -
    3642 throw std::invalid_argument("string too long");
    -
    3643 size_t size_chars = num_chars * sizeof(_Elem);
    -
    3644 size_t size = sizeof(uint32_t) + size_chars;
    -
    3645 size_t end_offset = m_offset + size;
    -
    3646 if (end_offset > m_reserved) {
    -
    3647 reserve(end_offset);
    -
    3648 if (!ok()) _Unlikely_
    -
    3649 return *this;
    -
    3650 }
    -
    3651 auto p = m_data + m_offset;
    -
    3652 *reinterpret_cast<uint32_t*>(p) = HE2LE((uint32_t)num_chars);
    -
    3653 memcpy(p + sizeof(uint32_t), data.data(), size_chars);
    -
    3654 m_offset = end_offset;
    -
    3655 if (m_offset > m_size)
    -
    3656 m_size = m_offset;
    -
    3657#if !CHECK_STREAM_STATE
    -
    3658 m_state = state_t::ok;
    -
    3659#endif
    -
    3660 return *this;
    -
    3661 }
    -
    -
    3662
    -
    -
    3668 size_t write_stream(_Inout_ basic & stream, _In_ size_t amount = SIZE_MAX)
    -
    3669 {
    -
    3670#if SET_FILE_OP_TIMES
    -
    3671 m_atime = m_mtime = time_point::now();
    -
    3672#endif
    -
    3673 size_t num_read, dst_offset = m_offset, dst_size = m_offset;
    -
    3674 size_t num_copied = 0, to_write = amount;
    -
    3675 m_state = state_t::ok;
    -
    3676 if (amount != SIZE_MAX) {
    -
    3677 dst_size = stdex::add(dst_size, amount);
    -
    3678 reserve(dst_size);
    -
    3679 if (!ok()) _Unlikely_
    -
    3680 return 0;
    -
    3681 while (to_write) {
    -
    3682 num_read = stream.read(m_data + dst_offset, to_write);
    -
    3683 dst_size = dst_offset += num_read;
    -
    3684 num_copied += num_read;
    -
    3685 to_write -= num_read;
    -
    3686 if (!stream.ok()) {
    -
    3687 if (stream.state() != state_t::eof)
    -
    3688 m_state = state_t::fail;
    -
    3689 break;
    -
    3690 }
    -
    3691 };
    -
    3692 }
    -
    3693 else {
    -
    3694 size_t block_size;
    -
    3695 while (to_write) {
    -
    3696 block_size = std::min(to_write, default_block_size);
    -
    3697 dst_size = stdex::add(dst_size, block_size);
    -
    3698 reserve(dst_size);
    -
    3699 if (!ok()) _Unlikely_
    -
    3700 break;
    -
    3701 num_read = stream.read(m_data + dst_offset, block_size);
    -
    3702 dst_size = dst_offset += num_read;
    -
    3703 num_copied += num_read;
    -
    3704 to_write -= num_read;
    -
    3705 if (!stream.ok()) {
    -
    3706 if (stream.state() != state_t::eof)
    -
    3707 m_state = state_t::fail;
    -
    3708 break;
    -
    3709 }
    -
    3710 };
    -
    3711 }
    -
    3712 m_offset = dst_offset;
    -
    3713 if (m_offset > m_size)
    -
    3714 m_size = m_offset;
    -
    3715 return num_copied;
    -
    3716 }
    -
    -
    3717
    -
    -
    3718 virtual void close()
    -
    3719 {
    -
    3720 if (m_manage && m_data)
    -
    3721 free(m_data);
    -
    3722 m_data = nullptr;
    -
    3723 m_manage = true;
    -
    3724 m_offset = 0;
    -
    3725 m_size = m_reserved = 0;
    -
    3726#if SET_FILE_OP_TIMES
    -
    3727 m_ctime = m_atime = m_mtime = time_point::min();
    -
    3728#endif
    -
    3729 m_state = state_t::ok;
    -
    3730 }
    -
    -
    3731
    -
    -
    3732 virtual fpos_t seek(_In_ foff_t offset, _In_ seek_t how = seek_t::beg)
    -
    3733 {
    -
    3734 fpos_t target;
    -
    3735 switch (how) {
    -
    3736 case seek_t::beg: target = offset; break;
    -
    3737 case seek_t::cur: target = static_cast<fpos_t>(m_offset) + offset; break;
    -
    3738 case seek_t::end: target = static_cast<fpos_t>(m_size) + offset; break;
    -
    3739 default: throw std::invalid_argument("unknown seek origin");
    -
    3740 }
    -
    3741 if (target <= SIZE_MAX) {
    -
    3742 m_state = state_t::ok;
    -
    3743 return m_offset = static_cast<size_t>(target);
    -
    3744 }
    -
    3745 m_state = state_t::fail;
    -
    3746 return fpos_max;
    -
    3747 }
    -
    -
    3748
    -
    -
    3749 virtual fpos_t tell() const
    -
    3750 {
    -
    3751 return m_offset;
    -
    3752 }
    -
    -
    3753
    -
    -
    3754 virtual fsize_t size()
    -
    3755 {
    -
    3756 return m_size;
    -
    3757 }
    -
    -
    3758
    -
    -
    3759 virtual void truncate()
    -
    3760 {
    -
    3761#if SET_FILE_OP_TIMES
    -
    3762 m_atime = m_mtime = time_point::now();
    -
    3763#endif
    -
    3764 m_size = m_offset;
    - -
    3766 }
    -
    -
    3767
    -
    3768#if SET_FILE_OP_TIMES
    -
    3769 virtual time_point ctime() const
    -
    3770 {
    -
    3771 return m_ctime;
    -
    3772 }
    -
    3773
    -
    3774 virtual time_point atime() const
    -
    3775 {
    -
    3776 return m_atime;
    -
    3777 }
    -
    3778
    -
    3779 virtual time_point mtime() const
    -
    3780 {
    -
    3781 return m_mtime;
    -
    3782 }
    -
    3783
    -
    3784 virtual void set_ctime(time_point date)
    -
    3785 {
    -
    3786 m_ctime = date;
    -
    3787 }
    -
    3788
    -
    3789 virtual void set_atime(time_point date)
    -
    3790 {
    -
    3791 m_atime = date;
    -
    3792 }
    -
    3793
    -
    3794 virtual void set_mtime(time_point date)
    -
    3795 {
    -
    3796 m_mtime = date;
    -
    3797 }
    -
    3798#endif
    -
    3799
    -
    3800 protected:
    -
    3808 template <class T>
    -
    -
    3809 inline void set(_In_ fpos_t offset, _In_ const T data)
    -
    3810 {
    -
    3811#if SET_FILE_OP_TIMES
    -
    3812 m_atime = m_mtime = time_point::now();
    -
    3813#endif
    -
    3814 _Assume_(offset + sizeof(T) < m_size);
    -
    3815 (*reinterpret_cast<T*>(m_data + offset)) = HE2LE(data);
    -
    3816 }
    -
    -
    3817
    -
    3818 public:
    -
    3819 inline void set(_In_ fpos_t offset, _In_ const int8_t data) { set<int8_t>(offset, data); }
    -
    3820 inline void set(_In_ fpos_t offset, _In_ const int16_t data) { set<int16_t>(offset, data); }
    -
    3821 inline void set(_In_ fpos_t offset, _In_ const int32_t data) { set<int32_t>(offset, data); }
    -
    3822 inline void set(_In_ fpos_t offset, _In_ const int64_t data) { set<int64_t>(offset, data); }
    -
    3823 inline void set(_In_ fpos_t offset, _In_ const uint8_t data) { set<uint8_t>(offset, data); }
    -
    3824 inline void set(_In_ fpos_t offset, _In_ const uint16_t data) { set<uint16_t>(offset, data); }
    -
    3825 inline void set(_In_ fpos_t offset, _In_ const uint32_t data) { set<uint32_t>(offset, data); }
    -
    3826 inline void set(_In_ fpos_t offset, _In_ const uint64_t data) { set<uint64_t>(offset, data); }
    -
    3827 inline void set(_In_ fpos_t offset, _In_ const float data) { set<float>(offset, data); }
    -
    3828 inline void set(_In_ fpos_t offset, _In_ const double data) { set<double>(offset, data); }
    -
    3829 inline void set(_In_ fpos_t offset, _In_ const char data) { set<char>(offset, data); }
    -
    3830#ifdef _NATIVE_WCHAR_T_DEFINED
    -
    3831 inline void set(_In_ fpos_t offset, _In_ const wchar_t data) { set<wchar_t>(offset, data); }
    -
    3832#endif
    -
    3833
    -
    3841 protected:
    -
    3842 template <class T>
    -
    -
    3843 inline void get(_In_ fpos_t offset, _Out_ T & data)
    -
    3844 {
    -
    3845 _Assume_(offset + sizeof(T) < m_size);
    -
    3846 data = LE2HE(*(T*)(m_data + offset));
    -
    3847#if SET_FILE_OP_TIMES
    -
    3848 m_atime = time_point::now();
    -
    3849#endif
    -
    3850 }
    -
    -
    3851
    -
    3852 public:
    -
    3853 inline void get(_In_ fpos_t offset, _Out_ int8_t & data) { get<int8_t>(offset, data); }
    -
    3854 inline void get(_In_ fpos_t offset, _Out_ int16_t & data) { get<int16_t>(offset, data); }
    -
    3855 inline void get(_In_ fpos_t offset, _Out_ int32_t & data) { get<int32_t>(offset, data); }
    -
    3856 inline void get(_In_ fpos_t offset, _Out_ int64_t & data) { get<int64_t>(offset, data); }
    -
    3857 inline void get(_In_ fpos_t offset, _Out_ uint8_t & data) { get<uint8_t>(offset, data); }
    -
    3858 inline void get(_In_ fpos_t offset, _Out_ uint16_t & data) { get<uint16_t>(offset, data); }
    -
    3859 inline void get(_In_ fpos_t offset, _Out_ uint32_t & data) { get<uint32_t>(offset, data); }
    -
    3860 inline void get(_In_ fpos_t offset, _Out_ uint64_t & data) { get<uint64_t>(offset, data); }
    -
    3861 inline void get(_In_ fpos_t offset, _Out_ float& data) { get<float>(offset, data); }
    -
    3862 inline void get(_In_ fpos_t offset, _Out_ double& data) { get<double>(offset, data); }
    -
    3863 inline void get(_In_ fpos_t offset, _Out_ char& data) { get<char>(offset, data); }
    -
    3864#ifdef _NATIVE_WCHAR_T_DEFINED
    -
    3865 inline void get(_In_ fpos_t offset, _Out_ wchar_t& data) { get<wchar_t>(offset, data); }
    -
    3866#endif
    -
    3867
    -
    3868 inline memory_file& operator <<(_In_ const int8_t data) { return write_data(data); }
    -
    3869 inline memory_file& operator >>(_Out_ int8_t & data) { return read_data(data); }
    -
    3870 inline memory_file& operator <<(_In_ const int16_t data) { return write_data(data); }
    -
    3871 inline memory_file& operator >>(_Out_ int16_t & data) { return read_data(data); }
    -
    3872 inline memory_file& operator <<(_In_ const int32_t data) { return write_data(data); }
    -
    3873 inline memory_file& operator >>(_Out_ int32_t & data) { return read_data(data); }
    -
    3874 inline memory_file& operator <<(_In_ const int64_t data) { return write_data(data); }
    -
    3875 inline memory_file& operator >>(_Out_ int64_t & data) { return read_data(data); }
    -
    3876 inline memory_file& operator <<(_In_ const uint8_t data) { return write_data(data); }
    -
    3877 inline memory_file& operator >>(_Out_ uint8_t & data) { return read_data(data); }
    -
    3878 inline memory_file& operator <<(_In_ const uint16_t data) { return write_data(data); }
    -
    3879 inline memory_file& operator >>(_Out_ uint16_t & data) { return read_data(data); }
    -
    3880 inline memory_file& operator <<(_In_ const uint32_t data) { return write_data(data); }
    -
    3881 inline memory_file& operator >>(_Out_ uint32_t & data) { return read_data(data); }
    -
    3882 inline memory_file& operator <<(_In_ const uint64_t data) { return write_data(data); }
    -
    3883 inline memory_file& operator >>(_Out_ uint64_t & data) { return read_data(data); }
    -
    3884 inline memory_file& operator <<(_In_ const float data) { return write_data(data); }
    -
    3885 inline memory_file& operator >>(_Out_ float& data) { return read_data(data); }
    -
    3886 inline memory_file& operator <<(_In_ const double data) { return write_data(data); }
    -
    3887 inline memory_file& operator >>(_Out_ double& data) { return read_data(data); }
    -
    3888 inline memory_file& operator <<(_In_ const char data) { return write_data(data); }
    -
    3889 inline memory_file& operator >>(_Out_ char& data) { return read_data(data); }
    -
    3890#ifdef _NATIVE_WCHAR_T_DEFINED
    -
    3891 inline memory_file& operator <<(_In_ const wchar_t data) { return write_data(data); }
    -
    3892 inline memory_file& operator >>(_Out_ wchar_t& data) { return read_data(data); }
    -
    3893#endif
    -
    3894 template<class _Elem, class _Traits = std::char_traits<_Elem>, class _Ax = std::allocator<_Elem>>
    -
    3895 inline memory_file& operator >>(_Out_ std::basic_string<_Elem, _Traits, _Ax>&data) { return read_str(data); }
    -
    3896 template <class T>
    -
    3897 inline memory_file& operator <<(_In_ const T * data) { return write_str(data); }
    -
    3898 template<class _Elem, class _Traits = std::char_traits<_Elem>, class _Ax = std::allocator<_Elem>>
    -
    3899 inline memory_file& operator <<(_In_ const std::basic_string<_Elem, _Traits, _Ax>& data) { return write_str(data); }
    -
    3900
    -
    3901 protected:
    -
    3902 uint8_t* m_data;
    - -
    3904 size_t m_offset;
    -
    3905 size_t m_size;
    -
    3906 size_t m_reserved;
    -
    3907#if SET_FILE_OP_TIMES
    -
    3908 time_point
    -
    3909 m_ctime,
    -
    3910 m_atime,
    -
    3911 m_mtime;
    -
    3912#endif
    -
    3913 };
    -
    -
    3914
    -
    -
    3918 class fifo : public basic {
    -
    3919 public:
    -
    3920 fifo() :
    -
    3921 m_offset(0),
    -
    3922 m_size(0),
    -
    3923 m_head(nullptr),
    -
    3924 m_tail(nullptr)
    -
    3925 {}
    -
    3926
    -
    3927 virtual ~fifo()
    -
    3928 {
    -
    3929 while (m_head) {
    -
    3930 auto p = m_head;
    -
    3931 m_head = p->next;
    -
    3932 delete p;
    -
    3933 }
    -
    3934 }
    -
    3935
    -
    3936#pragma warning(suppress: 6101) // See [2] below
    -
    -
    3937 virtual _Success_(return != 0 || length == 0) size_t read(
    -
    3938 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
    -
    3939 {
    -
    3940 _Assume_(data || !length);
    -
    3941 for (size_t to_read = length;;) {
    -
    3942 if (!m_head) _Unlikely_ {
    -
    3943 m_state = to_read < length || !length ? state_t::ok : state_t::eof;
    -
    3944 return length - to_read; // [2] Code analysis misses `length - to_read` bytes were written to data in previous loop iterations.
    -
    3945 }
    -
    3946 size_t remaining = m_head->size - m_offset;
    -
    3947 if (remaining > to_read) {
    -
    3948 memcpy(data, m_head->data + m_offset, to_read);
    -
    3949 m_offset += to_read;
    -
    3950 m_size -= to_read;
    -
    3951 m_state = state_t::ok;
    -
    3952 return length;
    -
    3953 }
    -
    3954 memcpy(data, m_head->data + m_offset, remaining);
    -
    3955 m_offset = 0;
    -
    3956 m_size -= remaining;
    -
    3957 reinterpret_cast<uint8_t*&>(data) += remaining;
    -
    3958 to_read -= remaining;
    -
    3959 auto p = m_head;
    -
    3960 m_head = p->next;
    -
    3961 delete p;
    -
    3962 }
    -
    3963 }
    -
    -
    3964
    -
    -
    3965 virtual _Success_(return != 0) size_t write(
    -
    3966 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
    -
    3967 {
    -
    3968 _Assume_(data || !length);
    -
    3969 try {
    -
    3970 std::unique_ptr<node_t> n(reinterpret_cast<node_t*>(new uint8_t[sizeof(node_t) + length]));
    -
    3971 n->next = nullptr;
    -
    3972 n->size = length;
    -
    3973 memcpy(n->data, data, length);
    -
    3974 m_size += length;
    -
    3975 if (m_head)
    -
    3976 m_tail = m_tail->next = n.release();
    -
    3977 else
    -
    3978 m_head = m_tail = n.release();
    -
    3979 m_state = state_t::ok;
    -
    3980 return length;
    -
    3981 }
    -
    3982 catch (const std::bad_alloc&) {
    -
    3983 m_state = state_t::fail;
    -
    3984 return 0;
    -
    3985 }
    -
    3986 }
    -
    -
    3987
    -
    -
    3988 virtual void close()
    -
    3989 {
    -
    3990 m_size = m_offset = 0;
    -
    3991 while (m_head) {
    -
    3992 auto p = m_head;
    -
    3993 m_head = p->next;
    -
    3994 delete p;
    -
    3995 }
    -
    3996 m_state = state_t::ok;
    -
    3997 }
    -
    -
    3998
    -
    4002 inline size_t size() const { return m_size; };
    -
    4003
    -
    4004 protected:
    -
    4005 size_t m_offset, m_size;
    -
    -
    4006 struct node_t {
    -
    4007 node_t* next;
    -
    4008 size_t size;
    -
    4009#pragma warning(suppress:4200)
    -
    4010 uint8_t data[0];
    -
    4011 } *m_head, * m_tail;
    -
    -
    4012 };
    -
    -
    4013
    -
    -
    4017 class diag_file : public basic_file {
    -
    4018 public:
    -
    4019 diag_file(_In_count_(num_files) basic_file* const* files, _In_ size_t num_files) :
    -
    4020 basic(num_files ? files[0]->state() : state_t::fail),
    -
    4021 m_files(files, files + num_files)
    -
    4022 {}
    -
    4023
    -
    -
    4024 virtual _Success_(return != 0 || length == 0) size_t read(
    -
    4025 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
    -
    4026 {
    -
    4027 _Assume_(data || !length);
    -
    4028 if (m_files.empty()) {
    -
    4029 m_state = state_t::fail;
    -
    4030 return 0;
    -
    4031 }
    -
    4032 size_t result = m_files[0]->read(data, length);
    -
    4033 _Assume_(result <= length);
    -
    4034 m_state = m_files[0]->state();
    -
    4035 if (length > m_tmp.size())
    -
    4036 m_tmp.resize(length);
    -
    4037 for (size_t i = 1, n = m_files.size(); i < n; ++i) {
    -
    4038 if (m_files[i]->read(m_tmp.data(), length) != result ||
    -
    4039 memcmp(m_tmp.data(), data, result))
    -
    4040 throw std::runtime_error("read mismatch");
    -
    4041 if (m_files[i]->state() != m_state)
    -
    4042 throw std::runtime_error("state mismatch");
    -
    4043 }
    -
    4044 return result;
    -
    4045 }
    -
    -
    4046
    -
    -
    4047 virtual _Success_(return != 0) size_t write(
    -
    4048 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
    -
    4049 {
    -
    4050 if (m_files.empty()) {
    -
    4051 m_state = state_t::fail;
    -
    4052 return 0;
    -
    4053 }
    -
    4054 size_t result = m_files[0]->write(data, length);
    -
    4055 m_state = m_files[0]->state();
    -
    4056 for (size_t i = 1, n = m_files.size(); i < n; ++i) {
    -
    4057 if (m_files[i]->write(data, length) != result)
    -
    4058 throw std::runtime_error("write mismatch");
    -
    4059 if (m_files[i]->state() != m_state)
    -
    4060 throw std::runtime_error("state mismatch");
    -
    4061 }
    -
    4062 return result;
    -
    4063 }
    -
    -
    4064
    -
    -
    4065 virtual void flush()
    -
    4066 {
    -
    4067 if (m_files.empty()) {
    -
    4068 m_state = state_t::ok;
    -
    4069 return;
    -
    4070 }
    -
    4071 m_files[0]->flush();
    -
    4072 m_state = m_files[0]->state();
    -
    4073 for (size_t i = 1, n = m_files.size(); i < n; ++i) {
    -
    4074 m_files[i]->flush();
    -
    4075 if (m_files[i]->state() != m_state)
    -
    4076 throw std::runtime_error("state mismatch");
    -
    4077 }
    -
    4078 }
    -
    -
    4079
    -
    -
    4080 virtual void close()
    -
    4081 {
    -
    4082 if (m_files.empty()) {
    -
    4083 m_state = state_t::ok;
    -
    4084 return;
    -
    4085 }
    -
    4086 m_files[0]->close();
    -
    4087 m_state = m_files[0]->state();
    -
    4088 for (size_t i = 1, n = m_files.size(); i < n; ++i) {
    -
    4089 m_files[i]->close();
    -
    4090 if (m_files[i]->state() != m_state)
    -
    4091 throw std::runtime_error("state mismatch");
    -
    4092 }
    -
    4093 m_tmp.clear();
    -
    4094 m_tmp.shrink_to_fit();
    -
    4095 }
    -
    -
    4096
    -
    -
    4097 virtual fpos_t seek(_In_ foff_t offset, _In_ seek_t how = seek_t::beg)
    -
    4098 {
    -
    4099 if (m_files.empty()) {
    -
    4100 m_state = state_t::fail;
    -
    4101 return fpos_max;
    -
    4102 }
    -
    4103 fpos_t result = m_files[0]->seek(offset, how);
    -
    4104 m_state = m_files[0]->state();
    -
    4105 for (size_t i = 1, n = m_files.size(); i < n; ++i) {
    -
    4106 if (m_files[i]->seek(offset, how) != result)
    -
    4107 throw std::runtime_error("seek mismatch");
    -
    4108 if (m_files[i]->state() != m_state)
    -
    4109 throw std::runtime_error("state mismatch");
    -
    4110 }
    -
    4111 return result;
    -
    4112 }
    -
    -
    4113
    -
    -
    4114 virtual fpos_t tell() const
    -
    4115 {
    -
    4116 if (m_files.empty())
    -
    4117 return fpos_max;
    -
    4118 fpos_t result = m_files[0]->tell();
    -
    4119 for (size_t i = 1, n = m_files.size(); i < n; ++i) {
    -
    4120 if (m_files[i]->tell() != result)
    -
    4121 throw std::runtime_error("tell mismatch");
    -
    4122 }
    -
    4123 return result;
    -
    4124 }
    -
    -
    4125
    -
    -
    4126 virtual void lock(_In_ fpos_t offset, _In_ fsize_t length)
    -
    4127 {
    -
    4128 if (m_files.empty())
    -
    4129 m_state = state_t::fail;
    -
    4130 m_files[0]->lock(offset, length);
    -
    4131 m_state = m_files[0]->state();
    -
    4132 for (size_t i = 1, n = m_files.size(); i < n; ++i) {
    -
    4133 m_files[i]->lock(offset, length);
    -
    4134 if (m_files[i]->state() != m_state)
    -
    4135 throw std::runtime_error("state mismatch");
    -
    4136 }
    -
    4137 }
    -
    -
    4138
    -
    -
    4139 virtual void unlock(_In_ fpos_t offset, _In_ fsize_t length)
    -
    4140 {
    -
    4141 if (m_files.empty())
    -
    4142 m_state = state_t::fail;
    -
    4143 m_files[0]->unlock(offset, length);
    -
    4144 m_state = m_files[0]->state();
    -
    4145 for (size_t i = 1, n = m_files.size(); i < n; ++i) {
    -
    4146 m_files[i]->unlock(offset, length);
    -
    4147 if (m_files[i]->state() != m_state)
    -
    4148 throw std::runtime_error("state mismatch");
    -
    4149 }
    -
    4150 }
    -
    -
    4151
    -
    -
    4152 virtual fsize_t size()
    -
    4153 {
    -
    4154 if (m_files.empty()) {
    -
    4155 m_state = state_t::fail;
    -
    4156 return 0;
    -
    4157 }
    -
    4158 fsize_t result = m_files[0]->size();
    -
    4159 m_state = m_files[0]->state();
    -
    4160 for (size_t i = 1, n = m_files.size(); i < n; ++i) {
    -
    4161 if (m_files[i]->size() != result)
    -
    4162 throw std::runtime_error("size mismatch");
    -
    4163 if (m_files[i]->state() != m_state)
    -
    4164 throw std::runtime_error("state mismatch");
    -
    4165 }
    -
    4166 return result;
    -
    4167 }
    -
    -
    4168
    -
    -
    4169 virtual void truncate()
    -
    4170 {
    -
    4171 if (m_files.empty())
    -
    4172 m_state = state_t::fail;
    -
    4173 m_files[0]->truncate();
    -
    4174 m_state = m_files[0]->state();
    -
    4175 for (size_t i = 1, n = m_files.size(); i < n; ++i) {
    -
    4176 m_files[i]->truncate();
    -
    4177 if (m_files[i]->state() != m_state)
    -
    4178 throw std::runtime_error("state mismatch");
    -
    4179 }
    -
    4180 }
    -
    -
    4181
    -
    4182 protected:
    -
    4183 std::vector<basic_file*> m_files;
    -
    4184 std::vector<uint8_t> m_tmp;
    -
    4185 };
    -
    -
    4186 }
    -
    4187}
    -
    Encoding converter context.
    Definition unicode.hpp:64
    -
    Provides read-ahead stream capability.
    Definition stream.hpp:1255
    -
    virtual size_t read(_Out_writes_bytes_to_opt_(length, return) void *data, size_t length)
    Reads block of data from the stream.
    Definition stream.hpp:1269
    -
    Provides write-back stream capability.
    Definition stream.hpp:1322
    -
    virtual void flush()
    Persists volatile element data.
    Definition stream.hpp:1359
    -
    virtual size_t write(_In_reads_bytes_opt_(length) const void *data, size_t length)
    Writes block of data to the stream.
    Definition stream.hpp:1335
    -
    Basic seekable stream operations.
    Definition stream.hpp:823
    -
    virtual void skip(fsize_t amount)
    Skips given amount of bytes of data on the stream.
    Definition stream.hpp:866
    -
    virtual time_point ctime() const
    Returns file creation time.
    Definition stream.hpp:913
    -
    virtual void lock(fpos_t offset, fsize_t length)
    Locks file section for exclusive access.
    Definition stream.hpp:882
    +
    25#include <sys/socket.h>
    +
    26#include <sys/stat.h>
    +
    27#endif
    +
    28#include <chrono>
    +
    29#include <condition_variable>
    +
    30#include <list>
    +
    31#include <memory>
    +
    32#include <set>
    +
    33#include <string>
    +
    34#include <thread>
    +
    35#include <vector>
    +
    36
    +
    37#if !defined(SET_FILE_OP_TIMES) && defined(RDAT_BELEZI_CAS_DOSTOPA_VER)
    +
    38#define SET_FILE_OP_TIMES 1
    +
    39#pragma message("RDAT_BELEZI_CAS_DOSTOPA_VER is deprecated. Use SET_FILE_OP_TIMES instead.")
    +
    40#elif !defined(SET_FILE_OP_TIMES)
    +
    41#define SET_FILE_OP_TIMES 0
    +
    42#endif
    +
    43#if !defined(CHECK_STREAM_STATE) && defined(RDAT_NE_PREVERJAJ_STANJA_VER)
    +
    44#define CHECK_STREAM_STATE 0
    +
    45#pragma message("RDAT_NE_PREVERJAJ_EOF_VER is deprecated. Use CHECK_STREAM_STATE=0 instead.")
    +
    46#else
    +
    47#define CHECK_STREAM_STATE 1
    +
    48#endif
    +
    49
    +
    50namespace stdex
    +
    51{
    +
    52 namespace stream
    +
    53 {
    +
    57 enum class state_t {
    +
    58 ok = 0,
    +
    59 eof,
    +
    60 fail,
    +
    61 };
    +
    62
    +
    66 using fsize_t = uint64_t;
    +
    67 constexpr fsize_t fsize_max = UINT64_MAX;
    +
    68
    +
    69 constexpr size_t iterate_count = 0x10;
    +
    70 constexpr size_t default_block_size = 0x10000;
    +
    71 constexpr char16_t utf16_bom = u'\ufeff';
    +
    72 constexpr char32_t utf32_bom = U'\ufeff';
    +
    73 constexpr const char utf8_bom[3] = { '\xef', '\xbb', '\xbf' };
    +
    74
    +
    +
    78 class basic
    +
    79 {
    +
    80 public:
    +
    81 basic(_In_ state_t state = state_t::ok) : m_state(state) {}
    +
    82
    +
    83 virtual ~basic() noexcept(false) {}
    +
    84
    +
    +
    96 virtual _Success_(return != 0 || length == 0) size_t read(
    +
    97 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
    +
    98 {
    +
    99 _Unreferenced_(data);
    +
    100 _Unreferenced_(length);
    +
    101 m_state = state_t::fail;
    +
    102 return 0;
    +
    103 }
    +
    +
    104
    +
    +
    114 virtual _Success_(return != 0) size_t write(
    +
    115 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
    +
    116 {
    +
    117 _Unreferenced_(data);
    +
    118 _Unreferenced_(length);
    +
    119 m_state = state_t::fail;
    +
    120 return 0;
    +
    121 }
    +
    +
    122
    +
    +
    126 virtual void flush()
    +
    127 {
    +
    128 m_state = state_t::ok;
    +
    129 }
    +
    +
    130
    +
    +
    134 virtual void close()
    +
    135 {
    +
    136 m_state = state_t::ok;
    +
    137 }
    +
    +
    138
    +
    +
    142 virtual void skip(_In_ fsize_t amount)
    +
    143 {
    +
    144 if (amount == 1)
    +
    145 read_byte();
    +
    146 else if (amount < iterate_count) {
    +
    147 for (size_t i = 0; i < static_cast<size_t>(amount); i++) {
    +
    148 read_byte();
    +
    149 if (!ok()) _Unlikely_
    +
    150 break;
    +
    151 }
    +
    152 }
    +
    153 else {
    +
    154 size_t block = static_cast<size_t>(std::min<fsize_t>(amount, default_block_size));
    +
    155 try {
    +
    156 std::unique_ptr<uint8_t[]> dummy(new uint8_t[block]);
    +
    157 while (amount) {
    +
    158 amount -= read_array(dummy.get(), sizeof(uint8_t), static_cast<size_t>(std::min<fsize_t>(amount, block)));
    +
    159 if (!ok()) _Unlikely_
    +
    160 break;
    +
    161 }
    +
    162 }
    +
    163 catch (const std::bad_alloc&) { m_state = state_t::fail; }
    +
    164 }
    +
    165 }
    +
    +
    166
    +
    170 inline state_t state() const { return m_state; };
    +
    171
    +
    175 inline bool ok() const { return m_state == state_t::ok; };
    +
    176
    +
    +
    184 virtual std::vector<uint8_t> read_remainder(_In_ size_t max_length = SIZE_MAX)
    +
    185 {
    +
    186 std::vector<uint8_t> result;
    +
    187 size_t offset, length;
    +
    188 offset = 0;
    +
    189 length = default_block_size;
    +
    190 while (offset < max_length) {
    +
    191 length = std::min(length, max_length);
    +
    192 try { result.resize(length); }
    +
    193 catch (const std::bad_alloc&) {
    +
    194 m_state = state_t::fail;
    +
    195 return result;
    +
    196 }
    +
    197 auto num_read = read_array(result.data() + offset, sizeof(uint8_t), length - offset);
    +
    198 offset += num_read;
    +
    199 if (!ok()) _Unlikely_
    +
    200 break;
    +
    201 length += default_block_size;
    +
    202 }
    +
    203 result.resize(offset);
    +
    204 return result;
    +
    205 }
    +
    +
    206
    +
    +
    210 inline uint8_t read_byte()
    +
    211 {
    +
    212 uint8_t byte;
    +
    213 if (read_array(&byte, sizeof(byte), 1) == 1)
    +
    214 return byte;
    +
    215 throw std::system_error(sys_error(), std::system_category(), "failed to read");
    +
    216 }
    +
    +
    217
    +
    +
    221 void write_byte(_In_ uint8_t byte, _In_ fsize_t amount = 1)
    +
    222 {
    +
    223 if (amount == 1)
    +
    224 write(&byte, sizeof(uint8_t));
    +
    225 else if (amount < iterate_count) {
    +
    226 for (size_t i = 0; i < static_cast<size_t>(amount); i++) {
    +
    227 write(&byte, sizeof(uint8_t));
    +
    228 if (!ok()) _Unlikely_
    +
    229 break;
    +
    230 }
    +
    231 }
    +
    232 else {
    +
    233 size_t block = static_cast<size_t>(std::min<fsize_t>(amount, default_block_size));
    +
    234 try {
    +
    235 std::unique_ptr<uint8_t[]> dummy(new uint8_t[block]);
    +
    236 memset(dummy.get(), byte, block);
    +
    237 while (amount) {
    +
    238 amount -= write_array(dummy.get(), sizeof(uint8_t), static_cast<size_t>(std::min<fsize_t>(amount, block)));
    +
    239 if (!ok()) _Unlikely_
    +
    240 break;
    +
    241 }
    +
    242 }
    +
    243 catch (const std::bad_alloc&) { m_state = state_t::fail; }
    +
    244 }
    +
    245 }
    +
    +
    246
    +
    258 template <class T>
    +
    +
    259 inline basic& read_data(_Out_ T& data)
    +
    260 {
    +
    261 if (!ok()) _Unlikely_ {
    +
    262 data = 0;
    +
    263 return *this;
    +
    264 }
    +
    265 if (read_array(&data, sizeof(T), 1) == 1)
    +
    266 (void)LE2HE(&data);
    +
    267 else {
    +
    268 data = 0;
    +
    269 if (ok())
    +
    270 m_state = state_t::eof;
    +
    271 }
    +
    272 return *this;
    +
    273 }
    +
    +
    274
    +
    286 template <class T>
    +
    +
    287 inline basic& write_data(_In_ const T data)
    +
    288 {
    +
    289 if (!ok()) _Unlikely_
    +
    290 return *this;
    +
    291#if BYTE_ORDER == BIG_ENDIAN
    +
    292 T data_le = HE2LE(data);
    +
    293 write(&data_le, sizeof(T));
    +
    294#else
    +
    295 write(&data, sizeof(T));
    +
    296#endif
    +
    297 return *this;
    +
    298 }
    +
    +
    299
    +
    305 template<class _Traits = std::char_traits<char>, class _Ax = std::allocator<char>>
    +
    +
    306 inline size_t readln(_Inout_ std::basic_string<char, _Traits, _Ax>& str)
    +
    307 {
    +
    308 str.clear();
    +
    309 return readln_and_attach(str);
    +
    310 }
    +
    +
    311
    +
    317 template<class _Traits = std::char_traits<wchar_t>, class _Ax = std::allocator<wchar_t>>
    +
    +
    318 inline size_t readln(_Inout_ std::basic_string<wchar_t, _Traits, _Ax>& wstr)
    +
    319 {
    +
    320 wstr.clear();
    +
    321 return readln_and_attach(wstr);
    +
    322 }
    +
    +
    323
    +
    329 template<class T_from, class T_to, class _Traits = std::char_traits<T_to>, class _Ax = std::allocator<T_to>>
    +
    +
    330 size_t readln(_Inout_ std::basic_string<T_to, _Traits, _Ax>& wstr, _In_ charset_encoder<T_from, T_to>& encoder)
    +
    331 {
    +
    332 if (encoder.from_encoding() == encoder.to_encoding())
    +
    333 return readln(wstr);
    +
    334 std::string str;
    + +
    336 encoder.strcpy(wstr, str);
    +
    337 return wstr.size();
    +
    338 }
    +
    +
    339
    +
    345 template<class _Elem, class _Traits = std::char_traits<_Elem>, class _Ax = std::allocator<_Elem>>
    +
    +
    346 size_t readln_and_attach(_Inout_ std::basic_string<_Elem, _Traits, _Ax>& str)
    +
    347 {
    +
    348 bool initial = true;
    +
    349 _Elem chr, previous = (_Elem)0;
    +
    350 do {
    +
    351 read_array(&chr, sizeof(_Elem), 1);
    +
    352 if (!initial && !(previous == static_cast<_Elem>('\r') && chr == static_cast<_Elem>('\n')))
    +
    353 str += previous;
    +
    354 else
    +
    355 initial = false;
    +
    356 previous = chr;
    +
    357 } while (ok() && chr != static_cast<_Elem>('\n'));
    +
    358 return str.size();
    +
    359 }
    +
    +
    360
    +
    366 template<class T_from, class T_to, class _Traits = std::char_traits<T_to>, class _Ax = std::allocator<T_to>>
    +
    +
    367 size_t readln_and_attach(_Inout_ std::basic_string<T_to, _Traits, _Ax>& wstr, _In_ charset_encoder<T_from, T_to>& encoder)
    +
    368 {
    +
    369 if (encoder.from_encoding() == encoder.to_encoding())
    +
    370 return readln_and_attach(wstr);
    +
    371 std::string str;
    + +
    373 encoder.strcat(wstr, str);
    +
    374 return wstr.size();
    +
    375 }
    +
    +
    376
    +
    +
    382 size_t read_array(_Out_writes_bytes_(size* count) void* array, _In_ size_t size, _In_ size_t count)
    +
    383 {
    +
    384 for (size_t to_read = mul(size, count);;) {
    +
    385 size_t num_read = read(array, to_read);
    +
    386 to_read -= num_read;
    +
    387 if (!to_read)
    +
    388 return count;
    +
    389 if (!ok()) _Unlikely_
    +
    390 return count - to_read / size;
    +
    391 reinterpret_cast<uint8_t*&>(array) += num_read;
    +
    392 }
    +
    393 }
    +
    +
    394
    +
    +
    400 inline size_t write_array(_In_reads_bytes_opt_(size* count) const void* array, _In_ size_t size, _In_ size_t count)
    +
    401 {
    +
    402 return write(array, mul(size, count)) / size;
    +
    403 }
    +
    +
    404
    +
    413 template <class T_from, class T_to>
    +
    +
    414 size_t write_array(_In_z_ const T_from* wstr, _In_ charset_encoder<T_from, T_to>& encoder)
    +
    415 {
    +
    416 if (!ok()) _Unlikely_
    +
    417 return 0;
    +
    418 size_t num_chars = stdex::strlen(wstr);
    +
    419 if (encoder.from_encoding() == encoder.to_encoding())
    +
    420 return write_array(wstr, sizeof(T_from), num_chars);
    +
    421 std::basic_string<T_to> str(encoder.convert(wstr, num_chars));
    +
    422 return write_array(str.data(), sizeof(T_to), str.size());
    +
    423 }
    +
    +
    424
    +
    434 template <class T_from, class T_to>
    +
    +
    435 size_t write_array(_In_reads_or_z_opt_(num_chars) const T_from* wstr, _In_ size_t num_chars, _In_ charset_encoder<T_from, T_to>& encoder)
    +
    436 {
    +
    437 if (!ok()) _Unlikely_
    +
    438 return 0;
    +
    439 num_chars = stdex::strnlen(wstr, num_chars);
    +
    440 if (encoder.from_encoding() == encoder.to_encoding())
    +
    441 return write_array(wstr, sizeof(T_from), num_chars);
    +
    442 std::basic_string<T_to> str(encoder.convert(wstr, num_chars));
    +
    443 return write_array(str.data(), sizeof(T_to), str.size());
    +
    444 }
    +
    +
    445
    +
    454 template<class T_from, class T_to, class _Traits = std::char_traits<T_from>, class _Ax = std::allocator<T_from>>
    +
    +
    455 size_t write_array(_In_ const std::basic_string<T_from, _Traits, _Ax>& wstr, _In_ charset_encoder<T_from, T_to>& encoder)
    +
    456 {
    +
    457 if (!ok()) _Unlikely_
    +
    458 return 0;
    +
    459 if (encoder.from_encoding() == encoder.to_encoding())
    +
    460 return write_array(wstr.data(), sizeof(T_from), wstr.size());
    +
    461 std::basic_string<T_to> str(encoder.convert(wstr));
    +
    462 return write_array(str.data(), sizeof(T_to), str.size());
    +
    463 }
    +
    +
    464
    +
    476 template<class _Elem, class _Traits = std::char_traits<_Elem>, class _Ax = std::allocator<_Elem>>
    +
    +
    477 inline basic& read_str(_Out_ std::basic_string<_Elem, _Traits, _Ax>& data)
    +
    478 {
    +
    479 data.clear();
    +
    480 if (!ok()) _Unlikely_
    +
    481 return *this;
    +
    482 uint32_t num_chars;
    +
    483 read_data(num_chars);
    +
    484 if (!ok()) _Unlikely_
    +
    485 return *this;
    +
    486 data.reserve(num_chars);
    +
    487 for (;;) {
    +
    488 _Elem buf[0x400];
    +
    489 uint32_t num_read = static_cast<uint32_t>(read_array(buf, sizeof(_Elem), std::min<uint32_t>(num_chars, _countof(buf))));
    +
    490 data.append(buf, buf + num_read);
    +
    491 num_chars -= num_read;
    +
    492 if (!num_chars || !ok())
    +
    493 return *this;
    +
    494 }
    +
    495 }
    +
    +
    496
    +
    508 template <class T>
    +
    +
    509 inline basic& write_str(_In_z_ const T* data)
    +
    510 {
    +
    511 // Stream state will be checked in write_data.
    +
    512 size_t num_chars = stdex::strlen(data);
    +
    513 if (num_chars > UINT32_MAX)
    +
    514 throw std::invalid_argument("string too long");
    +
    515 write_data(static_cast<uint32_t>(num_chars));
    +
    516 if (!ok()) _Unlikely_
    +
    517 return *this;
    +
    518 write_array(data, sizeof(T), num_chars);
    +
    519 return *this;
    +
    520 }
    +
    +
    521
    +
    533 template<class _Elem, class _Traits = std::char_traits<_Elem>, class _Ax = std::allocator<_Elem>>
    +
    +
    534 inline basic& write_str(_In_ const std::basic_string<_Elem, _Traits, _Ax>& data)
    +
    535 {
    +
    536 // Stream state will be checked in write_data.
    +
    537 size_t num_chars = data.size();
    +
    538 if (num_chars > UINT32_MAX)
    +
    539 throw std::invalid_argument("string too long");
    +
    540 write_data(static_cast<uint32_t>(num_chars));
    +
    541 if (!ok()) _Unlikely_
    +
    542 return *this;
    +
    543 write_array(data.data(), sizeof(_Elem), num_chars);
    +
    544 return *this;
    +
    545 }
    +
    +
    546
    +
    547#ifdef _WIN32
    +
    553 size_t write_sa(_In_ LPSAFEARRAY sa)
    +
    554 {
    +
    555 safearray_accessor<void> a(sa);
    +
    556 long ubound, lbound;
    +
    557 if (FAILED(SafeArrayGetUBound(sa, 1, &ubound)) ||
    +
    558 FAILED(SafeArrayGetLBound(sa, 1, &lbound)))
    +
    559 throw std::invalid_argument("SafeArrayGet[UL]Bound failed");
    +
    560 return write(a.data(), static_cast<size_t>(ubound) - lbound + 1);
    +
    561 }
    +
    562#endif
    +
    563
    +
    +
    569 fsize_t write_stream(_Inout_ basic& stream, _In_ fsize_t amount = fsize_max)
    +
    570 {
    +
    571 std::unique_ptr<uint8_t[]> data(new uint8_t[static_cast<size_t>(std::min<fsize_t>(amount, default_block_size))]);
    +
    572 fsize_t num_copied = 0, to_write = amount;
    +
    573 m_state = state_t::ok;
    +
    574 while (to_write) {
    +
    575 size_t num_read = stream.read(data.get(), static_cast<size_t>(std::min<fsize_t>(default_block_size, to_write)));
    +
    576 size_t num_written = write(data.get(), num_read);
    +
    577 num_copied += num_written;
    +
    578 to_write -= num_written;
    +
    579 if (stream.m_state == state_t::eof) {
    +
    580 // EOF is not an error.
    +
    581 m_state = state_t::ok;
    +
    582 break;
    +
    583 }
    +
    584 m_state = stream.m_state;
    +
    585 if (!ok())
    +
    586 break;
    +
    587 }
    +
    588 return num_copied;
    +
    589 }
    +
    +
    590
    +
    +
    594 void write_charset(_In_ charset_id charset)
    +
    595 {
    +
    596 if (charset == charset_id::utf32)
    +
    597 write_data(utf32_bom);
    +
    598 else if (charset == charset_id::utf16)
    +
    599 write_data(utf16_bom);
    +
    600 else if (charset == charset_id::utf8)
    +
    601 write_array(utf8_bom, sizeof(utf8_bom), 1);
    +
    602 }
    +
    +
    603
    +
    +
    609 size_t write_sprintf(_In_z_ _Printf_format_string_params_(2) const char* format, _In_opt_ locale_t locale, ...)
    +
    610 {
    +
    611 va_list params;
    +
    612 va_start(params, locale);
    +
    613 size_t num_chars = write_vsprintf(format, locale, params);
    +
    614 va_end(params);
    +
    615 return num_chars;
    +
    616 }
    +
    +
    617
    +
    +
    623 size_t write_sprintf(_In_z_ _Printf_format_string_params_(2) const wchar_t* format, _In_opt_ locale_t locale, ...)
    +
    624 {
    +
    625 va_list params;
    +
    626 va_start(params, locale);
    +
    627 size_t num_chars = write_vsprintf(format, locale, params);
    +
    628 va_end(params);
    +
    629 return num_chars;
    +
    630 }
    +
    +
    631
    +
    +
    637 size_t write_vsprintf(_In_z_ _Printf_format_string_params_(2) const char* format, _In_opt_ locale_t locale, _In_ va_list params)
    +
    638 {
    +
    639 std::string str;
    +
    640 str.reserve(default_block_size);
    +
    641 vappendf(str, format, locale, params);
    +
    642 return write_array(str.data(), sizeof(char), str.size());
    +
    643 }
    +
    +
    644
    +
    +
    650 size_t write_vsprintf(_In_z_ _Printf_format_string_params_(2) const wchar_t* format, _In_opt_ locale_t locale, _In_ va_list params)
    +
    651 {
    +
    652 std::wstring str;
    +
    653 str.reserve(default_block_size);
    +
    654 vappendf(str, format, locale, params);
    +
    655 return write_array(str.data(), sizeof(wchar_t), str.size());
    +
    656 }
    +
    +
    657
    +
    658 inline basic& operator >>(_Out_ int8_t& data) { return read_data(data); }
    +
    659 inline basic& operator <<(_In_ const int8_t data) { return write_data(data); }
    +
    660 inline basic& operator >>(_Out_ int16_t& data) { return read_data(data); }
    +
    661 inline basic& operator <<(_In_ const int16_t data) { return write_data(data); }
    +
    662 inline basic& operator >>(_Out_ int32_t& data) { return read_data(data); }
    +
    663 inline basic& operator <<(_In_ const int32_t data) { return write_data(data); }
    +
    664 inline basic& operator >>(_Out_ int64_t& data) { return read_data(data); }
    +
    665 inline basic& operator <<(_In_ const int64_t data) { return write_data(data); }
    +
    666 inline basic& operator >>(_Out_ uint8_t& data) { return read_data(data); }
    +
    667 inline basic& operator <<(_In_ const uint8_t data) { return write_data(data); }
    +
    668 inline basic& operator >>(_Out_ uint16_t& data) { return read_data(data); }
    +
    669 inline basic& operator <<(_In_ const uint16_t data) { return write_data(data); }
    +
    670 inline basic& operator >>(_Out_ uint32_t& data) { return read_data(data); }
    +
    671 inline basic& operator <<(_In_ const uint32_t data) { return write_data(data); }
    +
    672 inline basic& operator >>(_Out_ uint64_t& data) { return read_data(data); }
    +
    673 inline basic& operator <<(_In_ const uint64_t data) { return write_data(data); }
    +
    674 inline basic& operator >>(_Out_ float& data) { return read_data(data); }
    +
    675 inline basic& operator <<(_In_ const float data) { return write_data(data); }
    +
    676 inline basic& operator >>(_Out_ double& data) { return read_data(data); }
    +
    677 inline basic& operator <<(_In_ const double data) { return write_data(data); }
    +
    678 inline basic& operator >>(_Out_ char& data) { return read_data(data); }
    +
    679 inline basic& operator <<(_In_ const char data) { return write_data(data); }
    +
    680#ifdef _NATIVE_WCHAR_T_DEFINED
    +
    681 inline basic& operator >>(_Out_ wchar_t& data) { return read_data(data); }
    +
    682 inline basic& operator <<(_In_ const wchar_t data) { return write_data(data); }
    +
    683#endif
    +
    684 template<class _Elem, class _Traits = std::char_traits<_Elem>, class _Ax = std::allocator<_Elem>>
    +
    685 inline basic& operator >>(_Out_ std::basic_string<_Elem, _Traits, _Ax>& data) { return read_str(data); }
    +
    686 template <class T>
    +
    687 inline basic& operator <<(_In_ const T* data) { return write_str(data); }
    +
    688 template<class _Elem, class _Traits = std::char_traits<_Elem>, class _Ax = std::allocator<_Elem>>
    +
    689 inline basic& operator <<(_In_ const std::basic_string<_Elem, _Traits, _Ax>& data) { return write_str(data); }
    +
    690
    +
    691 template <class _Ty, class _Alloc = std::allocator<_Ty>>
    +
    692 basic& operator <<(_In_ const std::vector<_Ty, _Alloc>& data)
    +
    693 {
    +
    694 size_t num = data.size();
    +
    695 if (num > UINT32_MAX) _Unlikely_
    +
    696 throw std::invalid_argument("collection too big");
    +
    697 *this << static_cast<uint32_t>(num);
    +
    698 for (auto& el : data)
    +
    699 *this << el;
    +
    700 return *this;
    +
    701 }
    +
    702
    +
    703 template <class _Ty, class _Alloc = std::allocator<_Ty>>
    +
    704 basic& operator >>(_Out_ std::vector<_Ty, _Alloc>& data)
    +
    705 {
    +
    706 data.clear();
    +
    707 uint32_t num;
    +
    708 *this >> num;
    +
    709 if (!ok()) _Unlikely_
    +
    710 return *this;
    +
    711 data.reserve(num);
    +
    712 for (uint32_t i = 0; i < num; ++i) {
    +
    713 _Ty el;
    +
    714 *this >> el;
    +
    715 if (!ok()) _Unlikely_
    +
    716 return *this;
    +
    717 data.push_back(std::move(el));
    +
    718 }
    +
    719 }
    +
    720
    +
    721 template <class _Kty, class _Pr = std::less<_Kty>, class _Alloc = std::allocator<_Kty>>
    +
    722 basic& operator <<(_In_ const std::set<_Kty, _Pr, _Alloc>& data)
    +
    723 {
    +
    724 size_t num = data.size();
    +
    725 if (num > UINT32_MAX) _Unlikely_
    +
    726 throw std::invalid_argument("collection too big");
    +
    727 *this << static_cast<uint32_t>(num);
    +
    728 for (auto& el : data)
    +
    729 *this << el;
    +
    730 return *this;
    +
    731 }
    +
    732
    +
    733 template <class _Kty, class _Pr = std::less<_Kty>, class _Alloc = std::allocator<_Kty>>
    +
    734 basic& operator >>(_Out_ std::set<_Kty, _Pr, _Alloc>& data)
    +
    735 {
    +
    736 data.clear();
    +
    737 uint32_t num;
    +
    738 *this >> num;
    +
    739 if (!ok()) _Unlikely_
    +
    740 return *this;
    +
    741 for (uint32_t i = 0; i < num; ++i) {
    +
    742 _Kty el;
    +
    743 *this >> el;
    +
    744 if (!ok()) _Unlikely_
    +
    745 return *this;
    +
    746 data.insert(std::move(el));
    +
    747 }
    +
    748 }
    +
    749
    +
    750 template <class _Kty, class _Pr = std::less<_Kty>, class _Alloc = std::allocator<_Kty>>
    +
    751 basic& operator <<(_In_ const std::multiset<_Kty, _Pr, _Alloc>& data)
    +
    752 {
    +
    753 size_t num = data.size();
    +
    754 if (num > UINT32_MAX) _Unlikely_
    +
    755 throw std::invalid_argument("collection too big");
    +
    756 *this << static_cast<uint32_t>(num);
    +
    757 for (auto& el : data)
    +
    758 *this << el;
    +
    759 return *this;
    +
    760 }
    +
    761
    +
    762 template <class _Kty, class _Pr = std::less<_Kty>, class _Alloc = std::allocator<_Kty>>
    +
    763 basic& operator >>(_Out_ std::multiset<_Kty, _Pr, _Alloc>& data)
    +
    764 {
    +
    765 data.clear();
    +
    766 uint32_t num;
    +
    767 *this >> num;
    +
    768 if (!ok()) _Unlikely_
    +
    769 return *this;
    +
    770 for (uint32_t i = 0; i < num; ++i) {
    +
    771 _Kty el;
    +
    772 *this >> el;
    +
    773 if (!ok()) _Unlikely_
    +
    774 return *this;
    +
    775 data.insert(std::move(el));
    +
    776 }
    +
    777 return *this;
    +
    778 }
    +
    779
    +
    780 protected:
    +
    781 state_t m_state;
    +
    782 };
    +
    +
    783
    +
    787 using fpos_t = uint64_t;
    +
    788 constexpr fpos_t fpos_max = UINT64_MAX;
    +
    789 constexpr fpos_t fpos_min = 0;
    +
    790
    +
    794 using foff_t = int64_t;
    +
    795 constexpr foff_t foff_max = INT64_MAX;
    +
    796 constexpr foff_t foff_min = INT64_MIN;
    +
    797
    +
    801 enum class seek_t {
    +
    802#ifdef _WIN32
    +
    803 beg = FILE_BEGIN,
    +
    804 cur = FILE_CURRENT,
    +
    805 end = FILE_END
    +
    806#else
    +
    807 beg = SEEK_SET,
    +
    808 cur = SEEK_CUR,
    +
    809 end = SEEK_END
    +
    810#endif
    +
    811 };
    +
    812
    +
    813#if _HAS_CXX20
    +
    814 using clock = std::chrono::file_clock;
    +
    815#else
    +
    816 using clock = std::chrono::system_clock;
    +
    817#endif
    +
    818 using time_point = std::chrono::time_point<clock>;
    +
    819
    +
    +
    823 class basic_file : virtual public basic
    +
    824 {
    +
    825 public:
    +
    +
    826 virtual std::vector<uint8_t> read_remainder(_In_ size_t max_length = SIZE_MAX)
    +
    827 {
    +
    828 size_t length = std::min<size_t>(max_length, static_cast<size_t>(size() - tell()));
    +
    829 std::vector<uint8_t> result;
    +
    830 try { result.resize(length); }
    +
    831 catch (const std::bad_alloc&) {
    +
    832 m_state = state_t::fail;
    +
    833 return result;
    +
    834 }
    +
    835 result.resize(read_array(result.data(), sizeof(uint8_t), length));
    +
    836 return result;
    +
    837 }
    +
    +
    838
    +
    844 virtual fpos_t seek(_In_ foff_t offset, _In_ seek_t how = seek_t::beg) = 0;
    +
    845
    +
    851 inline fpos_t seekbeg(_In_ fpos_t offset) { return seek(offset, seek_t::beg); }
    +
    852
    +
    858 inline fpos_t seekcur(_In_ foff_t offset) { return seek(offset, seek_t::cur); }
    +
    859
    +
    865 inline fpos_t seekend(_In_ foff_t offset) { return seek(offset, seek_t::end); }
    +
    866
    +
    +
    867 virtual void skip(_In_ fsize_t amount)
    +
    868 {
    +
    869 seek(amount, seek_t::cur);
    +
    870 }
    +
    +
    871
    +
    878 virtual fpos_t tell() const = 0;
    +
    879
    +
    +
    883 virtual void lock(_In_ fpos_t offset, _In_ fsize_t length)
    +
    884 {
    +
    885 _Unreferenced_(offset);
    +
    886 _Unreferenced_(length);
    +
    887 throw std::domain_error("not implemented");
    +
    888 }
    +
    +
    889
    +
    +
    893 virtual void unlock(_In_ fpos_t offset, _In_ fsize_t length)
    +
    894 {
    +
    895 _Unreferenced_(offset);
    +
    896 _Unreferenced_(length);
    +
    897 throw std::domain_error("not implemented");
    +
    898 }
    +
    +
    899
    +
    904 virtual fsize_t size() = 0;
    +
    905
    +
    909 virtual void truncate() = 0;
    +
    910
    +
    +
    914 virtual time_point ctime() const
    +
    915 {
    +
    916 return time_point::min();
    +
    917 }
    +
    +
    918
    +
    +
    922 virtual time_point atime() const
    +
    923 {
    +
    924 return time_point::min();
    +
    925 }
    +
    +
    926
    +
    +
    930 virtual time_point mtime() const
    +
    931 {
    +
    932 return time_point::min();
    +
    933 }
    +
    +
    934
    +
    +
    938 virtual void set_ctime(time_point date)
    +
    939 {
    +
    940 _Unreferenced_(date);
    +
    941 throw std::domain_error("not implemented");
    +
    942 }
    +
    +
    943
    +
    +
    947 virtual void set_atime(time_point date)
    +
    948 {
    +
    949 _Unreferenced_(date);
    +
    950 throw std::domain_error("not implemented");
    +
    951 }
    +
    +
    952
    +
    +
    956 virtual void set_mtime(time_point date)
    +
    957 {
    +
    958 _Unreferenced_(date);
    +
    959 throw std::domain_error("not implemented");
    +
    960 }
    +
    +
    961
    +
    962#ifdef _WIN32
    +
    966 LPSAFEARRAY read_sa()
    +
    967 {
    +
    968 _Assume_(size() <= SIZE_MAX);
    +
    969 size_t length = static_cast<size_t>(size());
    +
    970 std::unique_ptr<SAFEARRAY, SafeArrayDestroy_delete> sa(SafeArrayCreateVector(VT_UI1, 0, (ULONG)length));
    +
    971 if (!sa) _Unlikely_
    +
    972 throw std::runtime_error("SafeArrayCreateVector failed");
    +
    973 safearray_accessor<void> a(sa.get());
    +
    974 if (seek(0) != 0) _Unlikely_
    +
    975 throw std::system_error(sys_error(), std::system_category(), "failed to seek");
    +
    976 if (read_array(a.data(), 1, length) != length)
    +
    977 throw std::system_error(sys_error(), std::system_category(), "failed to read");
    +
    978 return sa.release();
    +
    979 }
    +
    980#endif
    +
    981
    +
    +
    987 charset_id read_charset(_In_ charset_id default_charset = charset_id::system)
    +
    988 {
    +
    989 if (seek(0) != 0) _Unlikely_
    +
    990 throw std::system_error(sys_error(), std::system_category(), "failed to seek");
    +
    991 char32_t id_utf32;
    +
    992 read_array(&id_utf32, sizeof(char32_t), 1);
    +
    993 if (ok() && id_utf32 == utf32_bom)
    +
    994 return charset_id::utf32;
    +
    995
    +
    996 if (seek(0) != 0) _Unlikely_
    +
    997 throw std::system_error(sys_error(), std::system_category(), "failed to seek");
    +
    998 char16_t id_utf16;
    +
    999 read_array(&id_utf16, sizeof(char16_t), 1);
    +
    1000 if (ok() && id_utf16 == utf16_bom)
    +
    1001 return charset_id::utf16;
    +
    1002
    +
    1003 if (seek(0) != 0) _Unlikely_
    +
    1004 throw std::system_error(sys_error(), std::system_category(), "failed to seek");
    +
    1005 char id_utf8[3] = { 0 };
    +
    1006 read_array(id_utf8, sizeof(id_utf8), 1);
    +
    1007 if (ok() && strncmp(id_utf8, _countof(id_utf8), utf8_bom, _countof(utf8_bom)) == 0)
    +
    1008 return charset_id::utf8;
    +
    1009
    +
    1010 if (seek(0) != 0) _Unlikely_
    +
    1011 throw std::system_error(sys_error(), std::system_category(), "failed to seek");
    +
    1012 return default_charset;
    +
    1013 }
    +
    +
    1014 };
    +
    +
    1015
    +
    +
    1021 class converter : public basic
    +
    1022 {
    +
    1023 protected:
    +
    1025#pragma warning(suppress: 26495) // The delayed init call will finish initializing the class.
    +
    1026 explicit converter() : basic(state_t::fail) {}
    +
    1027
    +
    1028 void init(_Inout_ basic& source)
    +
    1029 {
    +
    1030 m_source = &source;
    +
    1031 init();
    +
    1032 }
    +
    1033
    +
    1034 void init()
    +
    1035 {
    +
    1036 m_state = m_source->state();
    +
    1037 }
    +
    1038
    +
    1039 void done()
    +
    1040 {
    +
    1041 m_source = nullptr;
    +
    1042 }
    +
    1044
    +
    1045 public:
    +
    1046 converter(_Inout_ basic& source) :
    +
    1047 basic(source.state()),
    +
    1048 m_source(&source)
    +
    1049 {}
    +
    1050
    +
    +
    1051 virtual _Success_(return != 0 || length == 0) size_t read(
    +
    1052 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
    +
    1053 {
    +
    1054 size_t num_read = m_source->read(data, length);
    +
    1055 m_state = m_source->state();
    +
    1056 return num_read;
    +
    1057 }
    +
    +
    1058
    +
    +
    1059 virtual _Success_(return != 0) size_t write(
    +
    1060 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
    +
    1061 {
    +
    1062 size_t num_written = m_source->write(data, length);
    +
    1063 m_state = m_source->state();
    +
    1064 return num_written;
    +
    1065 }
    +
    +
    1066
    +
    +
    1067 virtual void close()
    +
    1068 {
    +
    1069 m_source->close();
    +
    1070 m_state = m_source->state();
    +
    1071 }
    +
    +
    1072
    +
    +
    1073 virtual void flush()
    +
    1074 {
    +
    1075 m_source->flush();
    +
    1076 m_state = m_source->state();
    +
    1077 }
    +
    +
    1078
    +
    1079 protected:
    +
    1080 basic* m_source;
    +
    1081 };
    +
    +
    1082
    +
    +
    1086 class replicator : public basic
    +
    1087 {
    +
    1088 public:
    +
    1089 virtual ~replicator()
    +
    1090 {
    +
    1091 for (auto w = m_workers.begin(), w_end = m_workers.end(); w != w_end; ++w) {
    +
    1092 auto _w = w->get();
    +
    1093 {
    +
    1094 const std::lock_guard<std::mutex> lk(_w->mutex);
    +
    1095 _w->op = worker::op_t::quit;
    +
    1096 }
    +
    1097 _w->cv.notify_one();
    +
    1098 }
    +
    1099 for (auto w = m_workers.begin(), w_end = m_workers.end(); w != w_end; ++w)
    +
    1100 w->get()->join();
    +
    1101 }
    +
    1102
    +
    +
    1106 void push_back(_In_ basic* source)
    +
    1107 {
    +
    1108 m_workers.push_back(std::unique_ptr<worker>(new worker(source)));
    +
    1109 }
    +
    +
    1110
    +
    +
    1114 void remove(basic* source)
    +
    1115 {
    +
    1116 for (auto w = m_workers.begin(), w_end = m_workers.end(); w != w_end; ++w) {
    +
    1117 auto _w = w->get();
    +
    1118 if (_w->source == source) {
    +
    1119 {
    +
    1120 const std::lock_guard<std::mutex> lk(_w->mutex);
    +
    1121 _w->op = worker::op_t::quit;
    +
    1122 }
    +
    1123 _w->cv.notify_one();
    +
    1124 _w->join();
    +
    1125 m_workers.erase(w);
    +
    1126 return;
    +
    1127 }
    +
    1128 }
    +
    1129 }
    +
    +
    1130
    +
    +
    1131 virtual _Success_(return != 0) size_t write(
    +
    1132 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
    +
    1133 {
    +
    1134 for (auto w = m_workers.begin(), w_end = m_workers.end(); w != w_end; ++w) {
    +
    1135 auto _w = w->get();
    +
    1136 {
    +
    1137 const std::lock_guard<std::mutex> lk(_w->mutex);
    +
    1138 _w->op = worker::op_t::write;
    +
    1139 _w->data = data;
    +
    1140 _w->length = length;
    +
    1141 }
    +
    1142 _w->cv.notify_one();
    +
    1143 }
    +
    1144 size_t num_written = length;
    +
    1145 m_state = state_t::ok;
    +
    1146 for (auto w = m_workers.begin(), w_end = m_workers.end(); w != w_end; ++w) {
    +
    1147 auto _w = w->get();
    +
    1148 std::unique_lock<std::mutex> lk(_w->mutex);
    +
    1149 _w->cv.wait(lk, [&] {return _w->op == worker::op_t::noop; });
    +
    1150 if (_w->num_written < num_written)
    +
    1151 num_written = _w->num_written;
    +
    1152 if (ok() && !_w->source->ok())
    +
    1153 m_state = _w->source->state();
    +
    1154 }
    +
    1155 return num_written;
    +
    1156 }
    +
    +
    1157
    +
    +
    1158 virtual void close()
    +
    1159 {
    +
    1160 foreach_worker(worker::op_t::close);
    +
    1161 }
    +
    +
    1162
    +
    +
    1163 virtual void flush()
    +
    1164 {
    +
    1165 foreach_worker(worker::op_t::flush);
    +
    1166 }
    +
    +
    1167
    +
    1168 protected:
    +
    +
    1169 class worker : public std::thread
    +
    1170 {
    +
    1171 public:
    +
    1172 worker(_In_ basic* _source) :
    +
    1173 source(_source),
    +
    1174 op(op_t::noop),
    +
    1175 data(nullptr),
    +
    1176 length(0),
    +
    1177 num_written(0)
    +
    1178 {
    +
    1179 *static_cast<std::thread*>(this) = std::thread([](_Inout_ worker& w) { w.process_op(); }, std::ref(*this));
    +
    1180 }
    +
    1181
    +
    1182 protected:
    +
    1183 void process_op()
    +
    1184 {
    +
    1185 for (;;) {
    +
    1186 std::unique_lock<std::mutex> lk(mutex);
    +
    1187 cv.wait(lk, [&] {return op != op_t::noop; });
    +
    1188 switch (op) {
    +
    1189 case op_t::quit:
    +
    1190 return;
    +
    1191 case op_t::write:
    +
    1192 num_written = source->write(data, length);
    +
    1193 break;
    +
    1194 case op_t::close:
    +
    1195 source->close();
    +
    1196 break;
    +
    1197 case op_t::flush:
    +
    1198 source->flush();
    +
    1199 break;
    +
    1200 case op_t::noop:;
    +
    1201 }
    +
    1202 op = op_t::noop;
    +
    1203 lk.unlock();
    +
    1204 cv.notify_one();
    +
    1205 }
    +
    1206 }
    +
    1207
    +
    1208 public:
    +
    1209 basic* source;
    +
    1210 enum class op_t {
    +
    1211 noop = 0,
    +
    1212 quit,
    +
    1213 write,
    +
    1214 close,
    +
    1215 flush,
    +
    1216 } op;
    +
    1217 const void* data;
    +
    1218 size_t length;
    + +
    1220 std::mutex mutex;
    +
    1221 std::condition_variable cv;
    +
    1222 };
    +
    +
    1223
    +
    1224 void foreach_worker(_In_ worker::op_t op)
    +
    1225 {
    +
    1226 for (auto w = m_workers.begin(), w_end = m_workers.end(); w != w_end; ++w) {
    +
    1227 auto _w = w->get();
    +
    1228 {
    +
    1229 const std::lock_guard<std::mutex> lk(_w->mutex);
    +
    1230 _w->op = op;
    +
    1231 }
    +
    1232 _w->cv.notify_one();
    +
    1233 }
    +
    1234 m_state = state_t::ok;
    +
    1235 for (auto w = m_workers.begin(), w_end = m_workers.end(); w != w_end; ++w) {
    +
    1236 auto _w = w->get();
    +
    1237 std::unique_lock<std::mutex> lk(_w->mutex);
    +
    1238 _w->cv.wait(lk, [&] {return _w->op == worker::op_t::noop; });
    +
    1239 if (ok())
    +
    1240 m_state = _w->source->state();
    +
    1241 }
    +
    1242 }
    +
    1243
    +
    1244 std::list<std::unique_ptr<worker>> m_workers;
    +
    1245 };
    +
    +
    1246
    +
    1247 constexpr size_t default_async_limit = 0x100000;
    +
    1248
    +
    1254 template <size_t CAPACITY = default_async_limit>
    +
    + +
    1256 {
    +
    1257 public:
    +
    1258 async_reader(_Inout_ basic& source) :
    +
    1259 converter(source),
    +
    1260 m_worker([](_Inout_ async_reader& w) { w.process(); }, std::ref(*this))
    +
    1261 {}
    +
    1262
    +
    1263 virtual ~async_reader()
    +
    1264 {
    +
    1265 m_ring.quit();
    +
    1266 m_worker.join();
    +
    1267 }
    +
    1268
    +
    1269#pragma warning(suppress: 6101) // See [1] below
    +
    +
    1270 virtual _Success_(return != 0 || length == 0) size_t read(
    +
    1271 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
    +
    1272 {
    +
    1273 _Assume_(data || !length);
    +
    1274 for (size_t to_read = length;;) {
    +
    1275 uint8_t* ptr; size_t num_read;
    +
    1276 std::tie(ptr, num_read) = m_ring.front();
    +
    1277 if (!ptr) _Unlikely_ {
    +
    1278 m_state = to_read < length || !length ? state_t::ok : m_source->state();
    +
    1279 return length - to_read; // [1] Code analysis misses `length - to_read` bytes were written to data in previous loop iterations.
    +
    1280 }
    +
    1281 if (to_read < num_read)
    +
    1282 num_read = to_read;
    +
    1283 memcpy(data, ptr, num_read);
    +
    1284 m_ring.pop(num_read);
    +
    1285 to_read -= num_read;
    +
    1286 if (!to_read) {
    +
    1287 m_state = state_t::ok;
    +
    1288 return length;
    +
    1289 }
    +
    1290 reinterpret_cast<uint8_t*&>(data) += num_read;
    +
    1291 }
    +
    1292 }
    +
    +
    1293
    +
    1294 protected:
    +
    1295 void process()
    +
    1296 {
    +
    1297 for (;;) {
    +
    1298 uint8_t* ptr; size_t num_write;
    +
    1299 std::tie(ptr, num_write) = m_ring.back();
    +
    1300 if (!ptr) _Unlikely_
    +
    1301 break;
    +
    1302 num_write = m_source->read(ptr, num_write);
    +
    1303 m_ring.push(num_write);
    +
    1304 if (!m_source->ok()) {
    +
    1305 m_ring.quit();
    +
    1306 break;
    +
    1307 }
    +
    1308 }
    +
    1309 }
    +
    1310
    +
    1311 protected:
    +
    1312 ring<uint8_t, CAPACITY> m_ring;
    +
    1313 std::thread m_worker;
    +
    1314 };
    +
    +
    1315
    +
    1321 template <size_t CAPACITY = default_async_limit>
    +
    + +
    1323 {
    +
    1324 public:
    +
    1325 async_writer(_Inout_ basic& source) :
    +
    1326 converter(source),
    +
    1327 m_worker([](_Inout_ async_writer& w) { w.process(); }, std::ref(*this))
    +
    1328 {}
    +
    1329
    +
    1330 virtual ~async_writer()
    +
    1331 {
    +
    1332 m_ring.quit();
    +
    1333 m_worker.join();
    +
    1334 }
    +
    1335
    +
    +
    1336 virtual _Success_(return != 0) size_t write(
    +
    1337 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
    +
    1338 {
    +
    1339 _Assume_(data || !length);
    +
    1340 for (size_t to_write = length;;) {
    +
    1341 uint8_t* ptr; size_t num_write;
    +
    1342 std::tie(ptr, num_write) = m_ring.back();
    +
    1343 if (!ptr) _Unlikely_ {
    +
    1344 m_state = state_t::fail;
    +
    1345 return length - to_write;
    +
    1346 }
    +
    1347 if (to_write < num_write)
    +
    1348 num_write = to_write;
    +
    1349 memcpy(ptr, data, num_write);
    +
    1350 m_ring.push(num_write);
    +
    1351 to_write -= num_write;
    +
    1352 if (!to_write) {
    +
    1353 m_state = state_t::ok;
    +
    1354 return length;
    +
    1355 }
    +
    1356 reinterpret_cast<const uint8_t*&>(data) += num_write;
    +
    1357 }
    +
    1358 }
    +
    +
    1359
    +
    +
    1360 virtual void flush()
    +
    1361 {
    +
    1362 m_ring.sync();
    + +
    1364 }
    +
    +
    1365
    +
    1366 protected:
    +
    1367 void process()
    +
    1368 {
    +
    1369 for (;;) {
    +
    1370 uint8_t* ptr; size_t num_read;
    +
    1371 std::tie(ptr, num_read) = m_ring.front();
    +
    1372 if (!ptr)
    +
    1373 break;
    +
    1374 num_read = m_source->write(ptr, num_read);
    +
    1375 m_ring.pop(num_read);
    +
    1376 if (!m_source->ok()) {
    +
    1377 m_ring.quit();
    +
    1378 break;
    +
    1379 }
    +
    1380 }
    +
    1381 }
    +
    1382
    +
    1383 protected:
    +
    1384 ring<uint8_t, CAPACITY> m_ring;
    +
    1385 std::thread m_worker;
    +
    1386 };
    +
    +
    1387
    +
    1388 constexpr size_t default_buffer_size = 0x400;
    +
    1389
    +
    +
    1393 class buffer : public converter
    +
    1394 {
    +
    1395 protected:
    +
    1397 explicit buffer(_In_ size_t read_buffer_size = default_buffer_size, _In_ size_t write_buffer_size = default_buffer_size) :
    +
    1398 converter(),
    +
    1399 m_read_buffer(read_buffer_size),
    +
    1400 m_write_buffer(write_buffer_size)
    +
    1401 {}
    +
    1402
    +
    1403 void done()
    +
    1404 {
    +
    1405 if (m_source)
    +
    1406 flush_write();
    +
    1407 converter::done();
    +
    1408 }
    +
    1410
    +
    1411 public:
    +
    1412 buffer(_Inout_ basic& source, _In_ size_t read_buffer_size = default_buffer_size, _In_ size_t write_buffer_size = default_buffer_size) :
    +
    1413 converter(source),
    +
    1414 m_read_buffer(read_buffer_size),
    +
    1415 m_write_buffer(write_buffer_size)
    +
    1416 {}
    +
    1417
    +
    1418 virtual ~buffer()
    +
    1419 {
    +
    1420 if (m_source)
    +
    1421 flush_write();
    +
    1422 }
    +
    1423
    +
    +
    1424 virtual _Success_(return != 0 || length == 0) size_t read(
    +
    1425 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
    +
    1426 {
    +
    1427 _Assume_(data || !length);
    +
    1428 for (size_t to_read = length;;) {
    +
    1429 size_t buffer_size = m_read_buffer.tail - m_read_buffer.head;
    +
    1430 if (to_read <= buffer_size) {
    +
    1431 memcpy(data, m_read_buffer.data + m_read_buffer.head, to_read);
    +
    1432 m_read_buffer.head += to_read;
    +
    1433 m_state = state_t::ok;
    +
    1434 return length;
    +
    1435 }
    +
    1436 if (buffer_size) {
    +
    1437 memcpy(data, m_read_buffer.data + m_read_buffer.head, buffer_size);
    +
    1438 reinterpret_cast<uint8_t*&>(data) += buffer_size;
    +
    1439 to_read -= buffer_size;
    +
    1440 }
    +
    1441 m_read_buffer.head = 0;
    +
    1442 if (to_read > m_read_buffer.capacity) {
    +
    1443 // When needing to read more data than buffer capacity, bypass the buffer.
    +
    1444 m_read_buffer.tail = 0;
    +
    1445 to_read -= m_source->read(data, to_read);
    +
    1446 m_state = to_read < length ? state_t::ok : m_source->state();
    +
    1447 return length - to_read;
    +
    1448 }
    +
    1449 m_read_buffer.tail = m_source->read(m_read_buffer.data, m_read_buffer.capacity);
    +
    1450 if (m_read_buffer.tail < m_read_buffer.capacity && m_read_buffer.tail < to_read) _Unlikely_ {
    +
    1451 memcpy(data, m_read_buffer.data, m_read_buffer.tail);
    +
    1452 m_read_buffer.head = m_read_buffer.tail;
    +
    1453 to_read -= m_read_buffer.tail;
    +
    1454 m_state = to_read < length ? state_t::ok : m_source->state();
    +
    1455 return length - to_read;
    +
    1456 }
    +
    1457 }
    +
    1458 }
    +
    +
    1459
    +
    +
    1460 virtual _Success_(return != 0) size_t write(
    +
    1461 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
    +
    1462 {
    +
    1463 _Assume_(data || !length);
    +
    1464 if (!length) _Unlikely_ {
    +
    1465 // Pass null writes (zero-byte length). Null write operations have special meaning with with Windows pipes.
    +
    1466 flush_write();
    +
    1467 if (!ok()) _Unlikely_
    +
    1468 return 0;
    +
    1469 converter::write(nullptr, 0);
    +
    1470 return 0;
    +
    1471 }
    +
    1472
    +
    1473 for (size_t to_write = length;;) {
    +
    1474 size_t available_buffer = m_write_buffer.capacity - m_write_buffer.tail;
    +
    1475 if (to_write <= available_buffer) {
    +
    1476 memcpy(m_write_buffer.data + m_write_buffer.tail, data, to_write);
    +
    1477 m_write_buffer.tail += to_write;
    +
    1478 m_state = state_t::ok;
    +
    1479 return length;
    +
    1480 }
    +
    1481 if (available_buffer) {
    +
    1482 memcpy(m_write_buffer.data + m_write_buffer.tail, data, available_buffer);
    +
    1483 reinterpret_cast<const uint8_t*&>(data) += available_buffer;
    +
    1484 to_write -= available_buffer;
    +
    1485 m_write_buffer.tail += available_buffer;
    +
    1486 }
    +
    1487 size_t buffer_size = m_write_buffer.tail - m_write_buffer.head;
    +
    1488 if (buffer_size) {
    +
    1489 m_write_buffer.head += converter::write(m_write_buffer.data + m_write_buffer.head, buffer_size);
    +
    1490 if (m_write_buffer.head == m_write_buffer.tail)
    +
    1491 m_write_buffer.head = m_write_buffer.tail = 0;
    +
    1492 else
    +
    1493 return length - to_write;
    +
    1494 }
    +
    1495 if (to_write > m_write_buffer.capacity) {
    +
    1496 // When needing to write more data than buffer capacity, bypass the buffer.
    +
    1497 to_write -= converter::write(data, to_write);
    +
    1498 return length - to_write;
    +
    1499 }
    +
    1500 }
    +
    1501 }
    +
    +
    1502
    +
    +
    1503 virtual void flush()
    +
    1504 {
    +
    1505 flush_write();
    +
    1506 if (ok())
    + +
    1508 }
    +
    +
    1509
    +
    1510 protected:
    +
    1511 void flush_write()
    +
    1512 {
    +
    1513 size_t buffer_size = m_write_buffer.tail - m_write_buffer.head;
    +
    1514 if (buffer_size) {
    +
    1515 m_write_buffer.head += m_source->write(m_write_buffer.data + m_write_buffer.head, buffer_size);
    +
    1516 if (m_write_buffer.head == m_write_buffer.tail) {
    +
    1517 m_write_buffer.head = 0;
    +
    1518 m_write_buffer.tail = 0;
    +
    1519 }
    +
    1520 else {
    +
    1521 m_state = m_source->state();
    +
    1522 return;
    +
    1523 }
    +
    1524 }
    +
    1525 m_state = state_t::ok;
    +
    1526 }
    +
    1527
    +
    +
    1528 struct buffer_t {
    +
    1529 uint8_t* data;
    +
    1530 size_t head, tail, capacity;
    +
    1531
    +
    1532 buffer_t(_In_ size_t buffer_size) :
    +
    1533 head(0),
    +
    1534 tail(0),
    +
    1535 capacity(buffer_size),
    +
    1536 data(buffer_size ? new uint8_t[buffer_size] : nullptr)
    +
    1537 {}
    +
    1538
    +
    1539 ~buffer_t()
    +
    1540 {
    +
    1541 if (data)
    +
    1542 delete[] data;
    +
    1543 }
    +
    1544 } m_read_buffer, m_write_buffer;
    +
    +
    1545 };
    +
    +
    1546
    +
    +
    1550 class limiter : public converter
    +
    1551 {
    +
    1552 public:
    +
    1553 limiter(_Inout_ basic& source, _In_ fsize_t _read_limit = 0, _In_ fsize_t _write_limit = 0) :
    +
    1554 converter(source),
    +
    1555 read_limit(_read_limit),
    +
    1556 write_limit(_write_limit)
    +
    1557 {}
    +
    1558
    +
    +
    1559 virtual _Success_(return != 0 || length == 0) size_t read(
    +
    1560 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
    +
    1561 {
    +
    1562 size_t num_read;
    +
    1563 if (read_limit == fsize_max)
    +
    1564 num_read = converter::read(data, length);
    +
    1565 else if (length <= read_limit) {
    +
    1566 num_read = converter::read(data, length);
    +
    1567 read_limit -= num_read;
    +
    1568 }
    +
    1569 else if (length && !read_limit) {
    +
    1570 num_read = 0;
    +
    1571 m_state = state_t::eof;
    +
    1572 }
    +
    1573 else {
    +
    1574 num_read = converter::read(data, static_cast<size_t>(read_limit));
    +
    1575 read_limit -= num_read;
    +
    1576 }
    +
    1577 return num_read;
    +
    1578 }
    +
    +
    1579
    +
    +
    1580 virtual _Success_(return != 0) size_t write(
    +
    1581 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
    +
    1582 {
    +
    1583 size_t num_written;
    +
    1584 if (write_limit == fsize_max)
    +
    1585 num_written = converter::write(data, length);
    +
    1586 else if (length <= write_limit) {
    +
    1587 num_written = converter::write(data, length);
    +
    1588 write_limit -= num_written;
    +
    1589 }
    +
    1590 else if (length && !write_limit) {
    +
    1591 num_written = 0;
    +
    1592 m_state = state_t::fail;
    +
    1593 }
    +
    1594 else {
    +
    1595 num_written = converter::write(data, static_cast<size_t>(write_limit));
    +
    1596 write_limit -= num_written;
    +
    1597 }
    +
    1598 return num_written;
    +
    1599 }
    +
    +
    1600
    +
    1601 public:
    +
    1602 fsize_t
    + + +
    1605 };
    +
    +
    1606
    +
    +
    1610 class window : public limiter
    +
    1611 {
    +
    1612 public:
    +
    1613 window(_Inout_ basic& source, _In_ fpos_t _read_offset = 0, _In_ fsize_t read_limit = fsize_max, _In_ fpos_t _write_offset = 0, _In_ fsize_t write_limit = fsize_max) :
    +
    1614 limiter(source, read_limit, write_limit),
    +
    1615 read_offset(_read_offset),
    +
    1616 write_offset(_write_offset)
    +
    1617 {}
    +
    1618
    +
    +
    1619 virtual _Success_(return != 0 || length == 0) size_t read(
    +
    1620 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
    +
    1621 {
    +
    1622 if (read_offset) {
    +
    1623 m_source->skip(read_offset);
    +
    1624 m_state = m_source->state();
    +
    1625 if (!ok()) _Unlikely_
    +
    1626 return 0;
    +
    1627 read_offset = 0;
    +
    1628 }
    +
    1629 size_t num_read;
    +
    1630 if (read_limit == fsize_max)
    +
    1631 num_read = converter::read(data, length);
    +
    1632 else if (length <= read_limit) {
    +
    1633 num_read = converter::read(data, length);
    +
    1634 read_limit -= num_read;
    +
    1635 }
    +
    1636 else if (length && !read_limit) {
    +
    1637 num_read = 0;
    +
    1638 m_source->skip(length);
    +
    1639 m_state = state_t::eof;
    +
    1640 }
    +
    1641 else {
    +
    1642 num_read = converter::read(data, static_cast<size_t>(read_limit));
    +
    1643 read_limit -= num_read;
    +
    1644 }
    +
    1645 return num_read;
    +
    1646 }
    +
    +
    1647
    +
    +
    1648 virtual _Success_(return != 0) size_t write(
    +
    1649 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
    +
    1650 {
    +
    1651 size_t num_skipped, num_written;
    +
    1652 if (length <= write_offset) {
    +
    1653 write_offset -= length;
    +
    1654 m_state = state_t::ok;
    +
    1655 return length;
    +
    1656 }
    +
    1657 if (write_offset) {
    +
    1658 reinterpret_cast<const uint8_t*&>(data) += static_cast<size_t>(write_offset);
    +
    1659 length -= static_cast<size_t>(write_offset);
    +
    1660 num_skipped = static_cast<size_t>(write_offset);
    +
    1661 write_offset = 0;
    +
    1662 }
    +
    1663 else
    +
    1664 num_skipped = 0;
    +
    1665 if (write_limit == fsize_max)
    +
    1666 num_written = converter::write(data, length);
    +
    1667 else if (length <= write_limit) {
    +
    1668 num_written = converter::write(data, length);
    +
    1669 write_limit -= num_written;
    +
    1670 }
    +
    1671 else if (length && !write_limit) {
    +
    1672 num_skipped += length;
    +
    1673 num_written = 0;
    +
    1674 m_state = state_t::ok;
    +
    1675 }
    +
    1676 else {
    +
    1677 num_skipped += length - static_cast<size_t>(write_limit);
    +
    1678 num_written = converter::write(data, static_cast<size_t>(write_limit));
    +
    1679 write_limit -= num_written;
    +
    1680 }
    +
    1681 return num_skipped + num_written;
    +
    1682 }
    +
    +
    1683
    +
    1684 public:
    +
    1685 fpos_t
    + + +
    1688 };
    +
    +
    1689
    +
    + +
    1694 {
    +
    1695 public:
    +
    1696 file_window(_Inout_ basic_file& source, fpos_t offset = 0, fsize_t length = 0) :
    +
    1697 basic(source.state()),
    +
    1698 m_source(source),
    +
    1699 m_offset(source.tell()),
    +
    1700 m_region(offset, offset + length)
    +
    1701 {}
    +
    1702
    +
    +
    1703 virtual _Success_(return != 0 || length == 0) size_t read(
    +
    1704 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
    +
    1705 {
    +
    1706 _Assume_(data || !length);
    +
    1707 if (m_region.contains(m_offset)) {
    +
    1708 size_t num_read = m_source.read(data, static_cast<size_t>(std::min<fpos_t>(length, m_region.end - m_offset)));
    +
    1709 m_state = m_source.state();
    +
    1710 m_offset += num_read;
    +
    1711 return num_read;
    +
    1712 }
    +
    1713 m_state = length ? state_t::eof : state_t::ok;
    +
    1714 return 0;
    +
    1715 }
    +
    +
    1716
    +
    +
    1717 virtual _Success_(return != 0) size_t write(
    +
    1718 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
    +
    1719 {
    +
    1720 _Assume_(data || !length);
    +
    1721 if (m_region.contains(m_offset)) {
    +
    1722 size_t num_written = m_source.write(data, static_cast<size_t>(std::min<fpos_t>(length, m_region.end - m_offset)));
    +
    1723 m_state = m_source.state();
    +
    1724 m_offset += num_written;
    +
    1725 return num_written;
    +
    1726 }
    +
    1727 m_state = state_t::fail;
    +
    1728 return 0;
    +
    1729 }
    +
    +
    1730
    +
    +
    1731 virtual void close()
    +
    1732 {
    +
    1733 m_source.close();
    +
    1734 m_state = m_source.state();
    +
    1735 }
    +
    +
    1736
    +
    +
    1737 virtual void flush()
    +
    1738 {
    +
    1739 m_source.flush();
    +
    1740 m_state = m_source.state();
    +
    1741 }
    +
    +
    1742
    +
    +
    1743 virtual fpos_t seek(_In_ foff_t offset, _In_ seek_t how = seek_t::beg)
    +
    1744 {
    +
    1745 m_offset = m_source.seek(offset, how);
    +
    1746 m_state = m_source.state();
    +
    1747 return ok() ? m_offset - m_region.start : fpos_max;
    +
    1748 }
    +
    +
    1749
    +
    +
    1750 virtual void skip(_In_ fsize_t amount)
    +
    1751 {
    +
    1752 m_source.skip(amount);
    +
    1753 m_state = m_source.state();
    +
    1754 }
    +
    +
    1755
    +
    +
    1756 virtual fpos_t tell() const
    +
    1757 {
    +
    1758 fpos_t offset = m_source.tell();
    +
    1759 return m_region.contains(offset) ? offset - m_region.start : fpos_max;
    +
    1760 }
    +
    +
    1761
    +
    +
    1762 virtual void lock(_In_ fpos_t offset, _In_ fsize_t length)
    +
    1763 {
    +
    1764 if (m_region.contains(offset)) {
    +
    1765 m_source.lock(m_region.start + offset, std::min<fsize_t>(length, m_region.end - offset));
    +
    1766 m_state = m_source.state();
    +
    1767 }
    +
    1768 else
    +
    1769 m_state = state_t::fail;
    +
    1770 }
    +
    +
    1771
    +
    +
    1772 virtual void unlock(_In_ fpos_t offset, _In_ fsize_t length)
    +
    1773 {
    +
    1774 if (m_region.contains(offset)) {
    +
    1775 m_source.unlock(m_region.start + offset, std::min<fsize_t>(length, m_region.end - offset));
    +
    1776 m_state = m_source.state();
    +
    1777 }
    +
    1778 else
    +
    1779 m_state = state_t::fail;
    +
    1780 }
    +
    +
    1781
    +
    +
    1782 virtual fsize_t size()
    +
    1783 {
    +
    1784 return m_region.size();
    +
    1785 }
    +
    +
    1786
    +
    +
    1787 virtual void truncate()
    +
    1788 {
    +
    1789 m_state = state_t::fail;
    +
    1790 }
    +
    +
    1791
    +
    1792 protected:
    +
    1793 basic_file& m_source;
    +
    1794 fpos_t m_offset;
    +
    1795 interval<fpos_t> m_region;
    +
    1796 };
    +
    +
    1797
    +
    1798 constexpr size_t default_cache_size = 0x1000;
    +
    1799
    +
    +
    1803 class cache : public basic_file
    +
    1804 {
    +
    1805 protected:
    +
    1807#pragma warning(suppress: 26495) // The delayed init call will finish initializing the class.
    +
    1808 explicit cache(_In_ size_t cache_size = default_cache_size) :
    +
    1809 basic(state_t::fail),
    +
    1810 m_cache(cache_size)
    +
    1811 {}
    +
    1812
    +
    1813 void init(_Inout_ basic_file& source)
    +
    1814 {
    +
    1815 m_source = &source;
    +
    1816 init();
    +
    1817 }
    +
    1818
    +
    1819 void init()
    +
    1820 {
    +
    1821 m_state = m_source->state();
    +
    1822 m_offset = m_source->tell();
    +
    1823#if SET_FILE_OP_TIMES
    +
    1824 m_atime = m_source->atime();
    +
    1825 m_mtime = m_source->mtime();
    +
    1826#endif
    +
    1827 }
    +
    1828
    +
    1829 void done()
    +
    1830 {
    +
    1831 if (m_source) {
    +
    1832 flush_cache();
    +
    1833 if (!ok()) _Unlikely_
    +
    1834 throw std::system_error(sys_error(), std::system_category(), "failed to flush cache"); // Data loss occured
    +
    1835 m_source->seek(m_offset);
    +
    1836#if SET_FILE_OP_TIMES
    +
    1837 m_source->set_atime(m_atime);
    +
    1838 m_source->set_mtime(m_mtime);
    +
    1839#endif
    +
    1840 m_source = nullptr;
    +
    1841 }
    +
    1842 }
    +
    1844
    +
    1845 public:
    +
    1846 cache(_Inout_ basic_file& source, _In_ size_t cache_size = default_cache_size) :
    +
    1847 basic(source.state()),
    +
    1848 m_source(&source),
    +
    1849 m_cache(cache_size),
    +
    1850 m_offset(source.tell())
    +
    1851#if SET_FILE_OP_TIMES
    +
    1852 , m_atime(source.atime())
    +
    1853 , m_mtime(source.mtime())
    +
    1854#endif
    +
    1855 {}
    +
    1856
    +
    1857 virtual ~cache() noexcept(false)
    +
    1858 {
    +
    1859 if (m_source) {
    +
    1860 flush_cache();
    +
    1861 if (!ok()) _Unlikely_
    +
    1862 throw std::system_error(sys_error(), std::system_category(), "failed to flush cache"); // Data loss occured
    +
    1863 m_source->seek(m_offset);
    +
    1864#if SET_FILE_OP_TIMES
    +
    1865 m_source->set_atime(m_atime);
    +
    1866 m_source->set_mtime(m_mtime);
    +
    1867#endif
    +
    1868 }
    +
    1869 }
    +
    1870
    +
    +
    1871 virtual _Success_(return != 0 || length == 0) size_t read(
    +
    1872 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
    +
    1873 {
    +
    1874 _Assume_(data || !length);
    +
    1875#if SET_FILE_OP_TIMES
    +
    1876 m_atime = time_point::now();
    +
    1877#endif
    +
    1878 for (size_t to_read = length;;) {
    +
    1879 if (m_cache.status != cache_t::cache_t::status_t::empty) {
    +
    1880 if (m_cache.region.contains(m_offset)) {
    +
    1881 size_t remaining_cache = static_cast<size_t>(m_cache.region.end - m_offset);
    +
    1882 if (to_read <= remaining_cache) {
    +
    1883 memcpy(data, m_cache.data + static_cast<size_t>(m_offset - m_cache.region.start), to_read);
    +
    1884 m_offset += to_read;
    +
    1885 m_state = state_t::ok;
    +
    1886 return length;
    +
    1887 }
    +
    1888 memcpy(data, m_cache.data + static_cast<size_t>(m_offset - m_cache.region.start), remaining_cache);
    +
    1889 reinterpret_cast<uint8_t*&>(data) += remaining_cache;
    +
    1890 to_read -= remaining_cache;
    +
    1891 m_offset += remaining_cache;
    +
    1892 }
    +
    1893 flush_cache();
    +
    1894 if (!ok()) _Unlikely_ {
    +
    1895 if (to_read < length)
    +
    1896 m_state = state_t::ok;
    +
    1897 return length - to_read;
    +
    1898 }
    +
    1899 }
    +
    1900 {
    +
    1901 fpos_t end_max = m_offset + to_read;
    +
    1902 if (m_offset / m_cache.capacity < end_max / m_cache.capacity) {
    +
    1903 // Read spans multiple cache blocks. Bypass cache to the last block.
    +
    1904 m_source->seek(m_offset);
    +
    1905 if (!m_source->ok()) _Unlikely_ {
    +
    1906 m_state = to_read < length ? state_t::ok : state_t::fail;
    +
    1907 return length - to_read;
    +
    1908 }
    +
    1909 size_t num_read = m_source->read(data, to_read - static_cast<size_t>(end_max % m_cache.capacity));
    +
    1910 m_offset += num_read;
    +
    1911 to_read -= num_read;
    +
    1912 if (!to_read) {
    +
    1913 m_state = state_t::ok;
    +
    1914 return length;
    +
    1915 }
    +
    1916 reinterpret_cast<uint8_t*&>(data) += num_read;
    +
    1917 m_state = m_source->state();
    +
    1918 if (!ok()) {
    +
    1919 if (to_read < length)
    +
    1920 m_state = state_t::ok;
    +
    1921 return length - to_read;
    +
    1922 }
    +
    1923 }
    +
    1924 }
    +
    1925 load_cache(m_offset);
    +
    1926 if (!ok() || m_cache.region.end <= m_offset) _Unlikely_ {
    +
    1927 m_state = to_read < length ? state_t::ok : state_t::fail;
    +
    1928 return length - to_read;
    +
    1929 }
    +
    1930 }
    +
    1931 }
    +
    +
    1932
    +
    +
    1933 virtual _Success_(return != 0) size_t write(
    +
    1934 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
    +
    1935 {
    +
    1936 _Assume_(data || !length);
    +
    1937#if SET_FILE_OP_TIMES
    +
    1938 m_atime = m_mtime = time_point::now();
    +
    1939#endif
    +
    1940 for (size_t to_write = length;;) {
    +
    1941 if (m_cache.status != cache_t::cache_t::status_t::empty) {
    +
    1942 fpos_t end_max = m_cache.region.start + m_cache.capacity;
    +
    1943 if (m_cache.region.start <= m_offset && m_offset < end_max) {
    +
    1944 size_t remaining_cache = static_cast<size_t>(end_max - m_offset);
    +
    1945 if (to_write <= remaining_cache) {
    +
    1946 memcpy(m_cache.data + static_cast<size_t>(m_offset - m_cache.region.start), data, to_write);
    +
    1947 m_offset += to_write;
    +
    1948 m_cache.status = cache_t::cache_t::status_t::dirty;
    +
    1949 m_cache.region.end = std::max(m_cache.region.end, m_offset);
    +
    1950 m_state = state_t::ok;
    +
    1951 return length;
    +
    1952 }
    +
    1953 memcpy(m_cache.data + static_cast<size_t>(m_offset - m_cache.region.start), data, remaining_cache);
    +
    1954 reinterpret_cast<const uint8_t*&>(data) += remaining_cache;
    +
    1955 to_write -= remaining_cache;
    +
    1956 m_offset += remaining_cache;
    +
    1957 m_cache.status = cache_t::cache_t::status_t::dirty;
    +
    1958 m_cache.region.end = end_max;
    +
    1959 }
    +
    1960 flush_cache();
    +
    1961 if (!ok()) _Unlikely_
    +
    1962 return length - to_write;
    +
    1963 }
    +
    1964 {
    +
    1965 fpos_t end_max = m_offset + to_write;
    +
    1966 if (m_offset / m_cache.capacity < end_max / m_cache.capacity) {
    +
    1967 // Write spans multiple cache blocks. Bypass cache to the last block.
    +
    1968 m_source->seek(m_offset);
    +
    1969 if (!ok()) _Unlikely_
    +
    1970 return length - to_write;
    +
    1971 size_t num_written = m_source->write(data, to_write - static_cast<size_t>(end_max % m_cache.capacity));
    +
    1972 m_offset += num_written;
    +
    1973 m_state = m_source->state();
    +
    1974 to_write -= num_written;
    +
    1975 if (!to_write || !ok())
    +
    1976 return length - to_write;
    +
    1977 reinterpret_cast<const uint8_t*&>(data) += num_written;
    +
    1978 }
    +
    1979 }
    +
    1980 load_cache(m_offset);
    +
    1981 if (!ok()) _Unlikely_
    +
    1982 return length - to_write;
    +
    1983 }
    +
    1984 }
    +
    +
    1985
    +
    +
    1986 virtual void close()
    +
    1987 {
    +
    1988 invalidate_cache();
    +
    1989 if (!ok()) _Unlikely_
    +
    1990 throw std::system_error(sys_error(), std::system_category(), "failed to flush cache"); // Data loss occured
    +
    1991 m_source->close();
    +
    1992 m_state = m_source->state();
    +
    1993 }
    +
    +
    1994
    +
    +
    1995 virtual void flush()
    +
    1996 {
    +
    1997#if SET_FILE_OP_TIMES
    +
    1998 m_atime = m_mtime = time_point::min();
    +
    1999#endif
    +
    2000 flush_cache();
    +
    2001 if (!ok()) _Unlikely_
    +
    2002 return;
    +
    2003 m_source->flush();
    +
    2004 }
    +
    +
    2005
    +
    +
    2006 virtual fpos_t seek(_In_ foff_t offset, _In_ seek_t how = seek_t::beg)
    +
    2007 {
    +
    2008 m_state = state_t::ok;
    +
    2009 switch (how) {
    +
    2010 case seek_t::beg:
    +
    2011 return m_offset = offset;
    +
    2012 case seek_t::cur:
    +
    2013 return m_offset += offset;
    +
    2014 case seek_t::end:
    +
    2015 return m_offset = size() + offset;
    +
    2016 default:
    +
    2017 throw std::invalid_argument("unknown seek origin");
    +
    2018 }
    +
    2019 }
    +
    +
    2020
    +
    +
    2021 virtual fpos_t tell() const
    +
    2022 {
    +
    2023 return m_offset;
    +
    2024 }
    +
    +
    2025
    +
    +
    2026 virtual void lock(_In_ fpos_t offset, _In_ fsize_t length)
    +
    2027 {
    +
    2028 m_source->lock(offset, length);
    +
    2029 m_state = m_source->state();
    +
    2030 }
    +
    +
    2031
    +
    +
    2032 virtual void unlock(_In_ fpos_t offset, _In_ fsize_t length)
    +
    2033 {
    +
    2034 m_source->unlock(offset, length);
    +
    2035 m_state = m_source->state();
    +
    2036 }
    +
    +
    2037
    +
    +
    2038 virtual fsize_t size()
    +
    2039 {
    +
    2040 return m_cache.status != cache_t::cache_t::status_t::empty ?
    +
    2041 std::max(m_source->size(), m_cache.region.end) :
    +
    2042 m_source->size();
    +
    2043 }
    +
    +
    2044
    +
    +
    2045 virtual void truncate()
    +
    2046 {
    +
    2047#if SET_FILE_OP_TIMES
    +
    2048 m_atime = m_mtime = time_point::now();
    +
    2049#endif
    +
    2050 m_source->seek(m_offset);
    +
    2051 if (m_cache.region.end <= m_offset) {
    +
    2052 // Truncation does not affect cache.
    +
    2053 }
    +
    2054 else if (m_cache.region.start <= m_offset) {
    +
    2055 // Truncation truncates cache.
    +
    2056 m_cache.region.end = m_offset;
    +
    2057 }
    +
    2058 else {
    +
    2059 // Truncation invalidates cache.
    +
    2060 m_cache.status = cache_t::cache_t::status_t::empty;
    +
    2061 }
    +
    2062 m_source->truncate();
    +
    2063 m_state = m_source->state();
    +
    2064 }
    +
    +
    2065
    +
    +
    2066 virtual time_point ctime() const
    +
    2067 {
    +
    2068 return m_source->ctime();
    +
    2069 }
    +
    +
    2070
    +
    +
    2071 virtual time_point atime() const
    +
    2072 {
    +
    2073#if SET_FILE_OP_TIMES
    +
    2074 return std::max(m_atime, m_source->atime());
    +
    2075#else
    +
    2076 return m_source->atime();
    +
    2077#endif
    +
    2078 }
    +
    +
    2079
    +
    +
    2080 virtual time_point mtime() const
    +
    2081 {
    +
    2082#if SET_FILE_OP_TIMES
    +
    2083 return std::max(m_mtime, m_source->mtime());
    +
    2084#else
    +
    2085 return m_source->mtime();
    +
    2086#endif
    +
    2087 }
    +
    +
    2088
    +
    +
    2089 virtual void set_ctime(time_point date)
    +
    2090 {
    +
    2091 m_source->set_ctime(date);
    +
    2092 }
    +
    +
    2093
    +
    +
    2094 virtual void set_atime(time_point date)
    +
    2095 {
    +
    2096#if SET_FILE_OP_TIMES
    +
    2097 m_atime = date;
    +
    2098#endif
    +
    2099 m_source->set_atime(date);
    +
    2100 }
    +
    +
    2101
    +
    +
    2102 virtual void set_mtime(time_point date)
    +
    2103 {
    +
    2104#if SET_FILE_OP_TIMES
    +
    2105 m_mtime = date;
    +
    2106#endif
    +
    2107 m_source->set_mtime(date);
    +
    2108 }
    +
    +
    2109
    +
    2110 protected:
    +
    2112 void flush_cache()
    +
    2113 {
    +
    2114 if (m_cache.status != cache_t::cache_t::status_t::dirty)
    +
    2115 m_state = state_t::ok;
    +
    2116 else if (!m_cache.region.empty()) {
    +
    2117 write_cache();
    +
    2118 if (ok())
    +
    2119 m_cache.status = cache_t::cache_t::status_t::loaded;
    +
    2120 }
    +
    2121 else {
    +
    2122 m_state = state_t::ok;
    +
    2123 m_cache.status = cache_t::cache_t::status_t::loaded;
    +
    2124 }
    +
    2125 }
    +
    2126
    +
    2127 void invalidate_cache()
    +
    2128 {
    +
    2129 if (m_cache.status == cache_t::cache_t::status_t::dirty && !m_cache.region.empty()) {
    +
    2130 write_cache();
    +
    2131 if (!ok()) _Unlikely_
    +
    2132 return;
    +
    2133 } else
    +
    2134 m_state = state_t::ok;
    +
    2135 m_cache.status = cache_t::cache_t::status_t::empty;
    +
    2136 }
    +
    2137
    +
    2138 void load_cache(_In_ fpos_t start)
    +
    2139 {
    +
    2140 _Assume_(m_cache.status != cache_t::cache_t::status_t::dirty);
    +
    2141 start -= start % m_cache.capacity; // Align to cache block size.
    +
    2142 m_source->seek(m_cache.region.start = start);
    +
    2143 if (m_source->ok()) {
    +
    2144 m_cache.region.end = start + m_source->read(m_cache.data, m_cache.capacity);
    +
    2145 m_cache.status = cache_t::cache_t::status_t::loaded;
    +
    2146 m_state = state_t::ok; // Regardless the read failure, we still might have cached some data.
    +
    2147 }
    +
    2148 else
    +
    2149 m_state = state_t::fail;
    +
    2150 }
    +
    2151
    +
    2152 void write_cache()
    +
    2153 {
    +
    2154 _Assume_(m_cache.status == cache_t::cache_t::status_t::dirty);
    +
    2155 m_source->seek(m_cache.region.start);
    +
    2156 m_source->write(m_cache.data, static_cast<size_t>(m_cache.region.size()));
    +
    2157 m_state = m_source->state();
    +
    2158 }
    +
    2159
    +
    2160 basic_file* m_source;
    +
    2161 struct cache_t {
    +
    2162 uint8_t* data;
    +
    2163 size_t capacity;
    +
    2164 enum class status_t {
    +
    2165 empty = 0,
    +
    2166 loaded,
    +
    2167 dirty,
    +
    2168 } status;
    +
    2169 interval<fpos_t> region;
    +
    2170
    +
    2171 cache_t(_In_ size_t _capacity) :
    +
    2172 data(new uint8_t[_capacity]),
    +
    2173 capacity(_capacity),
    +
    2174 status(status_t::empty),
    +
    2175 region(0)
    +
    2176 {}
    +
    2177
    +
    2178 ~cache_t()
    +
    2179 {
    +
    2180 delete[] data;
    +
    2181 }
    +
    2182 } m_cache;
    +
    2183 fpos_t m_offset;
    +
    2184#if SET_FILE_OP_TIMES
    +
    2185 time_point
    +
    2186 m_atime,
    +
    2187 m_mtime;
    +
    2188#endif
    +
    2190 };
    +
    +
    2191
    +
    +
    2195 class basic_sys : virtual public basic, public sys_object
    +
    2196 {
    +
    2197 public:
    +
    2198 basic_sys(_In_opt_ sys_handle h = invalid_handle, _In_ state_t state = state_t::ok) :
    +
    2199 basic(state),
    +
    2200 sys_object(h)
    +
    2201 {}
    +
    2202
    +
    +
    2203 virtual _Success_(return != 0 || length == 0) size_t read(
    +
    2204 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
    +
    2205 {
    +
    2206 _Assume_(data || !length);
    +
    2207 // Windows Server 2003 and Windows XP: Pipe write operations across a network are limited in size per write.
    +
    2208 // The amount varies per platform. For x86 platforms it's 63.97 MB. For x64 platforms it's 31.97 MB. For Itanium
    +
    2209 // it's 63.95 MB. For more information regarding pipes, see the Remarks section.
    +
    2210 size_t
    +
    2211#if defined(_WIN64)
    +
    2212 block_size = 0x1F80000;
    +
    2213#elif defined(_WIN32)
    +
    2214 block_size = 0x3f00000;
    +
    2215#else
    +
    2216 block_size = SSIZE_MAX;
    +
    2217#endif
    +
    2218 for (size_t to_read = length;;) {
    +
    2219#ifdef _WIN32
    +
    2220 // ReadFile() might raise exception (e.g. STATUS_FILE_BAD_FORMAT/0xE0000002).
    +
    2221 BOOL succeeded;
    +
    2222 DWORD num_read;
    +
    2223 __try { succeeded = ReadFile(m_h, data, static_cast<DWORD>(std::min<size_t>(to_read, block_size)), &num_read, nullptr); }
    +
    2224 __except (EXCEPTION_EXECUTE_HANDLER) { succeeded = FALSE; SetLastError(ERROR_UNHANDLED_EXCEPTION); num_read = 0; }
    +
    2225 if (!succeeded && GetLastError() == ERROR_NO_SYSTEM_RESOURCES && block_size > default_block_size) _Unlikely_ {
    +
    2226 // Error "Insufficient system resources exist to complete the requested service." occurs
    +
    2227 // ocasionally, when attempting to read too much data at once (e.g. over \\TSClient).
    +
    2228 block_size = default_block_size;
    +
    2229 continue;
    +
    2230 }
    +
    2231 if (!succeeded) _Unlikely_
    +
    2232#else
    +
    2233 ssize_t num_read = ::read(m_h, data, static_cast<ssize_t>(std::min<size_t>(to_read, block_size)));
    +
    2234 if (num_read < 0) _Unlikely_
    +
    2235#endif
    +
    2236 {
    +
    2237 m_state = to_read < length ? state_t::ok : state_t::fail;
    +
    2238 return length - to_read;
    +
    2239 }
    +
    2240 if (!num_read) _Unlikely_ {
    +
    2241 m_state = to_read < length || !length ? state_t::ok : state_t::eof;
    +
    2242 return length - to_read;
    +
    2243 }
    +
    2244 to_read -= num_read;
    +
    2245 if (!to_read) {
    +
    2246 m_state = state_t::ok;
    +
    2247 return length;
    +
    2248 }
    +
    2249 reinterpret_cast<uint8_t*&>(data) += num_read;
    +
    2250 }
    +
    2251 }
    +
    +
    2252
    +
    +
    2253 virtual _Success_(return != 0) size_t write(
    +
    2254 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
    +
    2255 {
    +
    2256 // Windows Server 2003 and Windows XP: Pipe write operations across a network are limited in size per write.
    +
    2257 // The amount varies per platform. For x86 platforms it's 63.97 MB. For x64 platforms it's 31.97 MB. For Itanium
    +
    2258 // it's 63.95 MB. For more information regarding pipes, see the Remarks section.
    +
    2259 constexpr size_t
    +
    2260#if defined(_WIN64)
    +
    2261 block_size = 0x1F80000;
    +
    2262#elif defined(_WIN32)
    +
    2263 block_size = 0x3f00000;
    +
    2264#else
    +
    2265 block_size = SSIZE_MAX;
    +
    2266#endif
    +
    2267 for (size_t to_write = length;;) {
    +
    2268#ifdef _WIN32
    +
    2269 // ReadFile() might raise an exception. Be cautious with WriteFile() too.
    +
    2270 BOOL succeeded;
    +
    2271 DWORD num_written;
    +
    2272 __try { succeeded = WriteFile(m_h, data, static_cast<DWORD>(std::min<size_t>(to_write, block_size)), &num_written, nullptr); }
    +
    2273 __except (EXCEPTION_EXECUTE_HANDLER) { succeeded = FALSE; SetLastError(ERROR_UNHANDLED_EXCEPTION); num_written = 0; }
    +
    2274 to_write -= num_written;
    +
    2275 if (!to_write) {
    +
    2276 m_state = state_t::ok;
    +
    2277 return length;
    +
    2278 }
    +
    2279 reinterpret_cast<const uint8_t*&>(data) += num_written;
    +
    2280 if (!succeeded) _Unlikely_ {
    +
    2281 m_state = state_t::fail;
    +
    2282 return length - to_write;
    +
    2283 }
    +
    2284#else
    +
    2285 ssize_t num_written = ::write(m_h, data, static_cast<ssize_t>(std::min<size_t>(to_write, block_size)));
    +
    2286 if (num_written < 0) _Unlikely_ {
    +
    2287 m_state = state_t::fail;
    +
    2288 return length - to_write;
    +
    2289 }
    +
    2290 to_write -= num_written;
    +
    2291 if (!to_write) {
    +
    2292 m_state = state_t::ok;
    +
    2293 return length;
    +
    2294 }
    +
    2295 reinterpret_cast<const uint8_t*&>(data) += num_written;
    +
    2296#endif
    +
    2297 }
    +
    2298 }
    +
    +
    2299
    +
    +
    2300 virtual void close()
    +
    2301 {
    +
    2302 try {
    + +
    2304 m_state = state_t::ok;
    +
    2305 }
    +
    2306 catch (...) {
    +
    2307 m_state = state_t::fail;
    +
    2308 }
    +
    2309 }
    +
    +
    2310
    +
    +
    2311 virtual void flush()
    +
    2312 {
    +
    2313#ifdef _WIN32
    +
    2314 m_state = FlushFileBuffers(m_h) ? state_t::ok : state_t::fail;
    +
    2315#else
    +
    2316 m_state = fsync(m_h) >= 0 ? state_t::ok : state_t::fail;
    +
    2317#endif
    +
    2318 }
    +
    +
    2319 };
    +
    +
    2320
    +
    +
    2324 class buffered_sys : public buffer
    +
    2325 {
    +
    2326 public:
    +
    2327 buffered_sys(_In_opt_ sys_handle h = invalid_handle, size_t read_buffer_size = default_buffer_size, size_t write_buffer_size = default_buffer_size) :
    +
    2328 buffer(read_buffer_size, write_buffer_size),
    +
    2329 m_source(h)
    +
    2330 {
    +
    2331 init(m_source);
    +
    2332 }
    +
    2333
    +
    2334 virtual ~buffered_sys()
    +
    2335 {
    +
    2336 done();
    +
    2337 }
    +
    2338
    +
    2339 protected:
    +
    2340 basic_sys m_source;
    +
    2341 };
    +
    +
    2342
    +
    +
    2346 class socket : public basic
    +
    2347 {
    +
    2348 public:
    +
    2349 socket(_In_opt_ SOCKET h = INVALID_SOCKET, _In_ state_t state = state_t::ok) :
    +
    2350 basic(state),
    +
    2351 m_h(h)
    +
    2352 {}
    +
    2353
    +
    2354 private:
    +
    2355 socket(_In_ const socket& other);
    +
    2356 socket& operator =(_In_ const socket& other);
    +
    2357
    +
    2358 public:
    +
    2359 socket(_Inout_ socket&& other) noexcept : m_h(other.m_h)
    +
    2360 {
    +
    2361 other.m_h = INVALID_SOCKET;
    +
    2362 }
    +
    2363
    +
    2364 socket& operator =(_Inout_ socket&& other) noexcept
    +
    2365 {
    +
    2366 if (this != std::addressof(other)) {
    +
    2367 if (m_h != INVALID_SOCKET)
    +
    2368 ::closesocket(m_h);
    +
    2369 m_h = other.m_h;
    +
    2370 other.m_h = INVALID_SOCKET;
    +
    2371 }
    +
    2372 return *this;
    +
    2373 }
    +
    2374
    +
    +
    2382 socket(_In_ int af, _In_ int type, _In_ int protocol)
    +
    2383 {
    +
    2384 m_h = ::socket(af, type, protocol);
    +
    2385 if (m_h == INVALID_SOCKET) _Unlikely_
    +
    2386 m_state = state_t::fail;
    +
    2387 }
    +
    +
    2388
    +
    2389 virtual ~socket()
    +
    2390 {
    +
    2391 if (m_h != INVALID_SOCKET)
    +
    2392 ::closesocket(m_h);
    +
    2393 }
    +
    2394
    +
    2398 inline operator bool() const noexcept { return m_h != INVALID_SOCKET; }
    +
    2399
    +
    2403 inline SOCKET get() const noexcept { return m_h; }
    +
    2404
    +
    +
    2405 virtual _Success_(return != 0 || length == 0) size_t read(
    +
    2406 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
    +
    2407 {
    +
    2408 _Assume_(data || !length);
    +
    2409 constexpr int block_size = 0x10000000;
    +
    2410 for (size_t to_read = length;;) {
    +
    2411 int num_read = recv(m_h, reinterpret_cast<char*>(data), static_cast<int>(std::min<size_t>(to_read, block_size)), 0);
    +
    2412 if (num_read == SOCKET_ERROR) _Unlikely_ {
    +
    2413 m_state = to_read < length ? state_t::ok : state_t::fail;
    +
    2414 return length - to_read;
    +
    2415 }
    +
    2416 if (!num_read) {
    +
    2417 m_state = to_read < length || !length ? state_t::ok : state_t::eof;
    +
    2418 return length - to_read;
    +
    2419 }
    +
    2420 to_read -= num_read;
    +
    2421 if (!to_read) {
    +
    2422 m_state = state_t::ok;
    +
    2423 return length;
    +
    2424 }
    +
    2425 reinterpret_cast<uint8_t*&>(data) += num_read;
    +
    2426 }
    +
    2427 }
    +
    +
    2428
    +
    +
    2429 virtual _Success_(return != 0) size_t write(
    +
    2430 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
    +
    2431 {
    +
    2432 _Assume_(data || !length);
    +
    2433 constexpr int block_size = 0x10000000;
    +
    2434 for (size_t to_write = length;;) {
    +
    2435 int num_written = send(m_h, reinterpret_cast<const char*>(data), static_cast<int>(std::min<size_t>(to_write, block_size)), 0);
    +
    2436 if (num_written == SOCKET_ERROR) _Unlikely_ {
    +
    2437 m_state = state_t::fail;
    +
    2438 return length - to_write;
    +
    2439 }
    +
    2440 to_write -= num_written;
    +
    2441 if (!to_write) {
    +
    2442 m_state = state_t::ok;
    +
    2443 return length;
    +
    2444 }
    +
    2445 reinterpret_cast<const uint8_t*&>(data) += num_written;
    +
    2446 }
    +
    2447 }
    +
    +
    2448
    +
    +
    2449 virtual void close()
    +
    2450 {
    +
    2451 if (m_h != INVALID_SOCKET) {
    +
    2452 ::closesocket(m_h);
    +
    2453 m_h = INVALID_SOCKET;
    +
    2454 }
    +
    2455 m_state = state_t::ok;
    +
    2456 }
    +
    +
    2457
    +
    2458 protected:
    +
    2459 SOCKET m_h;
    +
    2460 };
    +
    +
    2461
    +
    2462#ifdef _WIN32
    +
    2466 class sequential_stream : public basic
    +
    2467 {
    +
    2468 public:
    +
    2469 sequential_stream(_In_ ISequentialStream* source) : m_source(source)
    +
    2470 {
    +
    2471 m_source->AddRef();
    +
    2472 }
    +
    2473
    +
    2474 virtual ~sequential_stream()
    +
    2475 {
    +
    2476 m_source->Release();
    +
    2477 }
    +
    2478
    +
    2479 virtual _Success_(return != 0 || length == 0) size_t read(
    +
    2480 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
    +
    2481 {
    +
    2482 _Assume_(data || !length);
    +
    2483 for (size_t to_read = length;;) {
    +
    2484 HRESULT hr;
    +
    2485 ULONG num_read = 0;
    +
    2486 __try { hr = m_source->Read(data, (ULONG)std::min<size_t>(to_read, ULONG_MAX), &num_read); }
    +
    2487 __except (EXCEPTION_EXECUTE_HANDLER) { hr = E_FAIL; }
    +
    2488 if (FAILED(hr)) _Unlikely_ {
    +
    2489 m_state = to_read < length ? state_t::ok : state_t::fail;
    +
    2490 return length - to_read;
    +
    2491 }
    +
    2492 to_read -= num_read;
    +
    2493 if (hr == S_FALSE) _Unlikely_ {
    +
    2494 m_state = to_read < length || !length ? state_t::ok : state_t::eof;
    +
    2495 return length - to_read;
    +
    2496 }
    +
    2497 if (!to_read) {
    +
    2498 m_state = state_t::ok;
    +
    2499 return length;
    +
    2500 }
    +
    2501 reinterpret_cast<uint8_t*&>(data) += num_read;
    +
    2502 }
    +
    2503 }
    +
    2504
    +
    2505 virtual _Success_(return != 0) size_t write(
    +
    2506 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
    +
    2507 {
    +
    2508 _Assume_(data || !length);
    +
    2509 for (size_t to_write = length;;) {
    +
    2510 HRESULT hr;
    +
    2511 ULONG num_written = 0;
    +
    2512 __try { hr = m_source->Write(data, static_cast<ULONG>(std::min<size_t>(to_write, ULONG_MAX)), &num_written); }
    +
    2513 __except (EXCEPTION_EXECUTE_HANDLER) { hr = E_FAIL; }
    +
    2514 // In abscence of documentation whether num_written gets set when FAILED(hr) (i.e. partially succesful writes),
    +
    2515 // assume write failed completely.
    +
    2516 if (FAILED(hr)) _Unlikely_ {
    +
    2517 m_state = state_t::fail;
    +
    2518 return length - to_write;
    +
    2519 }
    +
    2520 to_write -= num_written;
    +
    2521 if (!to_write) {
    +
    2522 m_state = state_t::ok;
    +
    2523 return length;
    +
    2524 }
    +
    2525 reinterpret_cast<const uint8_t*&>(data) += num_written;
    +
    2526 }
    +
    2527 }
    +
    2528
    +
    2529 protected:
    +
    2530 ISequentialStream* m_source;
    +
    2531 };
    +
    2532
    +
    2536 class asp : public basic
    +
    2537 {
    +
    2538 public:
    +
    2539 asp(_In_opt_ IRequest* request, _In_opt_ IResponse* response) :
    +
    2540 m_request(request),
    +
    2541 m_response(response)
    +
    2542 {
    +
    2543 if (m_request)
    +
    2544 m_request->AddRef();
    +
    2545 if (m_response)
    +
    2546 m_response->AddRef();
    +
    2547 }
    +
    2548
    +
    2549 virtual ~asp()
    +
    2550 {
    +
    2551 if (m_request)
    +
    2552 m_request->Release();
    +
    2553 if (m_response)
    +
    2554 m_response->Release();
    +
    2555 }
    +
    2556
    +
    2557 virtual _Success_(return != 0 || length == 0) size_t read(
    +
    2558 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
    +
    2559 {
    +
    2560 _Assume_(data || !length);
    +
    2561 if (!m_request) _Unlikely_ {
    +
    2562 m_state = state_t::fail;
    +
    2563 return 0;
    +
    2564 }
    +
    2565 for (size_t to_read = length;;) {
    +
    2566 VARIANT var_amount, var_data;
    +
    2567 V_VT(&var_amount) = VT_I4;
    +
    2568 V_I4(&var_amount) = (LONG)std::min<size_t>(to_read, LONG_MAX);
    +
    2569 V_VT(&var_data) = VT_EMPTY;
    +
    2570 HRESULT hr = [&]() {
    +
    2571 __try { return m_request->BinaryRead(&var_amount, &var_data); }
    +
    2572 __except (EXCEPTION_EXECUTE_HANDLER) { return E_FAIL; }
    +
    2573 }();
    +
    2574 if (FAILED(hr)) _Unlikely_ {
    +
    2575 m_state = to_read < length ? state_t::ok : state_t::fail;
    +
    2576 return length - to_read;
    +
    2577 }
    +
    2578 _Assume_(V_VT(&var_amount) == VT_I4);
    +
    2579 _Assume_(V_VT(&var_data) == (VT_ARRAY | VT_UI1));
    +
    2580 std::unique_ptr<SAFEARRAY, SafeArrayDestroy_delete> sa(V_ARRAY(&var_data));
    +
    2581 if (!V_I4(&var_amount)) _Unlikely_ {
    +
    2582 m_state = to_read < length || !length ? state_t::ok : state_t::eof;
    +
    2583 return length - to_read;
    +
    2584 }
    +
    2585 safearray_accessor<uint8_t> a(sa.get());
    +
    2586 memcpy(data, a.data(), V_I4(&var_amount));
    +
    2587 to_read -= V_I4(&var_amount);
    +
    2588 if (!to_read) {
    +
    2589 m_state = state_t::ok;
    +
    2590 return length;
    +
    2591 }
    +
    2592 reinterpret_cast<uint8_t*&>(data) += V_I4(&var_amount);
    +
    2593 }
    +
    2594 }
    +
    2595
    +
    2596 virtual _Success_(return != 0) size_t write(
    +
    2597 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
    +
    2598 {
    +
    2599 if (!m_response) {
    +
    2600 m_state = state_t::fail;
    +
    2601 return 0;
    +
    2602 }
    +
    2603 for (size_t to_write = length;;) {
    +
    2604 UINT num_written = static_cast<UINT>(std::min<size_t>(to_write, UINT_MAX));
    +
    2605 std::unique_ptr<OLECHAR, SysFreeString_delete> bstr_data(SysAllocStringByteLen(reinterpret_cast<LPCSTR>(data), num_written));
    +
    2606 VARIANT var_data;
    +
    2607 V_VT(&var_data) = VT_BSTR;
    +
    2608 V_BSTR(&var_data) = bstr_data.get();
    +
    2609 HRESULT hr = [&]() {
    +
    2610 __try { return m_response->BinaryWrite(var_data); }
    +
    2611 __except (EXCEPTION_EXECUTE_HANDLER) { return E_FAIL; }
    +
    2612 }();
    +
    2613 if (FAILED(hr)) _Unlikely_ {
    +
    2614 m_state = state_t::fail;
    +
    2615 return length - to_write;
    +
    2616 }
    +
    2617 to_write -= num_written;
    +
    2618 if (!to_write) {
    +
    2619 m_state = state_t::ok;
    +
    2620 return length;
    +
    2621 }
    +
    2622 reinterpret_cast<const uint8_t*&>(data) += num_written;
    +
    2623 }
    +
    2624 }
    +
    2625
    +
    2626 virtual void close()
    +
    2627 {
    +
    2628 if (m_response) {
    +
    2629 __try { m_response->End(); }
    +
    2630 __except (EXCEPTION_EXECUTE_HANDLER) {}
    +
    2631 }
    +
    2632 m_state = state_t::ok;
    +
    2633 }
    +
    2634
    +
    2635 virtual void flush()
    +
    2636 {
    +
    2637 if (m_response) {
    +
    2638 HRESULT hr;
    +
    2639 __try { hr = m_response->Flush(); }
    +
    2640 __except (EXCEPTION_EXECUTE_HANDLER) { hr = E_FAIL; }
    +
    2641 m_state = SUCCEEDED(hr) ? state_t::ok : state_t::fail;
    +
    2642 }
    +
    2643 }
    +
    2644
    +
    2645 protected:
    +
    2646 IRequest* m_request;
    +
    2647 IResponse* m_response;
    +
    2648 };
    +
    2649#endif
    +
    2650
    +
    2654 enum mode_t
    +
    2655 {
    +
    2656 mode_for_reading = 1 << 0,
    +
    2657 mode_for_writing = 1 << 1,
    +
    2658 mode_for_chmod = 1 << 2,
    +
    2659
    +
    2660 mode_open_existing = 0 << 3,
    +
    2661 mode_truncate_existing = 1 << 3,
    +
    2662 mode_preserve_existing = 2 << 3,
    +
    2663 mode_create_new = 3 << 3,
    +
    2664 mode_create = 4 << 3,
    +
    2665 mode_disposition_mask = 7 << 3,
    +
    2666
    +
    2667 mode_append = 1 << 6,
    +
    2668 mode_text = 0,
    +
    2669 mode_binary = 1 << 7,
    +
    2670
    +
    2671 share_none = 0,
    +
    2672 share_reading = 1 << 8,
    +
    2673 share_writing = 1 << 9,
    +
    2674 share_deleting = 1 << 10,
    +
    2675 share_all = share_reading | share_writing | share_deleting, // Allow others all operations on our file
    +
    2676
    +
    2677 inherit_handle = 1 << 11,
    +
    2678
    +
    2679 hint_write_thru = 1 << 12,
    +
    2680 hint_no_buffering = 1 << 13,
    +
    2681 hint_random_access = 1 << 14,
    +
    2682 hint_sequential_access = 1 << 15,
    +
    2683 };
    +
    2684
    +
    2685#pragma warning(push)
    +
    2686#pragma warning(disable: 4250)
    +
    +
    2690 class file : virtual public basic_file, virtual public basic_sys
    +
    2691 {
    +
    2692 public:
    +
    2693 file(_In_opt_ sys_handle h = invalid_handle, _In_ state_t state = state_t::ok) : basic_sys(h, state) {}
    +
    2694
    +
    +
    2701 file(_In_z_ const schar_t* filename, _In_ int mode)
    +
    2702 {
    +
    2703 open(filename, mode);
    +
    2704 }
    +
    +
    2705
    +
    2712 inline file(_In_ const stdex::sstring& filename, _In_ int mode) : file(filename.c_str(), mode) {}
    +
    2713
    +
    +
    2720 void open(_In_z_ const schar_t* filename, _In_ int mode)
    +
    2721 {
    +
    2722 if (m_h != invalid_handle)
    +
    2723 close();
    +
    2724
    +
    2725#ifdef _WIN32
    +
    2726 DWORD dwDesiredAccess = 0;
    +
    2727 if (mode & mode_for_reading) dwDesiredAccess |= GENERIC_READ;
    +
    2728 if (mode & mode_for_writing) dwDesiredAccess |= GENERIC_WRITE;
    +
    2729 if (mode & mode_for_chmod) dwDesiredAccess |= FILE_WRITE_ATTRIBUTES;
    +
    2730
    +
    2731 DWORD dwShareMode = 0;
    +
    2732 if (mode & share_reading) dwShareMode |= FILE_SHARE_READ;
    +
    2733 if (mode & share_writing) dwShareMode |= FILE_SHARE_WRITE;
    +
    2734 if (mode & share_deleting) dwShareMode |= FILE_SHARE_DELETE;
    +
    2735
    +
    2736 SECURITY_ATTRIBUTES sa = { sizeof(SECURITY_ATTRIBUTES) };
    +
    2737 sa.bInheritHandle = mode & inherit_handle ? true : false;
    +
    2738
    +
    2739 DWORD dwCreationDisposition;
    +
    2740 switch (mode & mode_disposition_mask) {
    +
    2741 case mode_open_existing: dwCreationDisposition = OPEN_EXISTING; break;
    +
    2742 case mode_truncate_existing: dwCreationDisposition = TRUNCATE_EXISTING; break;
    +
    2743 case mode_preserve_existing: dwCreationDisposition = OPEN_ALWAYS; break;
    +
    2744 case mode_create_new: dwCreationDisposition = CREATE_NEW; break;
    +
    2745 case mode_create: dwCreationDisposition = CREATE_ALWAYS; break;
    +
    2746 default: throw std::invalid_argument("invalid mode");
    +
    2747 }
    +
    2748
    +
    2749 DWORD dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL;
    +
    2750 if (mode & hint_write_thru) dwFlagsAndAttributes |= FILE_FLAG_WRITE_THROUGH;
    +
    2751 if (mode & hint_no_buffering) dwFlagsAndAttributes |= FILE_FLAG_NO_BUFFERING;
    +
    2752 if (mode & hint_random_access) dwFlagsAndAttributes |= FILE_FLAG_RANDOM_ACCESS;
    +
    2753 if (mode & hint_sequential_access) dwFlagsAndAttributes |= FILE_FLAG_SEQUENTIAL_SCAN;
    +
    2754
    +
    2755 m_h = CreateFile(filename, dwDesiredAccess, dwShareMode, &sa, dwCreationDisposition, dwFlagsAndAttributes, NULL);
    +
    2756#else
    +
    2757 int flags = 0;
    +
    2758 switch (mode & (mode_for_reading | mode_for_writing)) {
    +
    2759 case mode_for_reading: flags |= O_RDONLY; break;
    +
    2760 case mode_for_writing: flags |= O_WRONLY; break;
    +
    2761 case mode_for_reading | mode_for_writing: flags |= O_RDWR; break;
    +
    2762 }
    +
    2763 switch (mode & mode_disposition_mask) {
    +
    2764 case mode_open_existing: break;
    +
    2765 case mode_truncate_existing: flags |= O_TRUNC; break;
    +
    2766 case mode_preserve_existing: flags |= O_CREAT; break;
    +
    2767 case mode_create_new: flags |= O_CREAT | O_EXCL; break;
    +
    2768 case mode_create: flags |= O_CREAT | O_TRUNC; break;
    +
    2769 default: throw std::invalid_argument("invalid mode");
    +
    2770 }
    +
    2771 if (mode & hint_write_thru) flags |= O_DSYNC;
    +
    2772#ifndef __APPLE__
    +
    2773 if (mode & hint_no_buffering) flags |= O_RSYNC;
    +
    2774#endif
    +
    2775
    +
    2776 m_h = ::open(filename, flags, DEFFILEMODE);
    +
    2777#endif
    +
    2778 if (m_h != invalid_handle) {
    +
    2779 m_state = state_t::ok;
    +
    2780 if (mode & mode_append)
    +
    2781 seek(0, seek_t::end);
    +
    2782 }
    +
    2783 else
    +
    2784 m_state = state_t::fail;
    +
    2785 }
    +
    +
    2786
    +
    +
    2793 inline void open(_In_ const stdex::sstring& filename, _In_ int mode)
    +
    2794 {
    +
    2795 open(filename.c_str(), mode);
    +
    2796 }
    +
    +
    2797
    +
    +
    2798 virtual fpos_t seek(_In_ foff_t offset, _In_ seek_t how = seek_t::beg)
    +
    2799 {
    +
    2800#ifdef _WIN32
    +
    2801 LARGE_INTEGER li;
    +
    2802 li.QuadPart = offset;
    +
    2803 li.LowPart = SetFilePointer(m_h, li.LowPart, &li.HighPart, static_cast<DWORD>(how));
    +
    2804 if (li.LowPart != 0xFFFFFFFF || GetLastError() == NO_ERROR) {
    +
    2805 m_state = state_t::ok;
    +
    2806 return li.QuadPart;
    +
    2807 }
    +
    2808#else
    +
    2809 off64_t result = lseek64(m_h, offset, static_cast<int>(how));
    +
    2810 if (result >= 0) {
    +
    2811 m_state = state_t::ok;
    +
    2812 return result;
    +
    2813 }
    +
    2814#endif
    +
    2815 m_state = state_t::fail;
    +
    2816 return fpos_max;
    +
    2817 }
    +
    +
    2818
    +
    +
    2819 virtual fpos_t tell() const
    +
    2820 {
    +
    2821 if (m_h != invalid_handle) {
    +
    2822#ifdef _WIN32
    +
    2823 LARGE_INTEGER li;
    +
    2824 li.QuadPart = 0;
    +
    2825 li.LowPart = SetFilePointer(m_h, 0, &li.HighPart, FILE_CURRENT);
    +
    2826 if (li.LowPart != 0xFFFFFFFF || GetLastError() == NO_ERROR)
    +
    2827 return li.QuadPart;
    +
    2828#else
    +
    2829 off64_t result = lseek64(m_h, 0, SEEK_CUR);
    +
    2830 if (result >= 0)
    +
    2831 return result;
    +
    2832#endif
    +
    2833 }
    +
    2834 return fpos_max;
    +
    2835 }
    +
    +
    2836
    +
    +
    2837 virtual void lock(_In_ fpos_t offset, _In_ fsize_t length)
    +
    2838 {
    +
    2839#ifdef _WIN32
    +
    2840 LARGE_INTEGER liOffset;
    +
    2841 LARGE_INTEGER liSize;
    +
    2842 liOffset.QuadPart = offset;
    +
    2843 liSize.QuadPart = length;
    +
    2844 if (LockFile(m_h, liOffset.LowPart, liOffset.HighPart, liSize.LowPart, liSize.HighPart)) {
    +
    2845 m_state = state_t::ok;
    +
    2846 return;
    +
    2847 }
    +
    2848#else
    +
    2849 off64_t orig = lseek64(m_h, 0, SEEK_CUR);
    +
    2850 if (orig >= 0) {
    +
    2851 m_state = lseek64(m_h, offset, SEEK_SET) >= 0 && lockf64(m_h, F_LOCK, length) >= 0 ? state_t::ok : state_t::fail;
    +
    2852 lseek64(m_h, orig, SEEK_SET);
    +
    2853 m_state = state_t::ok;
    +
    2854 return;
    +
    2855 }
    +
    2856#endif
    +
    2857 m_state = state_t::fail;
    +
    2858 }
    +
    +
    2859
    +
    +
    2860 virtual void unlock(_In_ fpos_t offset, _In_ fsize_t length)
    +
    2861 {
    +
    2862#ifdef _WIN32
    +
    2863 LARGE_INTEGER liOffset;
    +
    2864 LARGE_INTEGER liSize;
    +
    2865 liOffset.QuadPart = offset;
    +
    2866 liSize.QuadPart = length;
    +
    2867 if (UnlockFile(m_h, liOffset.LowPart, liOffset.HighPart, liSize.LowPart, liSize.HighPart)) {
    +
    2868 m_state = state_t::ok;
    +
    2869 return;
    +
    2870 }
    +
    2871#else
    +
    2872 off64_t orig = lseek64(m_h, 0, SEEK_CUR);
    +
    2873 if (orig >= 0) {
    +
    2874 if (lseek64(m_h, offset, SEEK_SET) >= 0 && lockf64(m_h, F_ULOCK, length) >= 0) {
    +
    2875 lseek64(m_h, orig, SEEK_SET);
    +
    2876 m_state = state_t::ok;
    +
    2877 return;
    +
    2878 }
    +
    2879 lseek64(m_h, orig, SEEK_SET);
    +
    2880 }
    +
    2881#endif
    +
    2882 m_state = state_t::fail;
    +
    2883 }
    +
    +
    2884
    +
    +
    2885 virtual fsize_t size()
    +
    2886 {
    +
    2887#ifdef _WIN32
    +
    2888 LARGE_INTEGER li;
    +
    2889 li.LowPart = GetFileSize(m_h, (LPDWORD)&li.HighPart);
    +
    2890 if (li.LowPart == 0xFFFFFFFF && GetLastError() != NO_ERROR)
    +
    2891 li.QuadPart = -1;
    +
    2892 return li.QuadPart;
    +
    2893#else
    +
    2894 off64_t length = -1, orig = lseek64(m_h, 0, SEEK_CUR);
    +
    2895 if (orig >= 0) {
    +
    2896 length = lseek64(m_h, 0, SEEK_END);
    +
    2897 lseek64(m_h, orig, SEEK_SET);
    +
    2898 }
    +
    2899 return length;
    +
    2900#endif
    +
    2901 }
    +
    +
    2902
    +
    +
    2903 virtual void truncate()
    +
    2904 {
    +
    2905#ifdef _WIN32
    +
    2906 if (SetEndOfFile(m_h)) {
    +
    2907 m_state = state_t::ok;
    +
    2908 return;
    +
    2909 }
    +
    2910#else
    +
    2911 off64_t length = lseek64(m_h, 0, SEEK_CUR);
    +
    2912 if (length >= 0 && ftruncate64(m_h, length) >= 0) {
    +
    2913 m_state = state_t::ok;
    +
    2914 return;
    +
    2915 }
    +
    2916#endif
    +
    2917 m_state = state_t::fail;
    +
    2918 }
    +
    +
    2919
    +
    2920#ifdef _WIN32
    +
    2921 static inline time_point ft2tp(_In_ const FILETIME& ft)
    +
    2922 {
    +
    2923#if _HAS_CXX20
    +
    2924 uint64_t t = (static_cast<int64_t>(ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
    +
    2925#else
    +
    2926 uint64_t t = ((static_cast<int64_t>(ft.dwHighDateTime) << 32) | ft.dwLowDateTime) - 116444736000000000ll;
    +
    2927#endif
    +
    2928 return time_point(time_point::duration(t));
    +
    2929 }
    +
    2930
    +
    2931 static inline void tp2ft(_In_ time_point tp, _Out_ FILETIME& ft)
    +
    2932 {
    +
    2933#if _HAS_CXX20
    +
    2934 uint64_t t = tp.time_since_epoch().count();
    +
    2935#else
    +
    2936 uint64_t t = tp.time_since_epoch().count() + 116444736000000000ll;
    +
    2937#endif
    +
    2938 ft.dwHighDateTime = static_cast<DWORD>((t >> 32) & 0xffffffff);
    +
    2939 ft.dwLowDateTime = static_cast<DWORD>(t & 0xffffffff);
    +
    2940 }
    +
    2941#endif
    +
    2942
    +
    +
    2943 virtual time_point ctime() const
    +
    2944 {
    +
    2945#ifdef _WIN32
    +
    2946 FILETIME ft;
    +
    2947 if (GetFileTime(m_h, &ft, nullptr, nullptr))
    +
    2948 return ft2tp(ft);
    +
    2949#endif
    +
    2950 return time_point::min();
    +
    2951 }
    +
    +
    2952
    +
    +
    2953 virtual time_point atime() const
    +
    2954 {
    +
    2955#ifdef _WIN32
    +
    2956 FILETIME ft;
    +
    2957 if (GetFileTime(m_h, nullptr, &ft, nullptr))
    +
    2958 return ft2tp(ft);
    +
    2959#else
    +
    2960 struct stat buf;
    +
    2961 if (fstat(m_h, &buf) >= 0)
    +
    2962 return clock::from_time_t(buf.st_atime);
    +
    2963#endif
    +
    2964 return time_point::min();
    +
    2965 }
    +
    +
    2966
    +
    +
    2967 virtual time_point mtime() const
    +
    2968 {
    +
    2969#ifdef _WIN32
    +
    2970 FILETIME ft;
    +
    2971 if (GetFileTime(m_h, nullptr, nullptr, &ft))
    +
    2972 return ft2tp(ft);
    +
    2973#else
    +
    2974 struct stat buf;
    +
    2975 if (fstat(m_h, &buf) >= 0)
    +
    2976 return clock::from_time_t(buf.st_mtime);
    +
    2977#endif
    +
    2978 return time_point::min();
    +
    2979 }
    +
    +
    2980
    +
    +
    2981 virtual void set_ctime(time_point date)
    +
    2982 {
    +
    2983 _Assume_(m_h != invalid_handle);
    +
    2984#ifdef _WIN32
    +
    2985 FILETIME ft;
    +
    2986 tp2ft(date, ft);
    +
    2987 if (SetFileTime(m_h, &ft, nullptr, nullptr))
    +
    2988 return;
    +
    2989 throw std::system_error(GetLastError(), std::system_category(), "SetFileTime failed");
    +
    2990#else
    +
    2991 throw std::runtime_error("not supported");
    +
    2992#endif
    +
    2993 }
    +
    +
    2994
    +
    +
    2995 virtual void set_atime(time_point date)
    +
    2996 {
    +
    2997 _Assume_(m_h != invalid_handle);
    +
    2998#ifdef _WIN32
    +
    2999 FILETIME ft;
    +
    3000 tp2ft(date, ft);
    +
    3001 if (SetFileTime(m_h, nullptr, &ft, nullptr))
    +
    3002 return;
    +
    3003 throw std::system_error(GetLastError(), std::system_category(), "SetFileTime failed");
    +
    3004#else
    +
    3005 struct timespec ts[2] = {
    +
    3006 { date.time_since_epoch().count(), 0 },
    +
    3007 { 0, UTIME_OMIT },
    +
    3008 };
    +
    3009 if (futimens(m_h, ts) >= 0)
    +
    3010 return;
    +
    3011 throw std::system_error(errno, std::system_category(), "futimens failed");
    +
    3012#endif
    +
    3013 }
    +
    +
    3014
    +
    +
    3015 virtual void set_mtime(time_point date)
    +
    3016 {
    +
    3017#ifdef _WIN32
    +
    3018 FILETIME ft;
    +
    3019 tp2ft(date, ft);
    +
    3020 if (SetFileTime(m_h, nullptr, nullptr, &ft))
    +
    3021 return;
    +
    3022 throw std::system_error(GetLastError(), std::system_category(), "SetFileTime failed");
    +
    3023#else
    +
    3024 struct timespec ts[2] = {
    +
    3025 { 0, UTIME_OMIT },
    +
    3026 { date.time_since_epoch().count(), 0 },
    +
    3027 };
    +
    3028 if (futimens(m_h, ts) >= 0)
    +
    3029 return;
    +
    3030 throw std::system_error(errno, std::system_category(), "futimens failed");
    +
    3031#endif
    +
    3032 }
    +
    +
    3033
    +
    +
    3039 static bool exists(_In_z_ const stdex::schar_t* filename)
    +
    3040 {
    +
    3041#ifdef _WIN32
    +
    3042 return GetFileAttributes(filename) != INVALID_FILE_ATTRIBUTES;
    +
    3043#else
    +
    3044 struct stat s;
    +
    3045 return stat(filename, &s) == 0;
    +
    3046#endif
    +
    3047 }
    +
    +
    3048
    +
    +
    3054 static inline bool exists(_In_ const stdex::sstring& filename)
    +
    3055 {
    +
    3056 return exists(filename.c_str());
    +
    3057 }
    +
    +
    3058
    +
    +
    3066 static bool readonly(_In_z_ const stdex::schar_t* filename)
    +
    3067 {
    +
    3068#ifdef _WIN32
    +
    3069 DWORD dwAttr = GetFileAttributes(filename);
    +
    3070 return dwAttr != INVALID_FILE_ATTRIBUTES && (dwAttr & FILE_ATTRIBUTE_READONLY) != 0;
    +
    3071#else
    +
    3072 struct stat s;
    +
    3073 return stat(filename, &s) == 0 && (s.st_mode & (S_IWUSR|S_IWGRP|S_IWOTH)) == 0;
    +
    3074#endif
    +
    3075 }
    +
    +
    3076
    +
    +
    3084 static inline bool readonly(_In_ const stdex::sstring& filename)
    +
    3085 {
    +
    3086 return readonly(filename.c_str());
    +
    3087 }
    +
    +
    3088 };
    +
    +
    3089#pragma warning(pop)
    +
    3090
    +
    +
    3094 class cached_file : public cache
    +
    3095 {
    +
    3096 public:
    +
    3097 cached_file(_In_opt_ sys_handle h = invalid_handle, _In_ state_t state = state_t::ok, _In_ size_t cache_size = default_cache_size) :
    +
    3098 cache(cache_size),
    +
    3099 m_source(h, state)
    +
    3100 {
    +
    3101 init(m_source);
    +
    3102 }
    +
    3103
    +
    +
    3111 cached_file(_In_z_ const schar_t* filename, _In_ int mode, _In_ size_t cache_size = default_cache_size) :
    +
    3112 cache(cache_size),
    +
    3113 m_source(filename, mode & mode_for_writing ? mode | mode_for_reading : mode)
    +
    3114 {
    +
    3115 init(m_source);
    +
    3116 }
    +
    +
    3117
    +
    3125 inline cached_file(_In_ const stdex::sstring& filename, _In_ int mode, _In_ size_t cache_size = default_cache_size) : cached_file(filename.c_str(), mode, cache_size) {}
    +
    3126
    +
    3127 virtual ~cached_file()
    +
    3128 {
    +
    3129 done();
    +
    3130 }
    +
    3131
    +
    +
    3138 void open(_In_z_ const schar_t* filename, _In_ int mode)
    +
    3139 {
    +
    3140 invalidate_cache();
    +
    3141 if (!ok()) _Unlikely_{
    +
    3142 m_state = state_t::fail;
    +
    3143 return;
    +
    3144 }
    +
    3145 m_source.open(filename, mode & mode_for_writing ? mode | mode_for_reading : mode);
    +
    3146 if (m_source.ok()) {
    +
    3147 init();
    +
    3148 return;
    +
    3149 }
    +
    3150 m_state = state_t::fail;
    +
    3151 }
    +
    +
    3152
    +
    +
    3159 inline void open(_In_ const stdex::sstring& filename, _In_ int mode)
    +
    3160 {
    +
    3161 open(filename.c_str(), mode);
    +
    3162 }
    +
    +
    3163
    +
    3164 protected:
    +
    3165 file m_source;
    +
    3166 };
    +
    +
    3167
    +
    + +
    3172 {
    +
    3173 public:
    +
    3174 memory_file(_In_ state_t state = state_t::ok) :
    +
    3175 basic(state),
    +
    3176 m_data(nullptr),
    +
    3177 m_offset(0),
    +
    3178 m_size(0),
    +
    3179 m_reserved(0),
    +
    3180 m_manage(true)
    +
    3181 {
    +
    3182#if SET_FILE_OP_TIMES
    +
    3183 m_ctime = m_atime = m_mtime = time_point::now();
    +
    3184#endif
    +
    3185 }
    +
    3186
    +
    +
    3193 memory_file(_In_ size_t size, _In_ state_t state = state_t::ok) :
    +
    3194 basic(state),
    +
    3195 m_data(reinterpret_cast<uint8_t*>(malloc(size))),
    +
    3196 m_offset(0),
    +
    3197 m_size(0),
    + +
    3199 m_manage(true)
    +
    3200 {
    +
    3201 if (!m_data)
    +
    3202 throw std::bad_alloc();
    +
    3203#if SET_FILE_OP_TIMES
    +
    3204 m_ctime = m_atime = m_mtime = time_point::now();
    +
    3205#endif
    +
    3206 }
    +
    +
    3207
    +
    +
    3217 memory_file(_Inout_ void* data, _In_ size_t size, _In_ size_t reserved, _In_ bool manage = false, _In_ state_t state = state_t::ok) :
    +
    3218 basic(state),
    +
    3219 m_data(reinterpret_cast<uint8_t*>(data)),
    +
    3220 m_offset(0),
    +
    3221 m_size(size),
    +
    3222 m_reserved(reserved),
    +
    3223 m_manage(manage)
    +
    3224 {
    +
    3225 _Assume_(data || !size);
    +
    3226 _Assume_(reserved >= size);
    +
    3227#if SET_FILE_OP_TIMES
    +
    3228 m_ctime = m_atime = m_mtime = time_point::now();
    +
    3229#endif
    +
    3230 }
    +
    +
    3231
    +
    +
    3240 memory_file(_Inout_ void* data, _In_ size_t size, _In_ bool manage = false, _In_ state_t state = state_t::ok) :
    +
    3241 memory_file(data, size, size, manage, state)
    +
    3242 {}
    +
    +
    3243
    +
    +
    3250 memory_file(_In_z_ const schar_t* filename, _In_ int mode) : memory_file()
    +
    3251 {
    +
    3252 load(filename, mode);
    +
    3253 }
    +
    +
    3254
    +
    3261 inline memory_file(_In_ const stdex::sstring& filename, _In_ int mode) : memory_file(filename.c_str(), mode) {}
    +
    3262
    +
    3263 virtual ~memory_file()
    +
    3264 {
    +
    3265 if (m_manage && m_data)
    +
    3266 free(m_data);
    +
    3267 }
    +
    3268
    +
    +
    3275 void reserve(_In_ size_t required, _In_ bool tight = false) noexcept
    +
    3276 {
    +
    3277 if (required <= m_reserved && (!tight || required >= m_reserved)) {
    +
    3278 m_state = state_t::ok;
    +
    3279 return;
    +
    3280 }
    +
    3281 if (!m_manage) {
    +
    3282 m_state = state_t::fail;
    +
    3283 return;
    +
    3284 }
    +
    3285 size_t reserved = tight ? required : ((required + required / 4 + (default_block_size - 1)) / default_block_size) * default_block_size;
    +
    3286 auto data = reinterpret_cast<uint8_t*>(realloc(m_data, reserved));
    +
    3287 if (!data && reserved) _Unlikely_ {
    +
    3288 m_state = state_t::fail;
    +
    3289 return;
    +
    3290 }
    +
    3291 m_data = data;
    +
    3292 if (reserved < m_size)
    +
    3293 m_size = reserved;
    +
    3294 m_reserved = reserved;
    +
    3295 m_state = state_t::ok;
    +
    3296 }
    +
    +
    3297
    +
    +
    3304 void load(_In_z_ const schar_t* filename, _In_ int mode)
    +
    3305 {
    +
    3306 file f(filename, (mode & ~hint_random_access) | mode_for_reading | hint_sequential_access);
    +
    3307 if (!f.ok()) {
    +
    3308 m_state = state_t::fail;
    +
    3309 return;
    +
    3310 }
    +
    3311 fsize_t size = f.size();
    +
    3312 if (size > SIZE_MAX) {
    +
    3313 m_state = state_t::fail;
    +
    3314 return;
    +
    3315 }
    +
    3316 reserve(static_cast<size_t>(size), true);
    +
    3317 if (!ok()) _Unlikely_ {
    +
    3318 return;
    +
    3319 }
    +
    3320 m_offset = m_size = 0;
    +
    3321 write_stream(f);
    +
    3322 if (ok())
    +
    3323 m_offset = 0;
    +
    3324#if SET_FILE_OP_TIMES
    +
    3325 m_ctime = f.ctime();
    +
    3326 m_atime = f.atime();
    +
    3327 m_mtime = f.mtime();
    +
    3328#endif
    +
    3329 }
    +
    +
    3330
    +
    +
    3337 inline void load(_In_ const stdex::sstring& filename, _In_ int mode)
    +
    3338 {
    +
    3339 load(filename.c_str(), mode);
    +
    3340 }
    +
    +
    3341
    +
    +
    3348 void save(_In_z_ const schar_t* filename, _In_ int mode)
    +
    3349 {
    +
    3350 file f(filename, (mode & ~hint_random_access) | mode_for_writing | hint_sequential_access);
    +
    3351 if (!f.ok()) {
    +
    3352 m_state = state_t::fail;
    +
    3353 return;
    +
    3354 }
    +
    3355 f.write(m_data, m_size);
    +
    3356 if (!f.ok()) {
    +
    3357 m_state = state_t::fail;
    +
    3358 return;
    +
    3359 }
    +
    3360 f.truncate();
    +
    3361#if SET_FILE_OP_TIMES
    +
    3362 f.set_ctime(m_ctime);
    +
    3363 f.set_atime(m_atime);
    +
    3364 f.set_mtime(m_mtime);
    +
    3365#endif
    +
    3366 }
    +
    +
    3367
    +
    +
    3374 inline void save(_In_ const stdex::sstring& filename, _In_ int mode)
    +
    3375 {
    +
    3376 save(filename.c_str(), mode);
    +
    3377 }
    +
    +
    3378
    +
    3382 inline const void* data() const { return m_data; }
    +
    3383
    +
    +
    3384 virtual _Success_(return != 0 || length == 0) size_t read(
    +
    3385 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
    +
    3386 {
    +
    3387 _Assume_(data || !length);
    +
    3388#if SET_FILE_OP_TIMES
    +
    3389 m_atime = time_point::now();
    +
    3390#endif
    +
    3391 size_t available = m_size - m_offset;
    +
    3392 if (length <= available) {
    +
    3393 memcpy(data, m_data + m_offset, length);
    +
    3394 m_offset += length;
    +
    3395 m_state = state_t::ok;
    +
    3396 return length;
    +
    3397 }
    +
    3398 if (length && !available) {
    +
    3399 m_state = state_t::eof;
    +
    3400 return 0;
    +
    3401 }
    +
    3402 memcpy(data, m_data + m_offset, available);
    +
    3403 m_offset += available;
    +
    3404 m_state = state_t::ok;
    +
    3405 return available;
    +
    3406 }
    +
    +
    3407
    +
    3422 template <class T>
    +
    +
    3423 inline memory_file& read_data(_Out_ T& data)
    +
    3424 {
    +
    3425#if SET_FILE_OP_TIMES
    +
    3426 m_atime = time_point::now();
    +
    3427#endif
    +
    3428 if (CHECK_STREAM_STATE && !ok()) _Unlikely_ {
    +
    3429 data = 0;
    +
    3430 return *this;
    +
    3431 }
    +
    3432 size_t end_offset = m_offset + sizeof(T);
    +
    3433 if (end_offset <= m_size) {
    +
    3434 data = LE2HE(*reinterpret_cast<T*>(m_data + m_offset));
    +
    3435 m_offset = end_offset;
    +
    3436#if !CHECK_STREAM_STATE
    +
    3437 m_state = state_t::ok;
    +
    3438#endif
    +
    3439 }
    +
    3440 else {
    +
    3441 data = 0;
    +
    3442 m_offset = m_size;
    +
    3443 m_state = state_t::eof;
    +
    3444 }
    +
    3445 return *this;
    +
    3446 }
    +
    +
    3447
    +
    3462 template<class _Elem, class _Traits = std::char_traits<_Elem>, class _Ax = std::allocator<_Elem>>
    +
    +
    3463 memory_file& read_str(_Inout_ std::basic_string<_Elem, _Traits, _Ax>&data)
    +
    3464 {
    +
    3465#if SET_FILE_OP_TIMES
    +
    3466 m_atime = time_point::now();
    +
    3467#endif
    +
    3468 if (CHECK_STREAM_STATE && !ok()) _Unlikely_ {
    +
    3469 data.clear();
    +
    3470 return *this;
    +
    3471 }
    +
    3472 size_t end_offset = m_offset + sizeof(uint32_t);
    +
    3473 if (end_offset <= m_size) {
    +
    3474 uint32_t num_chars = LE2HE(*reinterpret_cast<uint32_t*>(m_data + m_offset));
    +
    3475 m_offset = end_offset;
    +
    3476 end_offset = stdex::add(m_offset, stdex::mul(num_chars, sizeof(_Elem)));
    +
    3477 _Elem* start = reinterpret_cast<_Elem*>(m_data + m_offset);
    +
    3478 if (end_offset <= m_size) {
    +
    3479 data.assign(start, start + num_chars);
    +
    3480 m_offset = end_offset;
    +
    3481#if !CHECK_STREAM_STATE
    +
    3482 m_state = state_t::ok;
    +
    3483#endif
    +
    3484 return *this;
    +
    3485 }
    +
    3486 if (end_offset <= m_size)
    +
    3487 data.assign(start, reinterpret_cast<_Elem*>(m_data + m_size));
    +
    3488 }
    +
    3489 m_offset = m_size;
    +
    3490 m_state = state_t::eof;
    +
    3491 return *this;
    +
    3492 }
    +
    +
    3493
    +
    +
    3494 virtual _Success_(return != 0) size_t write(
    +
    3495 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
    +
    3496 {
    +
    3497 _Assume_(data || !length);
    +
    3498#if SET_FILE_OP_TIMES
    +
    3499 m_atime = m_mtime = time_point::now();
    +
    3500#endif
    +
    3501 size_t end_offset = m_offset + length;
    +
    3502 if (end_offset > m_reserved) {
    +
    3503 reserve(end_offset);
    +
    3504 if (!ok()) _Unlikely_
    +
    3505 return 0;
    +
    3506 }
    +
    3507 memcpy(m_data + m_offset, data, length);
    +
    3508 m_offset = end_offset;
    +
    3509 if (m_offset > m_size)
    +
    3510 m_size = m_offset;
    +
    3511 m_state = state_t::ok;
    +
    3512 return length;
    +
    3513 }
    +
    +
    3514
    +
    +
    3518 void write_byte(_In_ uint8_t byte, _In_ size_t amount = 1)
    +
    3519 {
    +
    3520#if SET_FILE_OP_TIMES
    +
    3521 m_atime = m_mtime = time_point::now();
    +
    3522#endif
    +
    3523 size_t end_offset = m_offset + amount;
    +
    3524 if (end_offset > m_reserved) {
    +
    3525 reserve(end_offset);
    +
    3526 if (!ok()) _Unlikely_
    +
    3527 return;
    +
    3528 }
    +
    3529 memset(m_data + m_offset, byte, amount);
    +
    3530 m_offset = end_offset;
    +
    3531 if (m_offset > m_size)
    +
    3532 m_size = m_offset;
    +
    3533 m_state = state_t::ok;
    +
    3534 }
    +
    +
    3535
    +
    3550 template <class T>
    +
    +
    3551 inline memory_file& write_data(const T data)
    +
    3552 {
    +
    3553#if SET_FILE_OP_TIMES
    +
    3554 m_atime = m_mtime = time_point::now();
    +
    3555#endif
    +
    3556 if (CHECK_STREAM_STATE && !ok()) _Unlikely_
    +
    3557 return *this;
    +
    3558 size_t end_offset = m_offset + sizeof(T);
    +
    3559 if (end_offset > m_reserved) {
    +
    3560 reserve(end_offset);
    +
    3561 if (!ok()) _Unlikely_
    +
    3562 return *this;
    +
    3563 }
    +
    3564 (*reinterpret_cast<T*>(m_data + m_offset)) = HE2LE(data);
    +
    3565 m_offset = end_offset;
    +
    3566 if (m_offset > m_size)
    +
    3567 m_size = m_offset;
    +
    3568#if !CHECK_STREAM_STATE
    +
    3569 m_state = state_t::ok;
    +
    3570#endif
    +
    3571 return *this;
    +
    3572 }
    +
    +
    3573
    +
    3588 template <class T>
    +
    +
    3589 inline memory_file& write_str(_In_z_ const T * data)
    +
    3590 {
    +
    3591#if SET_FILE_OP_TIMES
    +
    3592 m_atime = m_mtime = time_point::now();
    +
    3593#endif
    +
    3594 if (CHECK_STREAM_STATE && !ok()) _Unlikely_
    +
    3595 return *this;
    +
    3596 size_t num_chars = stdex::strlen(data);
    +
    3597 if (num_chars > UINT32_MAX)
    +
    3598 throw std::invalid_argument("string too long");
    +
    3599 size_t size_chars = num_chars * sizeof(T);
    +
    3600 size_t size = sizeof(uint32_t) + size_chars;
    +
    3601 size_t end_offset = m_offset + size;
    +
    3602 if (end_offset > m_reserved) {
    +
    3603 reserve(end_offset);
    +
    3604 if (!ok()) _Unlikely_
    +
    3605 return *this;
    +
    3606 }
    +
    3607 auto p = m_data + m_offset;
    +
    3608 *reinterpret_cast<uint32_t*>(p) = HE2LE((uint32_t)num_chars);
    +
    3609 memcpy(p + sizeof(uint32_t), data, size_chars);
    +
    3610 m_offset = end_offset;
    +
    3611 if (m_offset > m_size)
    +
    3612 m_size = m_offset;
    +
    3613#if !CHECK_STREAM_STATE
    +
    3614 m_state = state_t::ok;
    +
    3615#endif
    +
    3616 return *this;
    +
    3617 }
    +
    +
    3618
    +
    3633 template<class _Elem, class _Traits = std::char_traits<_Elem>, class _Ax = std::allocator<_Elem>>
    +
    +
    3634 inline memory_file& write_str(_In_ const std::basic_string<_Elem, _Traits, _Ax>& data)
    +
    3635 {
    +
    3636#if SET_FILE_OP_TIMES
    +
    3637 m_atime = m_mtime = time_point::now();
    +
    3638#endif
    +
    3639 if (CHECK_STREAM_STATE && !ok()) _Unlikely_
    +
    3640 return *this;
    +
    3641 size_t num_chars = data.size();
    +
    3642 if (num_chars > UINT32_MAX)
    +
    3643 throw std::invalid_argument("string too long");
    +
    3644 size_t size_chars = num_chars * sizeof(_Elem);
    +
    3645 size_t size = sizeof(uint32_t) + size_chars;
    +
    3646 size_t end_offset = m_offset + size;
    +
    3647 if (end_offset > m_reserved) {
    +
    3648 reserve(end_offset);
    +
    3649 if (!ok()) _Unlikely_
    +
    3650 return *this;
    +
    3651 }
    +
    3652 auto p = m_data + m_offset;
    +
    3653 *reinterpret_cast<uint32_t*>(p) = HE2LE((uint32_t)num_chars);
    +
    3654 memcpy(p + sizeof(uint32_t), data.data(), size_chars);
    +
    3655 m_offset = end_offset;
    +
    3656 if (m_offset > m_size)
    +
    3657 m_size = m_offset;
    +
    3658#if !CHECK_STREAM_STATE
    +
    3659 m_state = state_t::ok;
    +
    3660#endif
    +
    3661 return *this;
    +
    3662 }
    +
    +
    3663
    +
    +
    3669 size_t write_stream(_Inout_ basic & stream, _In_ size_t amount = SIZE_MAX)
    +
    3670 {
    +
    3671#if SET_FILE_OP_TIMES
    +
    3672 m_atime = m_mtime = time_point::now();
    +
    3673#endif
    +
    3674 size_t num_read, dst_offset = m_offset, dst_size = m_offset;
    +
    3675 size_t num_copied = 0, to_write = amount;
    +
    3676 m_state = state_t::ok;
    +
    3677 if (amount != SIZE_MAX) {
    +
    3678 dst_size = stdex::add(dst_size, amount);
    +
    3679 reserve(dst_size);
    +
    3680 if (!ok()) _Unlikely_
    +
    3681 return 0;
    +
    3682 while (to_write) {
    +
    3683 num_read = stream.read(m_data + dst_offset, to_write);
    +
    3684 dst_size = dst_offset += num_read;
    +
    3685 num_copied += num_read;
    +
    3686 to_write -= num_read;
    +
    3687 if (!stream.ok()) {
    +
    3688 if (stream.state() != state_t::eof)
    +
    3689 m_state = state_t::fail;
    +
    3690 break;
    +
    3691 }
    +
    3692 };
    +
    3693 }
    +
    3694 else {
    +
    3695 size_t block_size;
    +
    3696 while (to_write) {
    +
    3697 block_size = std::min(to_write, default_block_size);
    +
    3698 dst_size = stdex::add(dst_size, block_size);
    +
    3699 reserve(dst_size);
    +
    3700 if (!ok()) _Unlikely_
    +
    3701 break;
    +
    3702 num_read = stream.read(m_data + dst_offset, block_size);
    +
    3703 dst_size = dst_offset += num_read;
    +
    3704 num_copied += num_read;
    +
    3705 to_write -= num_read;
    +
    3706 if (!stream.ok()) {
    +
    3707 if (stream.state() != state_t::eof)
    +
    3708 m_state = state_t::fail;
    +
    3709 break;
    +
    3710 }
    +
    3711 };
    +
    3712 }
    +
    3713 m_offset = dst_offset;
    +
    3714 if (m_offset > m_size)
    +
    3715 m_size = m_offset;
    +
    3716 return num_copied;
    +
    3717 }
    +
    +
    3718
    +
    +
    3719 virtual void close()
    +
    3720 {
    +
    3721 if (m_manage && m_data)
    +
    3722 free(m_data);
    +
    3723 m_data = nullptr;
    +
    3724 m_manage = true;
    +
    3725 m_offset = 0;
    +
    3726 m_size = m_reserved = 0;
    +
    3727#if SET_FILE_OP_TIMES
    +
    3728 m_ctime = m_atime = m_mtime = time_point::min();
    +
    3729#endif
    +
    3730 m_state = state_t::ok;
    +
    3731 }
    +
    +
    3732
    +
    +
    3733 virtual fpos_t seek(_In_ foff_t offset, _In_ seek_t how = seek_t::beg)
    +
    3734 {
    +
    3735 fpos_t target;
    +
    3736 switch (how) {
    +
    3737 case seek_t::beg: target = offset; break;
    +
    3738 case seek_t::cur: target = static_cast<fpos_t>(m_offset) + offset; break;
    +
    3739 case seek_t::end: target = static_cast<fpos_t>(m_size) + offset; break;
    +
    3740 default: throw std::invalid_argument("unknown seek origin");
    +
    3741 }
    +
    3742 if (target <= SIZE_MAX) {
    +
    3743 m_state = state_t::ok;
    +
    3744 return m_offset = static_cast<size_t>(target);
    +
    3745 }
    +
    3746 m_state = state_t::fail;
    +
    3747 return fpos_max;
    +
    3748 }
    +
    +
    3749
    +
    +
    3750 virtual fpos_t tell() const
    +
    3751 {
    +
    3752 return m_offset;
    +
    3753 }
    +
    +
    3754
    +
    +
    3755 virtual fsize_t size()
    +
    3756 {
    +
    3757 return m_size;
    +
    3758 }
    +
    +
    3759
    +
    +
    3760 virtual void truncate()
    +
    3761 {
    +
    3762#if SET_FILE_OP_TIMES
    +
    3763 m_atime = m_mtime = time_point::now();
    +
    3764#endif
    +
    3765 m_size = m_offset;
    + +
    3767 }
    +
    +
    3768
    +
    3769#if SET_FILE_OP_TIMES
    +
    3770 virtual time_point ctime() const
    +
    3771 {
    +
    3772 return m_ctime;
    +
    3773 }
    +
    3774
    +
    3775 virtual time_point atime() const
    +
    3776 {
    +
    3777 return m_atime;
    +
    3778 }
    +
    3779
    +
    3780 virtual time_point mtime() const
    +
    3781 {
    +
    3782 return m_mtime;
    +
    3783 }
    +
    3784
    +
    3785 virtual void set_ctime(time_point date)
    +
    3786 {
    +
    3787 m_ctime = date;
    +
    3788 }
    +
    3789
    +
    3790 virtual void set_atime(time_point date)
    +
    3791 {
    +
    3792 m_atime = date;
    +
    3793 }
    +
    3794
    +
    3795 virtual void set_mtime(time_point date)
    +
    3796 {
    +
    3797 m_mtime = date;
    +
    3798 }
    +
    3799#endif
    +
    3800
    +
    3801 protected:
    +
    3809 template <class T>
    +
    +
    3810 inline void set(_In_ fpos_t offset, _In_ const T data)
    +
    3811 {
    +
    3812#if SET_FILE_OP_TIMES
    +
    3813 m_atime = m_mtime = time_point::now();
    +
    3814#endif
    +
    3815 _Assume_(offset + sizeof(T) < m_size);
    +
    3816 (*reinterpret_cast<T*>(m_data + offset)) = HE2LE(data);
    +
    3817 }
    +
    +
    3818
    +
    3819 public:
    +
    3820 inline void set(_In_ fpos_t offset, _In_ const int8_t data) { set<int8_t>(offset, data); }
    +
    3821 inline void set(_In_ fpos_t offset, _In_ const int16_t data) { set<int16_t>(offset, data); }
    +
    3822 inline void set(_In_ fpos_t offset, _In_ const int32_t data) { set<int32_t>(offset, data); }
    +
    3823 inline void set(_In_ fpos_t offset, _In_ const int64_t data) { set<int64_t>(offset, data); }
    +
    3824 inline void set(_In_ fpos_t offset, _In_ const uint8_t data) { set<uint8_t>(offset, data); }
    +
    3825 inline void set(_In_ fpos_t offset, _In_ const uint16_t data) { set<uint16_t>(offset, data); }
    +
    3826 inline void set(_In_ fpos_t offset, _In_ const uint32_t data) { set<uint32_t>(offset, data); }
    +
    3827 inline void set(_In_ fpos_t offset, _In_ const uint64_t data) { set<uint64_t>(offset, data); }
    +
    3828 inline void set(_In_ fpos_t offset, _In_ const float data) { set<float>(offset, data); }
    +
    3829 inline void set(_In_ fpos_t offset, _In_ const double data) { set<double>(offset, data); }
    +
    3830 inline void set(_In_ fpos_t offset, _In_ const char data) { set<char>(offset, data); }
    +
    3831#ifdef _NATIVE_WCHAR_T_DEFINED
    +
    3832 inline void set(_In_ fpos_t offset, _In_ const wchar_t data) { set<wchar_t>(offset, data); }
    +
    3833#endif
    +
    3834
    +
    3842 protected:
    +
    3843 template <class T>
    +
    +
    3844 inline void get(_In_ fpos_t offset, _Out_ T & data)
    +
    3845 {
    +
    3846 _Assume_(offset + sizeof(T) < m_size);
    +
    3847 data = LE2HE(*(T*)(m_data + offset));
    +
    3848#if SET_FILE_OP_TIMES
    +
    3849 m_atime = time_point::now();
    +
    3850#endif
    +
    3851 }
    +
    +
    3852
    +
    3853 public:
    +
    3854 inline void get(_In_ fpos_t offset, _Out_ int8_t & data) { get<int8_t>(offset, data); }
    +
    3855 inline void get(_In_ fpos_t offset, _Out_ int16_t & data) { get<int16_t>(offset, data); }
    +
    3856 inline void get(_In_ fpos_t offset, _Out_ int32_t & data) { get<int32_t>(offset, data); }
    +
    3857 inline void get(_In_ fpos_t offset, _Out_ int64_t & data) { get<int64_t>(offset, data); }
    +
    3858 inline void get(_In_ fpos_t offset, _Out_ uint8_t & data) { get<uint8_t>(offset, data); }
    +
    3859 inline void get(_In_ fpos_t offset, _Out_ uint16_t & data) { get<uint16_t>(offset, data); }
    +
    3860 inline void get(_In_ fpos_t offset, _Out_ uint32_t & data) { get<uint32_t>(offset, data); }
    +
    3861 inline void get(_In_ fpos_t offset, _Out_ uint64_t & data) { get<uint64_t>(offset, data); }
    +
    3862 inline void get(_In_ fpos_t offset, _Out_ float& data) { get<float>(offset, data); }
    +
    3863 inline void get(_In_ fpos_t offset, _Out_ double& data) { get<double>(offset, data); }
    +
    3864 inline void get(_In_ fpos_t offset, _Out_ char& data) { get<char>(offset, data); }
    +
    3865#ifdef _NATIVE_WCHAR_T_DEFINED
    +
    3866 inline void get(_In_ fpos_t offset, _Out_ wchar_t& data) { get<wchar_t>(offset, data); }
    +
    3867#endif
    +
    3868
    +
    3869 inline memory_file& operator <<(_In_ const int8_t data) { return write_data(data); }
    +
    3870 inline memory_file& operator >>(_Out_ int8_t & data) { return read_data(data); }
    +
    3871 inline memory_file& operator <<(_In_ const int16_t data) { return write_data(data); }
    +
    3872 inline memory_file& operator >>(_Out_ int16_t & data) { return read_data(data); }
    +
    3873 inline memory_file& operator <<(_In_ const int32_t data) { return write_data(data); }
    +
    3874 inline memory_file& operator >>(_Out_ int32_t & data) { return read_data(data); }
    +
    3875 inline memory_file& operator <<(_In_ const int64_t data) { return write_data(data); }
    +
    3876 inline memory_file& operator >>(_Out_ int64_t & data) { return read_data(data); }
    +
    3877 inline memory_file& operator <<(_In_ const uint8_t data) { return write_data(data); }
    +
    3878 inline memory_file& operator >>(_Out_ uint8_t & data) { return read_data(data); }
    +
    3879 inline memory_file& operator <<(_In_ const uint16_t data) { return write_data(data); }
    +
    3880 inline memory_file& operator >>(_Out_ uint16_t & data) { return read_data(data); }
    +
    3881 inline memory_file& operator <<(_In_ const uint32_t data) { return write_data(data); }
    +
    3882 inline memory_file& operator >>(_Out_ uint32_t & data) { return read_data(data); }
    +
    3883 inline memory_file& operator <<(_In_ const uint64_t data) { return write_data(data); }
    +
    3884 inline memory_file& operator >>(_Out_ uint64_t & data) { return read_data(data); }
    +
    3885 inline memory_file& operator <<(_In_ const float data) { return write_data(data); }
    +
    3886 inline memory_file& operator >>(_Out_ float& data) { return read_data(data); }
    +
    3887 inline memory_file& operator <<(_In_ const double data) { return write_data(data); }
    +
    3888 inline memory_file& operator >>(_Out_ double& data) { return read_data(data); }
    +
    3889 inline memory_file& operator <<(_In_ const char data) { return write_data(data); }
    +
    3890 inline memory_file& operator >>(_Out_ char& data) { return read_data(data); }
    +
    3891#ifdef _NATIVE_WCHAR_T_DEFINED
    +
    3892 inline memory_file& operator <<(_In_ const wchar_t data) { return write_data(data); }
    +
    3893 inline memory_file& operator >>(_Out_ wchar_t& data) { return read_data(data); }
    +
    3894#endif
    +
    3895 template<class _Elem, class _Traits = std::char_traits<_Elem>, class _Ax = std::allocator<_Elem>>
    +
    3896 inline memory_file& operator >>(_Out_ std::basic_string<_Elem, _Traits, _Ax>&data) { return read_str(data); }
    +
    3897 template <class T>
    +
    3898 inline memory_file& operator <<(_In_ const T * data) { return write_str(data); }
    +
    3899 template<class _Elem, class _Traits = std::char_traits<_Elem>, class _Ax = std::allocator<_Elem>>
    +
    3900 inline memory_file& operator <<(_In_ const std::basic_string<_Elem, _Traits, _Ax>& data) { return write_str(data); }
    +
    3901
    +
    3902 protected:
    +
    3903 uint8_t* m_data;
    + +
    3905 size_t m_offset;
    +
    3906 size_t m_size;
    +
    3907 size_t m_reserved;
    +
    3908#if SET_FILE_OP_TIMES
    +
    3909 time_point
    +
    3910 m_ctime,
    +
    3911 m_atime,
    +
    3912 m_mtime;
    +
    3913#endif
    +
    3914 };
    +
    +
    3915
    +
    +
    3919 class fifo : public basic {
    +
    3920 public:
    +
    3921 fifo() :
    +
    3922 m_offset(0),
    +
    3923 m_size(0),
    +
    3924 m_head(nullptr),
    +
    3925 m_tail(nullptr)
    +
    3926 {}
    +
    3927
    +
    3928 virtual ~fifo()
    +
    3929 {
    +
    3930 while (m_head) {
    +
    3931 auto p = m_head;
    +
    3932 m_head = p->next;
    +
    3933 delete p;
    +
    3934 }
    +
    3935 }
    +
    3936
    +
    3937#pragma warning(suppress: 6101) // See [2] below
    +
    +
    3938 virtual _Success_(return != 0 || length == 0) size_t read(
    +
    3939 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
    +
    3940 {
    +
    3941 _Assume_(data || !length);
    +
    3942 for (size_t to_read = length;;) {
    +
    3943 if (!m_head) _Unlikely_ {
    +
    3944 m_state = to_read < length || !length ? state_t::ok : state_t::eof;
    +
    3945 return length - to_read; // [2] Code analysis misses `length - to_read` bytes were written to data in previous loop iterations.
    +
    3946 }
    +
    3947 size_t remaining = m_head->size - m_offset;
    +
    3948 if (remaining > to_read) {
    +
    3949 memcpy(data, m_head->data + m_offset, to_read);
    +
    3950 m_offset += to_read;
    +
    3951 m_size -= to_read;
    +
    3952 m_state = state_t::ok;
    +
    3953 return length;
    +
    3954 }
    +
    3955 memcpy(data, m_head->data + m_offset, remaining);
    +
    3956 m_offset = 0;
    +
    3957 m_size -= remaining;
    +
    3958 reinterpret_cast<uint8_t*&>(data) += remaining;
    +
    3959 to_read -= remaining;
    +
    3960 auto p = m_head;
    +
    3961 m_head = p->next;
    +
    3962 delete p;
    +
    3963 }
    +
    3964 }
    +
    +
    3965
    +
    +
    3966 virtual _Success_(return != 0) size_t write(
    +
    3967 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
    +
    3968 {
    +
    3969 _Assume_(data || !length);
    +
    3970 try {
    +
    3971 std::unique_ptr<node_t> n(reinterpret_cast<node_t*>(new uint8_t[sizeof(node_t) + length]));
    +
    3972 n->next = nullptr;
    +
    3973 n->size = length;
    +
    3974 memcpy(n->data, data, length);
    +
    3975 m_size += length;
    +
    3976 if (m_head)
    +
    3977 m_tail = m_tail->next = n.release();
    +
    3978 else
    +
    3979 m_head = m_tail = n.release();
    +
    3980 m_state = state_t::ok;
    +
    3981 return length;
    +
    3982 }
    +
    3983 catch (const std::bad_alloc&) {
    +
    3984 m_state = state_t::fail;
    +
    3985 return 0;
    +
    3986 }
    +
    3987 }
    +
    +
    3988
    +
    +
    3989 virtual void close()
    +
    3990 {
    +
    3991 m_size = m_offset = 0;
    +
    3992 while (m_head) {
    +
    3993 auto p = m_head;
    +
    3994 m_head = p->next;
    +
    3995 delete p;
    +
    3996 }
    +
    3997 m_state = state_t::ok;
    +
    3998 }
    +
    +
    3999
    +
    4003 inline size_t size() const { return m_size; };
    +
    4004
    +
    4005 protected:
    +
    4006 size_t m_offset, m_size;
    +
    +
    4007 struct node_t {
    +
    4008 node_t* next;
    +
    4009 size_t size;
    +
    4010#pragma warning(suppress:4200)
    +
    4011 uint8_t data[0];
    +
    4012 } *m_head, * m_tail;
    +
    +
    4013 };
    +
    +
    4014
    +
    +
    4018 class diag_file : public basic_file {
    +
    4019 public:
    +
    4020 diag_file(_In_count_(num_files) basic_file* const* files, _In_ size_t num_files) :
    +
    4021 basic(num_files ? files[0]->state() : state_t::fail),
    +
    4022 m_files(files, files + num_files)
    +
    4023 {}
    +
    4024
    +
    +
    4025 virtual _Success_(return != 0 || length == 0) size_t read(
    +
    4026 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
    +
    4027 {
    +
    4028 _Assume_(data || !length);
    +
    4029 if (m_files.empty()) {
    +
    4030 m_state = state_t::fail;
    +
    4031 return 0;
    +
    4032 }
    +
    4033 size_t result = m_files[0]->read(data, length);
    +
    4034 _Assume_(result <= length);
    +
    4035 m_state = m_files[0]->state();
    +
    4036 if (length > m_tmp.size())
    +
    4037 m_tmp.resize(length);
    +
    4038 for (size_t i = 1, n = m_files.size(); i < n; ++i) {
    +
    4039 if (m_files[i]->read(m_tmp.data(), length) != result ||
    +
    4040 memcmp(m_tmp.data(), data, result))
    +
    4041 throw std::runtime_error("read mismatch");
    +
    4042 if (m_files[i]->state() != m_state)
    +
    4043 throw std::runtime_error("state mismatch");
    +
    4044 }
    +
    4045 return result;
    +
    4046 }
    +
    +
    4047
    +
    +
    4048 virtual _Success_(return != 0) size_t write(
    +
    4049 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
    +
    4050 {
    +
    4051 if (m_files.empty()) {
    +
    4052 m_state = state_t::fail;
    +
    4053 return 0;
    +
    4054 }
    +
    4055 size_t result = m_files[0]->write(data, length);
    +
    4056 m_state = m_files[0]->state();
    +
    4057 for (size_t i = 1, n = m_files.size(); i < n; ++i) {
    +
    4058 if (m_files[i]->write(data, length) != result)
    +
    4059 throw std::runtime_error("write mismatch");
    +
    4060 if (m_files[i]->state() != m_state)
    +
    4061 throw std::runtime_error("state mismatch");
    +
    4062 }
    +
    4063 return result;
    +
    4064 }
    +
    +
    4065
    +
    +
    4066 virtual void flush()
    +
    4067 {
    +
    4068 if (m_files.empty()) {
    +
    4069 m_state = state_t::ok;
    +
    4070 return;
    +
    4071 }
    +
    4072 m_files[0]->flush();
    +
    4073 m_state = m_files[0]->state();
    +
    4074 for (size_t i = 1, n = m_files.size(); i < n; ++i) {
    +
    4075 m_files[i]->flush();
    +
    4076 if (m_files[i]->state() != m_state)
    +
    4077 throw std::runtime_error("state mismatch");
    +
    4078 }
    +
    4079 }
    +
    +
    4080
    +
    +
    4081 virtual void close()
    +
    4082 {
    +
    4083 if (m_files.empty()) {
    +
    4084 m_state = state_t::ok;
    +
    4085 return;
    +
    4086 }
    +
    4087 m_files[0]->close();
    +
    4088 m_state = m_files[0]->state();
    +
    4089 for (size_t i = 1, n = m_files.size(); i < n; ++i) {
    +
    4090 m_files[i]->close();
    +
    4091 if (m_files[i]->state() != m_state)
    +
    4092 throw std::runtime_error("state mismatch");
    +
    4093 }
    +
    4094 m_tmp.clear();
    +
    4095 m_tmp.shrink_to_fit();
    +
    4096 }
    +
    +
    4097
    +
    +
    4098 virtual fpos_t seek(_In_ foff_t offset, _In_ seek_t how = seek_t::beg)
    +
    4099 {
    +
    4100 if (m_files.empty()) {
    +
    4101 m_state = state_t::fail;
    +
    4102 return fpos_max;
    +
    4103 }
    +
    4104 fpos_t result = m_files[0]->seek(offset, how);
    +
    4105 m_state = m_files[0]->state();
    +
    4106 for (size_t i = 1, n = m_files.size(); i < n; ++i) {
    +
    4107 if (m_files[i]->seek(offset, how) != result)
    +
    4108 throw std::runtime_error("seek mismatch");
    +
    4109 if (m_files[i]->state() != m_state)
    +
    4110 throw std::runtime_error("state mismatch");
    +
    4111 }
    +
    4112 return result;
    +
    4113 }
    +
    +
    4114
    +
    +
    4115 virtual fpos_t tell() const
    +
    4116 {
    +
    4117 if (m_files.empty())
    +
    4118 return fpos_max;
    +
    4119 fpos_t result = m_files[0]->tell();
    +
    4120 for (size_t i = 1, n = m_files.size(); i < n; ++i) {
    +
    4121 if (m_files[i]->tell() != result)
    +
    4122 throw std::runtime_error("tell mismatch");
    +
    4123 }
    +
    4124 return result;
    +
    4125 }
    +
    +
    4126
    +
    +
    4127 virtual void lock(_In_ fpos_t offset, _In_ fsize_t length)
    +
    4128 {
    +
    4129 if (m_files.empty())
    +
    4130 m_state = state_t::fail;
    +
    4131 m_files[0]->lock(offset, length);
    +
    4132 m_state = m_files[0]->state();
    +
    4133 for (size_t i = 1, n = m_files.size(); i < n; ++i) {
    +
    4134 m_files[i]->lock(offset, length);
    +
    4135 if (m_files[i]->state() != m_state)
    +
    4136 throw std::runtime_error("state mismatch");
    +
    4137 }
    +
    4138 }
    +
    +
    4139
    +
    +
    4140 virtual void unlock(_In_ fpos_t offset, _In_ fsize_t length)
    +
    4141 {
    +
    4142 if (m_files.empty())
    +
    4143 m_state = state_t::fail;
    +
    4144 m_files[0]->unlock(offset, length);
    +
    4145 m_state = m_files[0]->state();
    +
    4146 for (size_t i = 1, n = m_files.size(); i < n; ++i) {
    +
    4147 m_files[i]->unlock(offset, length);
    +
    4148 if (m_files[i]->state() != m_state)
    +
    4149 throw std::runtime_error("state mismatch");
    +
    4150 }
    +
    4151 }
    +
    +
    4152
    +
    +
    4153 virtual fsize_t size()
    +
    4154 {
    +
    4155 if (m_files.empty()) {
    +
    4156 m_state = state_t::fail;
    +
    4157 return 0;
    +
    4158 }
    +
    4159 fsize_t result = m_files[0]->size();
    +
    4160 m_state = m_files[0]->state();
    +
    4161 for (size_t i = 1, n = m_files.size(); i < n; ++i) {
    +
    4162 if (m_files[i]->size() != result)
    +
    4163 throw std::runtime_error("size mismatch");
    +
    4164 if (m_files[i]->state() != m_state)
    +
    4165 throw std::runtime_error("state mismatch");
    +
    4166 }
    +
    4167 return result;
    +
    4168 }
    +
    +
    4169
    +
    +
    4170 virtual void truncate()
    +
    4171 {
    +
    4172 if (m_files.empty())
    +
    4173 m_state = state_t::fail;
    +
    4174 m_files[0]->truncate();
    +
    4175 m_state = m_files[0]->state();
    +
    4176 for (size_t i = 1, n = m_files.size(); i < n; ++i) {
    +
    4177 m_files[i]->truncate();
    +
    4178 if (m_files[i]->state() != m_state)
    +
    4179 throw std::runtime_error("state mismatch");
    +
    4180 }
    +
    4181 }
    +
    +
    4182
    +
    4183 protected:
    +
    4184 std::vector<basic_file*> m_files;
    +
    4185 std::vector<uint8_t> m_tmp;
    +
    4186 };
    +
    +
    4187 }
    +
    4188}
    +
    Encoding converter context.
    Definition unicode.hpp:70
    +
    Provides read-ahead stream capability.
    Definition stream.hpp:1256
    +
    virtual size_t read(_Out_writes_bytes_to_opt_(length, return) void *data, size_t length)
    Reads block of data from the stream.
    Definition stream.hpp:1270
    +
    Provides write-back stream capability.
    Definition stream.hpp:1323
    +
    virtual void flush()
    Persists volatile element data.
    Definition stream.hpp:1360
    +
    virtual size_t write(_In_reads_bytes_opt_(length) const void *data, size_t length)
    Writes block of data to the stream.
    Definition stream.hpp:1336
    +
    Basic seekable stream operations.
    Definition stream.hpp:824
    +
    virtual void skip(fsize_t amount)
    Skips given amount of bytes of data on the stream.
    Definition stream.hpp:867
    +
    virtual time_point ctime() const
    Returns file creation time.
    Definition stream.hpp:914
    +
    virtual void lock(fpos_t offset, fsize_t length)
    Locks file section for exclusive access.
    Definition stream.hpp:883
    virtual void truncate()=0
    Sets file size - truncates the remainder of file content from the current file position to the end of...
    -
    charset_id read_charset(charset_id default_charset=charset_id::system)
    Attempts to detect textfile charset based on UTF-32, UTF-16 or UTF-8 BOM.
    Definition stream.hpp:986
    -
    fpos_t seekbeg(fpos_t offset)
    Seeks to absolute file position.
    Definition stream.hpp:850
    -
    virtual std::vector< uint8_t > read_remainder(size_t max_length=SIZE_MAX)
    Reads and returns remainder of the stream.
    Definition stream.hpp:825
    -
    virtual void set_mtime(time_point date)
    Sets file modification time.
    Definition stream.hpp:955
    -
    fpos_t seekcur(foff_t offset)
    Seeks to relative from current file position.
    Definition stream.hpp:857
    -
    virtual time_point atime() const
    Returns file access time.
    Definition stream.hpp:921
    -
    virtual void set_ctime(time_point date)
    Sets file create time.
    Definition stream.hpp:937
    +
    charset_id read_charset(charset_id default_charset=charset_id::system)
    Attempts to detect textfile charset based on UTF-32, UTF-16 or UTF-8 BOM.
    Definition stream.hpp:987
    +
    fpos_t seekbeg(fpos_t offset)
    Seeks to absolute file position.
    Definition stream.hpp:851
    +
    virtual std::vector< uint8_t > read_remainder(size_t max_length=SIZE_MAX)
    Reads and returns remainder of the stream.
    Definition stream.hpp:826
    +
    virtual void set_mtime(time_point date)
    Sets file modification time.
    Definition stream.hpp:956
    +
    fpos_t seekcur(foff_t offset)
    Seeks to relative from current file position.
    Definition stream.hpp:858
    +
    virtual time_point atime() const
    Returns file access time.
    Definition stream.hpp:922
    +
    virtual void set_ctime(time_point date)
    Sets file create time.
    Definition stream.hpp:938
    virtual fsize_t size()=0
    Returns file size Should the file size cannot be determined, the method returns fsize_max and it does...
    -
    virtual void unlock(fpos_t offset, fsize_t length)
    Unlocks file section for exclusive access.
    Definition stream.hpp:892
    +
    virtual void unlock(fpos_t offset, fsize_t length)
    Unlocks file section for exclusive access.
    Definition stream.hpp:893
    virtual fpos_t tell() const =0
    Returns absolute file position in file or fpos_max if fails. This method does not update stream state...
    -
    virtual time_point mtime() const
    Returns file modification time.
    Definition stream.hpp:929
    -
    fpos_t seekend(foff_t offset)
    Seeks to relative from end file position.
    Definition stream.hpp:864
    -
    virtual void set_atime(time_point date)
    Sets file access time.
    Definition stream.hpp:946
    +
    virtual time_point mtime() const
    Returns file modification time.
    Definition stream.hpp:930
    +
    fpos_t seekend(foff_t offset)
    Seeks to relative from end file position.
    Definition stream.hpp:865
    +
    virtual void set_atime(time_point date)
    Sets file access time.
    Definition stream.hpp:947
    virtual fpos_t seek(foff_t offset, seek_t how=seek_t::beg)=0
    Seeks to specified relative file position.
    -
    OS data stream (file, pipe, socket...)
    Definition stream.hpp:2195
    -
    virtual size_t write(_In_reads_bytes_opt_(length) const void *data, size_t length)
    Writes block of data to the stream.
    Definition stream.hpp:2252
    -
    virtual void flush()
    Persists volatile element data.
    Definition stream.hpp:2310
    -
    virtual size_t read(_Out_writes_bytes_to_opt_(length, return) void *data, size_t length)
    Reads block of data from the stream.
    Definition stream.hpp:2202
    -
    virtual void close()
    Closes the stream.
    Definition stream.hpp:2299
    -
    ‍UTF-8 byte-order-mark
    Definition stream.hpp:78
    -
    bool ok() const
    Returns true if the stream state is clean i.e. previous operation was succesful.
    Definition stream.hpp:174
    -
    size_t write_vsprintf(_Printf_format_string_params_(2) const char *format, locale_t locale, va_list params)
    Writes formatted string to the stream.
    Definition stream.hpp:636
    -
    size_t write_array(const std::basic_string< T_from, _Traits, _Ax > &wstr, charset_encoder< T_from, T_to > &encoder)
    Writes array of characters to the stream.
    Definition stream.hpp:454
    -
    state_t state() const
    Returns stream state after last operation.
    Definition stream.hpp:169
    -
    basic & read_str(std::basic_string< _Elem, _Traits, _Ax > &data)
    Reads length-prefixed string from the stream.
    Definition stream.hpp:476
    -
    size_t write_sprintf(_Printf_format_string_params_(2) const wchar_t *format, locale_t locale,...)
    Writes formatted string to the stream.
    Definition stream.hpp:622
    -
    size_t write_vsprintf(_Printf_format_string_params_(2) const wchar_t *format, locale_t locale, va_list params)
    Writes formatted string to the stream.
    Definition stream.hpp:649
    -
    virtual void flush()
    Persists volatile element data.
    Definition stream.hpp:125
    -
    virtual void skip(fsize_t amount)
    Skips given amount of bytes of data on the stream.
    Definition stream.hpp:141
    -
    virtual void close()
    Closes the stream.
    Definition stream.hpp:133
    -
    uint8_t read_byte()
    Reads one byte of data.
    Definition stream.hpp:209
    -
    virtual std::vector< uint8_t > read_remainder(size_t max_length=SIZE_MAX)
    Reads and returns remainder of the stream.
    Definition stream.hpp:183
    -
    size_t write_sprintf(_Printf_format_string_params_(2) const char *format, locale_t locale,...)
    Writes formatted string to the stream.
    Definition stream.hpp:608
    -
    size_t readln(std::basic_string< char, _Traits, _Ax > &str)
    Reads stream to the end-of-line or end-of-file.
    Definition stream.hpp:305
    -
    size_t readln_and_attach(std::basic_string< _Elem, _Traits, _Ax > &str)
    Reads stream to the end-of-line or end-of-file and append to str.
    Definition stream.hpp:345
    -
    size_t read_array(_Out_writes_bytes_(size *count) void *array, size_t size, size_t count)
    Reads an array of data from the stream.
    Definition stream.hpp:381
    -
    basic & write_str(const T *data)
    Writes string to the stream length-prefixed.
    Definition stream.hpp:508
    -
    virtual size_t read(_Out_writes_bytes_to_opt_(length, return) void *data, size_t length)
    Reads block of data from the stream.
    Definition stream.hpp:95
    -
    size_t readln(std::basic_string< wchar_t, _Traits, _Ax > &wstr)
    Reads stream to the end-of-line or end-of-file.
    Definition stream.hpp:317
    -
    void write_charset(charset_id charset)
    Writes UTF8, UTF-16 or UTF-32 byte-order-mark.
    Definition stream.hpp:593
    -
    basic & write_str(const std::basic_string< _Elem, _Traits, _Ax > &data)
    Writes string to the stream length-prefixed.
    Definition stream.hpp:533
    -
    basic & write_data(const T data)
    Writes one primitive data type.
    Definition stream.hpp:286
    -
    size_t write_array(const T_from *wstr, charset_encoder< T_from, T_to > &encoder)
    Writes array of characters to the stream.
    Definition stream.hpp:413
    -
    size_t readln_and_attach(std::basic_string< T_to, _Traits, _Ax > &wstr, charset_encoder< T_from, T_to > &encoder)
    Reads stream to the end-of-line or end-of-file and append to str.
    Definition stream.hpp:366
    -
    fsize_t write_stream(basic &stream, fsize_t amount=fsize_max)
    Writes content of another stream.
    Definition stream.hpp:568
    -
    virtual size_t write(_In_reads_bytes_opt_(length) const void *data, size_t length)
    Writes block of data to the stream.
    Definition stream.hpp:113
    -
    size_t write_array(_In_reads_or_z_opt_(num_chars) const T_from *wstr, size_t num_chars, charset_encoder< T_from, T_to > &encoder)
    Writes array of characters to the stream.
    Definition stream.hpp:434
    -
    size_t readln(std::basic_string< T_to, _Traits, _Ax > &wstr, charset_encoder< T_from, T_to > &encoder)
    Reads stream to the end-of-line or end-of-file.
    Definition stream.hpp:329
    -
    size_t write_array(_In_reads_bytes_opt_(size *count) const void *array, size_t size, size_t count)
    Writes an array of data to the stream.
    Definition stream.hpp:399
    -
    void write_byte(uint8_t byte, fsize_t amount=1)
    Writes a byte of data.
    Definition stream.hpp:220
    -
    basic & read_data(T &data)
    Reads one primitive data type.
    Definition stream.hpp:258
    -
    Buffered read/write stream.
    Definition stream.hpp:1393
    -
    virtual void flush()
    Persists volatile element data.
    Definition stream.hpp:1502
    -
    virtual size_t read(_Out_writes_bytes_to_opt_(length, return) void *data, size_t length)
    Reads block of data from the stream.
    Definition stream.hpp:1423
    -
    virtual size_t write(_In_reads_bytes_opt_(length) const void *data, size_t length)
    Writes block of data to the stream.
    Definition stream.hpp:1459
    -
    Buffered OS data stream (file, pipe, socket...)
    Definition stream.hpp:2324
    -
    Cached file.
    Definition stream.hpp:1803
    -
    virtual time_point ctime() const
    Returns file creation time.
    Definition stream.hpp:2065
    -
    virtual void truncate()
    Sets file size - truncates the remainder of file content from the current file position to the end of...
    Definition stream.hpp:2044
    -
    virtual size_t read(_Out_writes_bytes_to_opt_(length, return) void *data, size_t length)
    Reads block of data from the stream.
    Definition stream.hpp:1870
    -
    virtual time_point atime() const
    Returns file access time.
    Definition stream.hpp:2070
    -
    virtual fsize_t size()
    Returns file size Should the file size cannot be determined, the method returns fsize_max and it does...
    Definition stream.hpp:2037
    -
    virtual void unlock(fpos_t offset, fsize_t length)
    Unlocks file section for exclusive access.
    Definition stream.hpp:2031
    -
    virtual time_point mtime() const
    Returns file modification time.
    Definition stream.hpp:2079
    -
    virtual void close()
    Closes the stream.
    Definition stream.hpp:1985
    -
    virtual void set_mtime(time_point date)
    Sets file modification time.
    Definition stream.hpp:2101
    -
    virtual void lock(fpos_t offset, fsize_t length)
    Locks file section for exclusive access.
    Definition stream.hpp:2025
    -
    virtual void flush()
    Persists volatile element data.
    Definition stream.hpp:1994
    -
    virtual size_t write(_In_reads_bytes_opt_(length) const void *data, size_t length)
    Writes block of data to the stream.
    Definition stream.hpp:1932
    -
    virtual void set_ctime(time_point date)
    Sets file create time.
    Definition stream.hpp:2088
    -
    virtual fpos_t tell() const
    Returns absolute file position in file or fpos_max if fails. This method does not update stream state...
    Definition stream.hpp:2020
    -
    virtual void set_atime(time_point date)
    Sets file access time.
    Definition stream.hpp:2093
    -
    virtual fpos_t seek(foff_t offset, seek_t how=seek_t::beg)
    Seeks to specified relative file position.
    Definition stream.hpp:2005
    -
    Cached file-system file.
    Definition stream.hpp:3094
    -
    cached_file(const stdex::sstring &filename, int mode, size_t cache_size=default_cache_size)
    Opens file.
    Definition stream.hpp:3124
    -
    void open(const stdex::sstring &filename, int mode)
    Opens file.
    Definition stream.hpp:3158
    -
    void open(const schar_t *filename, int mode)
    Opens file.
    Definition stream.hpp:3137
    -
    cached_file(const schar_t *filename, int mode, size_t cache_size=default_cache_size)
    Opens file.
    Definition stream.hpp:3110
    -
    Modifies data on the fly when reading from/writing to a source stream. Could also be used to modify r...
    Definition stream.hpp:1021
    -
    virtual void flush()
    Persists volatile element data.
    Definition stream.hpp:1072
    -
    virtual void close()
    Closes the stream.
    Definition stream.hpp:1066
    -
    virtual size_t read(_Out_writes_bytes_to_opt_(length, return) void *data, size_t length)
    Reads block of data from the stream.
    Definition stream.hpp:1050
    -
    virtual size_t write(_In_reads_bytes_opt_(length) const void *data, size_t length)
    Writes block of data to the stream.
    Definition stream.hpp:1058
    -
    Compares multiple files to perform the same.
    Definition stream.hpp:4017
    -
    virtual fsize_t size()
    Returns file size Should the file size cannot be determined, the method returns fsize_max and it does...
    Definition stream.hpp:4152
    -
    virtual void truncate()
    Sets file size - truncates the remainder of file content from the current file position to the end of...
    Definition stream.hpp:4169
    -
    virtual size_t write(_In_reads_bytes_opt_(length) const void *data, size_t length)
    Writes block of data to the stream.
    Definition stream.hpp:4047
    -
    virtual void close()
    Closes the stream.
    Definition stream.hpp:4080
    -
    virtual void lock(fpos_t offset, fsize_t length)
    Locks file section for exclusive access.
    Definition stream.hpp:4126
    -
    virtual void unlock(fpos_t offset, fsize_t length)
    Unlocks file section for exclusive access.
    Definition stream.hpp:4139
    -
    virtual fpos_t seek(foff_t offset, seek_t how=seek_t::beg)
    Seeks to specified relative file position.
    Definition stream.hpp:4097
    -
    virtual fpos_t tell() const
    Returns absolute file position in file or fpos_max if fails. This method does not update stream state...
    Definition stream.hpp:4114
    -
    virtual void flush()
    Persists volatile element data.
    Definition stream.hpp:4065
    -
    virtual size_t read(_Out_writes_bytes_to_opt_(length, return) void *data, size_t length)
    Reads block of data from the stream.
    Definition stream.hpp:4024
    -
    In-memory FIFO queue.
    Definition stream.hpp:3918
    -
    virtual void close()
    Closes the stream.
    Definition stream.hpp:3988
    -
    virtual size_t write(_In_reads_bytes_opt_(length) const void *data, size_t length)
    Writes block of data to the stream.
    Definition stream.hpp:3965
    -
    size_t size() const
    Returns total size of pending data in the queue.
    Definition stream.hpp:4002
    -
    virtual size_t read(_Out_writes_bytes_to_opt_(length, return) void *data, size_t length)
    Reads block of data from the stream.
    Definition stream.hpp:3937
    -
    Limits file reading/writing to a predefined window.
    Definition stream.hpp:1693
    -
    virtual void truncate()
    Sets file size - truncates the remainder of file content from the current file position to the end of...
    Definition stream.hpp:1786
    -
    virtual void flush()
    Persists volatile element data.
    Definition stream.hpp:1736
    -
    virtual void skip(fsize_t amount)
    Skips given amount of bytes of data on the stream.
    Definition stream.hpp:1749
    -
    virtual fpos_t seek(foff_t offset, seek_t how=seek_t::beg)
    Seeks to specified relative file position.
    Definition stream.hpp:1742
    -
    virtual fsize_t size()
    Returns file size Should the file size cannot be determined, the method returns fsize_max and it does...
    Definition stream.hpp:1781
    -
    virtual size_t write(_In_reads_bytes_opt_(length) const void *data, size_t length)
    Writes block of data to the stream.
    Definition stream.hpp:1716
    -
    virtual void lock(fpos_t offset, fsize_t length)
    Locks file section for exclusive access.
    Definition stream.hpp:1761
    -
    virtual size_t read(_Out_writes_bytes_to_opt_(length, return) void *data, size_t length)
    Reads block of data from the stream.
    Definition stream.hpp:1702
    -
    virtual void unlock(fpos_t offset, fsize_t length)
    Unlocks file section for exclusive access.
    Definition stream.hpp:1771
    -
    virtual fpos_t tell() const
    Returns absolute file position in file or fpos_max if fails. This method does not update stream state...
    Definition stream.hpp:1755
    -
    virtual void close()
    Closes the stream.
    Definition stream.hpp:1730
    -
    File-system file.
    Definition stream.hpp:2690
    -
    file(const stdex::sstring &filename, int mode)
    Opens file.
    Definition stream.hpp:2711
    -
    static bool readonly(const stdex::sstring &filename)
    Checks if file/folder/symlink is read-only.
    Definition stream.hpp:3083
    -
    virtual time_point mtime() const
    Returns file modification time.
    Definition stream.hpp:2966
    -
    virtual void unlock(fpos_t offset, fsize_t length)
    Unlocks file section for exclusive access.
    Definition stream.hpp:2859
    -
    file(const schar_t *filename, int mode)
    Opens file.
    Definition stream.hpp:2700
    -
    virtual void set_ctime(time_point date)
    Sets file create time.
    Definition stream.hpp:2980
    -
    static bool readonly(const stdex::schar_t *filename)
    Checks if file/folder/symlink is read-only.
    Definition stream.hpp:3065
    -
    static bool exists(const stdex::sstring &filename)
    Checks if file/folder/symlink likely exists.
    Definition stream.hpp:3053
    -
    virtual time_point atime() const
    Returns file access time.
    Definition stream.hpp:2952
    -
    void open(const schar_t *filename, int mode)
    Opens file.
    Definition stream.hpp:2719
    -
    virtual void set_mtime(time_point date)
    Sets file modification time.
    Definition stream.hpp:3014
    -
    virtual void set_atime(time_point date)
    Sets file access time.
    Definition stream.hpp:2994
    -
    virtual void lock(fpos_t offset, fsize_t length)
    Locks file section for exclusive access.
    Definition stream.hpp:2836
    -
    virtual void truncate()
    Sets file size - truncates the remainder of file content from the current file position to the end of...
    Definition stream.hpp:2902
    -
    virtual time_point ctime() const
    Returns file creation time.
    Definition stream.hpp:2942
    -
    void open(const stdex::sstring &filename, int mode)
    Opens file.
    Definition stream.hpp:2792
    -
    virtual fsize_t size()
    Returns file size Should the file size cannot be determined, the method returns fsize_max and it does...
    Definition stream.hpp:2884
    -
    virtual fpos_t seek(foff_t offset, seek_t how=seek_t::beg)
    Seeks to specified relative file position.
    Definition stream.hpp:2797
    -
    virtual fpos_t tell() const
    Returns absolute file position in file or fpos_max if fails. This method does not update stream state...
    Definition stream.hpp:2818
    -
    static bool exists(const stdex::schar_t *filename)
    Checks if file/folder/symlink likely exists.
    Definition stream.hpp:3038
    -
    Limits reading from/writing to stream to a predefined number of bytes.
    Definition stream.hpp:1550
    -
    fsize_t read_limit
    Number of bytes left that may be read from the stream.
    Definition stream.hpp:1602
    -
    virtual size_t read(_Out_writes_bytes_to_opt_(length, return) void *data, size_t length)
    Reads block of data from the stream.
    Definition stream.hpp:1558
    -
    virtual size_t write(_In_reads_bytes_opt_(length) const void *data, size_t length)
    Writes block of data to the stream.
    Definition stream.hpp:1579
    -
    fsize_t write_limit
    Number of bytes left, that can be written to the stream.
    Definition stream.hpp:1603
    -
    In-memory file.
    Definition stream.hpp:3171
    -
    memory_file(const schar_t *filename, int mode)
    Loads content from file-system file.
    Definition stream.hpp:3249
    -
    memory_file & write_str(const std::basic_string< _Elem, _Traits, _Ax > &data)
    Writes string to the stream length-prefixed.
    Definition stream.hpp:3633
    -
    size_t m_size
    file size
    Definition stream.hpp:3905
    -
    void get(fpos_t offset, T &data)
    Reads data from specified file location This does not move file pointer. It checks for data size Assu...
    Definition stream.hpp:3843
    -
    size_t write_stream(basic &stream, size_t amount=SIZE_MAX)
    Writes content of another stream.
    Definition stream.hpp:3668
    -
    uint8_t * m_data
    file data
    Definition stream.hpp:3902
    -
    memory_file & read_data(T &data)
    Reads one primitive data type.
    Definition stream.hpp:3422
    -
    virtual void close()
    Closes the stream.
    Definition stream.hpp:3718
    -
    virtual size_t read(_Out_writes_bytes_to_opt_(length, return) void *data, size_t length)
    Reads block of data from the stream.
    Definition stream.hpp:3383
    -
    virtual fpos_t tell() const
    Returns absolute file position in file or fpos_max if fails. This method does not update stream state...
    Definition stream.hpp:3749
    -
    size_t m_reserved
    reserved file size
    Definition stream.hpp:3906
    -
    memory_file(size_t size, state_t state=state_t::ok)
    Creates an empty file of reserved size.
    Definition stream.hpp:3192
    -
    void reserve(size_t required, bool tight=false) noexcept
    Reallocates memory.
    Definition stream.hpp:3274
    -
    memory_file(const stdex::sstring &filename, int mode)
    Loads content from file-system file.
    Definition stream.hpp:3260
    -
    memory_file & read_str(std::basic_string< _Elem, _Traits, _Ax > &data)
    Reads length-prefixed string from the stream.
    Definition stream.hpp:3462
    -
    void write_byte(uint8_t byte, size_t amount=1)
    Writes a byte of data.
    Definition stream.hpp:3517
    -
    void set(fpos_t offset, const T data)
    Writes data to specified file location This does not move file pointer nor update file size....
    Definition stream.hpp:3809
    -
    void load(const stdex::sstring &filename, int mode)
    Loads content from a file-system file.
    Definition stream.hpp:3336
    -
    size_t m_offset
    file pointer
    Definition stream.hpp:3904
    -
    void save(const schar_t *filename, int mode)
    Saves content to a file-system file.
    Definition stream.hpp:3347
    -
    void load(const schar_t *filename, int mode)
    Loads content from a file-system file.
    Definition stream.hpp:3303
    -
    virtual fsize_t size()
    Returns file size Should the file size cannot be determined, the method returns fsize_max and it does...
    Definition stream.hpp:3754
    -
    virtual fpos_t seek(foff_t offset, seek_t how=seek_t::beg)
    Seeks to specified relative file position.
    Definition stream.hpp:3732
    -
    virtual void truncate()
    Sets file size - truncates the remainder of file content from the current file position to the end of...
    Definition stream.hpp:3759
    -
    memory_file & write_data(const T data)
    Writes one primitive data type.
    Definition stream.hpp:3550
    -
    memory_file & write_str(const T *data)
    Writes string to the stream length-prefixed.
    Definition stream.hpp:3588
    -
    void save(const stdex::sstring &filename, int mode)
    Saves content to a file-system file.
    Definition stream.hpp:3373
    -
    bool m_manage
    may reallocate m_data?
    Definition stream.hpp:3903
    -
    memory_file(void *data, size_t size, bool manage=false, state_t state=state_t::ok)
    Creates a file based on available data.
    Definition stream.hpp:3239
    -
    virtual size_t write(_In_reads_bytes_opt_(length) const void *data, size_t length)
    Writes block of data to the stream.
    Definition stream.hpp:3493
    -
    memory_file(void *data, size_t size, size_t reserved, bool manage=false, state_t state=state_t::ok)
    Creates a file based on available data.
    Definition stream.hpp:3216
    -
    const void * data() const
    Returns pointer to data.
    Definition stream.hpp:3381
    -
    Definition stream.hpp:1169
    +
    OS data stream (file, pipe, socket...)
    Definition stream.hpp:2196
    +
    virtual size_t write(_In_reads_bytes_opt_(length) const void *data, size_t length)
    Writes block of data to the stream.
    Definition stream.hpp:2253
    +
    virtual void flush()
    Persists volatile element data.
    Definition stream.hpp:2311
    +
    virtual size_t read(_Out_writes_bytes_to_opt_(length, return) void *data, size_t length)
    Reads block of data from the stream.
    Definition stream.hpp:2203
    +
    virtual void close()
    Closes the stream.
    Definition stream.hpp:2300
    +
    ‍UTF-8 byte-order-mark
    Definition stream.hpp:79
    +
    bool ok() const
    Returns true if the stream state is clean i.e. previous operation was succesful.
    Definition stream.hpp:175
    +
    size_t write_vsprintf(_Printf_format_string_params_(2) const char *format, locale_t locale, va_list params)
    Writes formatted string to the stream.
    Definition stream.hpp:637
    +
    size_t write_array(const std::basic_string< T_from, _Traits, _Ax > &wstr, charset_encoder< T_from, T_to > &encoder)
    Writes array of characters to the stream.
    Definition stream.hpp:455
    +
    state_t state() const
    Returns stream state after last operation.
    Definition stream.hpp:170
    +
    basic & read_str(std::basic_string< _Elem, _Traits, _Ax > &data)
    Reads length-prefixed string from the stream.
    Definition stream.hpp:477
    +
    size_t write_sprintf(_Printf_format_string_params_(2) const wchar_t *format, locale_t locale,...)
    Writes formatted string to the stream.
    Definition stream.hpp:623
    +
    size_t write_vsprintf(_Printf_format_string_params_(2) const wchar_t *format, locale_t locale, va_list params)
    Writes formatted string to the stream.
    Definition stream.hpp:650
    +
    virtual void flush()
    Persists volatile element data.
    Definition stream.hpp:126
    +
    virtual void skip(fsize_t amount)
    Skips given amount of bytes of data on the stream.
    Definition stream.hpp:142
    +
    virtual void close()
    Closes the stream.
    Definition stream.hpp:134
    +
    uint8_t read_byte()
    Reads one byte of data.
    Definition stream.hpp:210
    +
    virtual std::vector< uint8_t > read_remainder(size_t max_length=SIZE_MAX)
    Reads and returns remainder of the stream.
    Definition stream.hpp:184
    +
    size_t write_sprintf(_Printf_format_string_params_(2) const char *format, locale_t locale,...)
    Writes formatted string to the stream.
    Definition stream.hpp:609
    +
    size_t readln(std::basic_string< char, _Traits, _Ax > &str)
    Reads stream to the end-of-line or end-of-file.
    Definition stream.hpp:306
    +
    size_t readln_and_attach(std::basic_string< _Elem, _Traits, _Ax > &str)
    Reads stream to the end-of-line or end-of-file and append to str.
    Definition stream.hpp:346
    +
    size_t read_array(_Out_writes_bytes_(size *count) void *array, size_t size, size_t count)
    Reads an array of data from the stream.
    Definition stream.hpp:382
    +
    basic & write_str(const T *data)
    Writes string to the stream length-prefixed.
    Definition stream.hpp:509
    +
    virtual size_t read(_Out_writes_bytes_to_opt_(length, return) void *data, size_t length)
    Reads block of data from the stream.
    Definition stream.hpp:96
    +
    size_t readln(std::basic_string< wchar_t, _Traits, _Ax > &wstr)
    Reads stream to the end-of-line or end-of-file.
    Definition stream.hpp:318
    +
    void write_charset(charset_id charset)
    Writes UTF8, UTF-16 or UTF-32 byte-order-mark.
    Definition stream.hpp:594
    +
    basic & write_str(const std::basic_string< _Elem, _Traits, _Ax > &data)
    Writes string to the stream length-prefixed.
    Definition stream.hpp:534
    +
    basic & write_data(const T data)
    Writes one primitive data type.
    Definition stream.hpp:287
    +
    size_t write_array(const T_from *wstr, charset_encoder< T_from, T_to > &encoder)
    Writes array of characters to the stream.
    Definition stream.hpp:414
    +
    size_t readln_and_attach(std::basic_string< T_to, _Traits, _Ax > &wstr, charset_encoder< T_from, T_to > &encoder)
    Reads stream to the end-of-line or end-of-file and append to str.
    Definition stream.hpp:367
    +
    fsize_t write_stream(basic &stream, fsize_t amount=fsize_max)
    Writes content of another stream.
    Definition stream.hpp:569
    +
    virtual size_t write(_In_reads_bytes_opt_(length) const void *data, size_t length)
    Writes block of data to the stream.
    Definition stream.hpp:114
    +
    size_t write_array(_In_reads_or_z_opt_(num_chars) const T_from *wstr, size_t num_chars, charset_encoder< T_from, T_to > &encoder)
    Writes array of characters to the stream.
    Definition stream.hpp:435
    +
    size_t readln(std::basic_string< T_to, _Traits, _Ax > &wstr, charset_encoder< T_from, T_to > &encoder)
    Reads stream to the end-of-line or end-of-file.
    Definition stream.hpp:330
    +
    size_t write_array(_In_reads_bytes_opt_(size *count) const void *array, size_t size, size_t count)
    Writes an array of data to the stream.
    Definition stream.hpp:400
    +
    void write_byte(uint8_t byte, fsize_t amount=1)
    Writes a byte of data.
    Definition stream.hpp:221
    +
    basic & read_data(T &data)
    Reads one primitive data type.
    Definition stream.hpp:259
    +
    Buffered read/write stream.
    Definition stream.hpp:1394
    +
    virtual void flush()
    Persists volatile element data.
    Definition stream.hpp:1503
    +
    virtual size_t read(_Out_writes_bytes_to_opt_(length, return) void *data, size_t length)
    Reads block of data from the stream.
    Definition stream.hpp:1424
    +
    virtual size_t write(_In_reads_bytes_opt_(length) const void *data, size_t length)
    Writes block of data to the stream.
    Definition stream.hpp:1460
    +
    Buffered OS data stream (file, pipe, socket...)
    Definition stream.hpp:2325
    +
    Cached file.
    Definition stream.hpp:1804
    +
    virtual time_point ctime() const
    Returns file creation time.
    Definition stream.hpp:2066
    +
    virtual void truncate()
    Sets file size - truncates the remainder of file content from the current file position to the end of...
    Definition stream.hpp:2045
    +
    virtual size_t read(_Out_writes_bytes_to_opt_(length, return) void *data, size_t length)
    Reads block of data from the stream.
    Definition stream.hpp:1871
    +
    virtual time_point atime() const
    Returns file access time.
    Definition stream.hpp:2071
    +
    virtual fsize_t size()
    Returns file size Should the file size cannot be determined, the method returns fsize_max and it does...
    Definition stream.hpp:2038
    +
    virtual void unlock(fpos_t offset, fsize_t length)
    Unlocks file section for exclusive access.
    Definition stream.hpp:2032
    +
    virtual time_point mtime() const
    Returns file modification time.
    Definition stream.hpp:2080
    +
    virtual void close()
    Closes the stream.
    Definition stream.hpp:1986
    +
    virtual void set_mtime(time_point date)
    Sets file modification time.
    Definition stream.hpp:2102
    +
    virtual void lock(fpos_t offset, fsize_t length)
    Locks file section for exclusive access.
    Definition stream.hpp:2026
    +
    virtual void flush()
    Persists volatile element data.
    Definition stream.hpp:1995
    +
    virtual size_t write(_In_reads_bytes_opt_(length) const void *data, size_t length)
    Writes block of data to the stream.
    Definition stream.hpp:1933
    +
    virtual void set_ctime(time_point date)
    Sets file create time.
    Definition stream.hpp:2089
    +
    virtual fpos_t tell() const
    Returns absolute file position in file or fpos_max if fails. This method does not update stream state...
    Definition stream.hpp:2021
    +
    virtual void set_atime(time_point date)
    Sets file access time.
    Definition stream.hpp:2094
    +
    virtual fpos_t seek(foff_t offset, seek_t how=seek_t::beg)
    Seeks to specified relative file position.
    Definition stream.hpp:2006
    +
    Cached file-system file.
    Definition stream.hpp:3095
    +
    cached_file(const stdex::sstring &filename, int mode, size_t cache_size=default_cache_size)
    Opens file.
    Definition stream.hpp:3125
    +
    void open(const stdex::sstring &filename, int mode)
    Opens file.
    Definition stream.hpp:3159
    +
    void open(const schar_t *filename, int mode)
    Opens file.
    Definition stream.hpp:3138
    +
    cached_file(const schar_t *filename, int mode, size_t cache_size=default_cache_size)
    Opens file.
    Definition stream.hpp:3111
    +
    Modifies data on the fly when reading from/writing to a source stream. Could also be used to modify r...
    Definition stream.hpp:1022
    +
    virtual void flush()
    Persists volatile element data.
    Definition stream.hpp:1073
    +
    virtual void close()
    Closes the stream.
    Definition stream.hpp:1067
    +
    virtual size_t read(_Out_writes_bytes_to_opt_(length, return) void *data, size_t length)
    Reads block of data from the stream.
    Definition stream.hpp:1051
    +
    virtual size_t write(_In_reads_bytes_opt_(length) const void *data, size_t length)
    Writes block of data to the stream.
    Definition stream.hpp:1059
    +
    Compares multiple files to perform the same.
    Definition stream.hpp:4018
    +
    virtual fsize_t size()
    Returns file size Should the file size cannot be determined, the method returns fsize_max and it does...
    Definition stream.hpp:4153
    +
    virtual void truncate()
    Sets file size - truncates the remainder of file content from the current file position to the end of...
    Definition stream.hpp:4170
    +
    virtual size_t write(_In_reads_bytes_opt_(length) const void *data, size_t length)
    Writes block of data to the stream.
    Definition stream.hpp:4048
    +
    virtual void close()
    Closes the stream.
    Definition stream.hpp:4081
    +
    virtual void lock(fpos_t offset, fsize_t length)
    Locks file section for exclusive access.
    Definition stream.hpp:4127
    +
    virtual void unlock(fpos_t offset, fsize_t length)
    Unlocks file section for exclusive access.
    Definition stream.hpp:4140
    +
    virtual fpos_t seek(foff_t offset, seek_t how=seek_t::beg)
    Seeks to specified relative file position.
    Definition stream.hpp:4098
    +
    virtual fpos_t tell() const
    Returns absolute file position in file or fpos_max if fails. This method does not update stream state...
    Definition stream.hpp:4115
    +
    virtual void flush()
    Persists volatile element data.
    Definition stream.hpp:4066
    +
    virtual size_t read(_Out_writes_bytes_to_opt_(length, return) void *data, size_t length)
    Reads block of data from the stream.
    Definition stream.hpp:4025
    +
    In-memory FIFO queue.
    Definition stream.hpp:3919
    +
    virtual void close()
    Closes the stream.
    Definition stream.hpp:3989
    +
    virtual size_t write(_In_reads_bytes_opt_(length) const void *data, size_t length)
    Writes block of data to the stream.
    Definition stream.hpp:3966
    +
    size_t size() const
    Returns total size of pending data in the queue.
    Definition stream.hpp:4003
    +
    virtual size_t read(_Out_writes_bytes_to_opt_(length, return) void *data, size_t length)
    Reads block of data from the stream.
    Definition stream.hpp:3938
    +
    Limits file reading/writing to a predefined window.
    Definition stream.hpp:1694
    +
    virtual void truncate()
    Sets file size - truncates the remainder of file content from the current file position to the end of...
    Definition stream.hpp:1787
    +
    virtual void flush()
    Persists volatile element data.
    Definition stream.hpp:1737
    +
    virtual void skip(fsize_t amount)
    Skips given amount of bytes of data on the stream.
    Definition stream.hpp:1750
    +
    virtual fpos_t seek(foff_t offset, seek_t how=seek_t::beg)
    Seeks to specified relative file position.
    Definition stream.hpp:1743
    +
    virtual fsize_t size()
    Returns file size Should the file size cannot be determined, the method returns fsize_max and it does...
    Definition stream.hpp:1782
    +
    virtual size_t write(_In_reads_bytes_opt_(length) const void *data, size_t length)
    Writes block of data to the stream.
    Definition stream.hpp:1717
    +
    virtual void lock(fpos_t offset, fsize_t length)
    Locks file section for exclusive access.
    Definition stream.hpp:1762
    +
    virtual size_t read(_Out_writes_bytes_to_opt_(length, return) void *data, size_t length)
    Reads block of data from the stream.
    Definition stream.hpp:1703
    +
    virtual void unlock(fpos_t offset, fsize_t length)
    Unlocks file section for exclusive access.
    Definition stream.hpp:1772
    +
    virtual fpos_t tell() const
    Returns absolute file position in file or fpos_max if fails. This method does not update stream state...
    Definition stream.hpp:1756
    +
    virtual void close()
    Closes the stream.
    Definition stream.hpp:1731
    +
    File-system file.
    Definition stream.hpp:2691
    +
    file(const stdex::sstring &filename, int mode)
    Opens file.
    Definition stream.hpp:2712
    +
    static bool readonly(const stdex::sstring &filename)
    Checks if file/folder/symlink is read-only.
    Definition stream.hpp:3084
    +
    virtual time_point mtime() const
    Returns file modification time.
    Definition stream.hpp:2967
    +
    virtual void unlock(fpos_t offset, fsize_t length)
    Unlocks file section for exclusive access.
    Definition stream.hpp:2860
    +
    file(const schar_t *filename, int mode)
    Opens file.
    Definition stream.hpp:2701
    +
    virtual void set_ctime(time_point date)
    Sets file create time.
    Definition stream.hpp:2981
    +
    static bool readonly(const stdex::schar_t *filename)
    Checks if file/folder/symlink is read-only.
    Definition stream.hpp:3066
    +
    static bool exists(const stdex::sstring &filename)
    Checks if file/folder/symlink likely exists.
    Definition stream.hpp:3054
    +
    virtual time_point atime() const
    Returns file access time.
    Definition stream.hpp:2953
    +
    void open(const schar_t *filename, int mode)
    Opens file.
    Definition stream.hpp:2720
    +
    virtual void set_mtime(time_point date)
    Sets file modification time.
    Definition stream.hpp:3015
    +
    virtual void set_atime(time_point date)
    Sets file access time.
    Definition stream.hpp:2995
    +
    virtual void lock(fpos_t offset, fsize_t length)
    Locks file section for exclusive access.
    Definition stream.hpp:2837
    +
    virtual void truncate()
    Sets file size - truncates the remainder of file content from the current file position to the end of...
    Definition stream.hpp:2903
    +
    virtual time_point ctime() const
    Returns file creation time.
    Definition stream.hpp:2943
    +
    void open(const stdex::sstring &filename, int mode)
    Opens file.
    Definition stream.hpp:2793
    +
    virtual fsize_t size()
    Returns file size Should the file size cannot be determined, the method returns fsize_max and it does...
    Definition stream.hpp:2885
    +
    virtual fpos_t seek(foff_t offset, seek_t how=seek_t::beg)
    Seeks to specified relative file position.
    Definition stream.hpp:2798
    +
    virtual fpos_t tell() const
    Returns absolute file position in file or fpos_max if fails. This method does not update stream state...
    Definition stream.hpp:2819
    +
    static bool exists(const stdex::schar_t *filename)
    Checks if file/folder/symlink likely exists.
    Definition stream.hpp:3039
    +
    Limits reading from/writing to stream to a predefined number of bytes.
    Definition stream.hpp:1551
    +
    fsize_t read_limit
    Number of bytes left that may be read from the stream.
    Definition stream.hpp:1603
    +
    virtual size_t read(_Out_writes_bytes_to_opt_(length, return) void *data, size_t length)
    Reads block of data from the stream.
    Definition stream.hpp:1559
    +
    virtual size_t write(_In_reads_bytes_opt_(length) const void *data, size_t length)
    Writes block of data to the stream.
    Definition stream.hpp:1580
    +
    fsize_t write_limit
    Number of bytes left, that can be written to the stream.
    Definition stream.hpp:1604
    +
    In-memory file.
    Definition stream.hpp:3172
    +
    memory_file(const schar_t *filename, int mode)
    Loads content from file-system file.
    Definition stream.hpp:3250
    +
    memory_file & write_str(const std::basic_string< _Elem, _Traits, _Ax > &data)
    Writes string to the stream length-prefixed.
    Definition stream.hpp:3634
    +
    size_t m_size
    file size
    Definition stream.hpp:3906
    +
    void get(fpos_t offset, T &data)
    Reads data from specified file location This does not move file pointer. It checks for data size Assu...
    Definition stream.hpp:3844
    +
    size_t write_stream(basic &stream, size_t amount=SIZE_MAX)
    Writes content of another stream.
    Definition stream.hpp:3669
    +
    uint8_t * m_data
    file data
    Definition stream.hpp:3903
    +
    memory_file & read_data(T &data)
    Reads one primitive data type.
    Definition stream.hpp:3423
    +
    virtual void close()
    Closes the stream.
    Definition stream.hpp:3719
    +
    virtual size_t read(_Out_writes_bytes_to_opt_(length, return) void *data, size_t length)
    Reads block of data from the stream.
    Definition stream.hpp:3384
    +
    virtual fpos_t tell() const
    Returns absolute file position in file or fpos_max if fails. This method does not update stream state...
    Definition stream.hpp:3750
    +
    size_t m_reserved
    reserved file size
    Definition stream.hpp:3907
    +
    memory_file(size_t size, state_t state=state_t::ok)
    Creates an empty file of reserved size.
    Definition stream.hpp:3193
    +
    void reserve(size_t required, bool tight=false) noexcept
    Reallocates memory.
    Definition stream.hpp:3275
    +
    memory_file(const stdex::sstring &filename, int mode)
    Loads content from file-system file.
    Definition stream.hpp:3261
    +
    memory_file & read_str(std::basic_string< _Elem, _Traits, _Ax > &data)
    Reads length-prefixed string from the stream.
    Definition stream.hpp:3463
    +
    void write_byte(uint8_t byte, size_t amount=1)
    Writes a byte of data.
    Definition stream.hpp:3518
    +
    void set(fpos_t offset, const T data)
    Writes data to specified file location This does not move file pointer nor update file size....
    Definition stream.hpp:3810
    +
    void load(const stdex::sstring &filename, int mode)
    Loads content from a file-system file.
    Definition stream.hpp:3337
    +
    size_t m_offset
    file pointer
    Definition stream.hpp:3905
    +
    void save(const schar_t *filename, int mode)
    Saves content to a file-system file.
    Definition stream.hpp:3348
    +
    void load(const schar_t *filename, int mode)
    Loads content from a file-system file.
    Definition stream.hpp:3304
    +
    virtual fsize_t size()
    Returns file size Should the file size cannot be determined, the method returns fsize_max and it does...
    Definition stream.hpp:3755
    +
    virtual fpos_t seek(foff_t offset, seek_t how=seek_t::beg)
    Seeks to specified relative file position.
    Definition stream.hpp:3733
    +
    virtual void truncate()
    Sets file size - truncates the remainder of file content from the current file position to the end of...
    Definition stream.hpp:3760
    +
    memory_file & write_data(const T data)
    Writes one primitive data type.
    Definition stream.hpp:3551
    +
    memory_file & write_str(const T *data)
    Writes string to the stream length-prefixed.
    Definition stream.hpp:3589
    +
    void save(const stdex::sstring &filename, int mode)
    Saves content to a file-system file.
    Definition stream.hpp:3374
    +
    bool m_manage
    may reallocate m_data?
    Definition stream.hpp:3904
    +
    memory_file(void *data, size_t size, bool manage=false, state_t state=state_t::ok)
    Creates a file based on available data.
    Definition stream.hpp:3240
    +
    virtual size_t write(_In_reads_bytes_opt_(length) const void *data, size_t length)
    Writes block of data to the stream.
    Definition stream.hpp:3494
    +
    memory_file(void *data, size_t size, size_t reserved, bool manage=false, state_t state=state_t::ok)
    Creates a file based on available data.
    Definition stream.hpp:3217
    +
    const void * data() const
    Returns pointer to data.
    Definition stream.hpp:3382
    +
    Definition stream.hpp:1170
    enum stdex::stream::replicator::worker::op_t op
    Operation to perform.
    -
    size_t num_written
    Number of bytes written.
    Definition stream.hpp:1218
    -
    size_t length
    Byte limit of data to write.
    Definition stream.hpp:1217
    -
    const void * data
    Data to write.
    Definition stream.hpp:1216
    -
    Replicates writing of the same data to multiple streams.
    Definition stream.hpp:1086
    -
    void push_back(basic *source)
    Adds stream on the list.
    Definition stream.hpp:1105
    -
    virtual void flush()
    Persists volatile element data.
    Definition stream.hpp:1162
    -
    void remove(basic *source)
    Removes stream from the list.
    Definition stream.hpp:1113
    -
    virtual size_t write(_In_reads_bytes_opt_(length) const void *data, size_t length)
    Writes block of data to the stream.
    Definition stream.hpp:1130
    -
    virtual void close()
    Closes the stream.
    Definition stream.hpp:1157
    -
    Socket stream.
    Definition stream.hpp:2346
    -
    virtual void close()
    Closes the stream.
    Definition stream.hpp:2448
    -
    socket(int af, int type, int protocol)
    Creates a socket.
    Definition stream.hpp:2381
    -
    SOCKET get() const noexcept
    Returns socket handle.
    Definition stream.hpp:2402
    -
    virtual size_t read(_Out_writes_bytes_to_opt_(length, return) void *data, size_t length)
    Reads block of data from the stream.
    Definition stream.hpp:2404
    -
    virtual size_t write(_In_reads_bytes_opt_(length) const void *data, size_t length)
    Writes block of data to the stream.
    Definition stream.hpp:2428
    -
    Limits reading from/writing to stream to a predefined window.
    Definition stream.hpp:1610
    -
    fpos_t write_offset
    Number of bytes to discard on write.
    Definition stream.hpp:1686
    -
    virtual size_t write(_In_reads_bytes_opt_(length) const void *data, size_t length)
    Writes block of data to the stream.
    Definition stream.hpp:1647
    -
    virtual size_t read(_Out_writes_bytes_to_opt_(length, return) void *data, size_t length)
    Reads block of data from the stream.
    Definition stream.hpp:1618
    -
    fpos_t read_offset
    Number of bytes to skip on read.
    Definition stream.hpp:1685
    -
    Operating system object (file, pipe, anything with an OS handle etc.)
    Definition system.hpp:91
    -
    virtual void close()
    Closes object.
    Definition system.hpp:132
    +
    size_t num_written
    Number of bytes written.
    Definition stream.hpp:1219
    +
    size_t length
    Byte limit of data to write.
    Definition stream.hpp:1218
    +
    const void * data
    Data to write.
    Definition stream.hpp:1217
    +
    Replicates writing of the same data to multiple streams.
    Definition stream.hpp:1087
    +
    void push_back(basic *source)
    Adds stream on the list.
    Definition stream.hpp:1106
    +
    virtual void flush()
    Persists volatile element data.
    Definition stream.hpp:1163
    +
    void remove(basic *source)
    Removes stream from the list.
    Definition stream.hpp:1114
    +
    virtual size_t write(_In_reads_bytes_opt_(length) const void *data, size_t length)
    Writes block of data to the stream.
    Definition stream.hpp:1131
    +
    virtual void close()
    Closes the stream.
    Definition stream.hpp:1158
    +
    Socket stream.
    Definition stream.hpp:2347
    +
    virtual void close()
    Closes the stream.
    Definition stream.hpp:2449
    +
    socket(int af, int type, int protocol)
    Creates a socket.
    Definition stream.hpp:2382
    +
    SOCKET get() const noexcept
    Returns socket handle.
    Definition stream.hpp:2403
    +
    virtual size_t read(_Out_writes_bytes_to_opt_(length, return) void *data, size_t length)
    Reads block of data from the stream.
    Definition stream.hpp:2405
    +
    virtual size_t write(_In_reads_bytes_opt_(length) const void *data, size_t length)
    Writes block of data to the stream.
    Definition stream.hpp:2429
    +
    Limits reading from/writing to stream to a predefined window.
    Definition stream.hpp:1611
    +
    fpos_t write_offset
    Number of bytes to discard on write.
    Definition stream.hpp:1687
    +
    virtual size_t write(_In_reads_bytes_opt_(length) const void *data, size_t length)
    Writes block of data to the stream.
    Definition stream.hpp:1648
    +
    virtual size_t read(_Out_writes_bytes_to_opt_(length, return) void *data, size_t length)
    Reads block of data from the stream.
    Definition stream.hpp:1619
    +
    fpos_t read_offset
    Number of bytes to skip on read.
    Definition stream.hpp:1686
    +
    Operating system object (file, pipe, anything with an OS handle etc.)
    Definition system.hpp:93
    +
    virtual void close()
    Closes object.
    Definition system.hpp:134
    Numerical interval.
    Definition interval.hpp:18
    bool contains(T x) const
    Is value in interval?
    Definition interval.hpp:79
    T size() const
    Returns interval size.
    Definition interval.hpp:47
    T end
    interval end
    Definition interval.hpp:20
    T start
    interval start
    Definition interval.hpp:19
    -
    Definition stream.hpp:1527
    -
    Definition stream.hpp:4006
    +
    Definition stream.hpp:1528
    +
    Definition stream.hpp:4007
    diff --git a/string_8hpp_source.html b/string_8hpp_source.html index c1849c031..1203dff1d 100644 --- a/string_8hpp_source.html +++ b/string_8hpp_source.html @@ -99,1164 +99,1123 @@ $(document).ready(function() { init_codefold(0); });
    15#include <time.h>
    16#if defined(_WIN32)
    17#include "windows.h"
    -
    18#include <rpc.h>
    -
    19#elif defined(__APPLE__)
    -
    20#include <uuid/uuid.h>
    -
    21#include <xlocale.h>
    -
    22#else
    -
    23#include <xlocale.h>
    -
    24#endif
    -
    25#include <algorithm>
    -
    26#include <locale>
    -
    27#include <memory>
    -
    28#include <stdexcept>
    -
    29
    -
    30namespace stdex
    -
    31{
    -
    32#ifdef _WIN32
    -
    33 using locale_t = _locale_t;
    -
    34
    -
    35 inline locale_t create_locale(_In_ int category, _In_z_ const char* locale) { return _create_locale(category, locale); }
    -
    36 inline locale_t create_locale(_In_ int category, _In_z_ const wchar_t* locale) { return _wcreate_locale(category, locale); }
    -
    37 inline void free_locale(_In_opt_ locale_t locale) { _free_locale(locale); }
    -
    38#else
    -
    39 using locale_t = ::locale_t;
    -
    40
    -
    41 inline locale_t create_locale(_In_ int category, _In_z_ const char* locale)
    -
    42 {
    -
    43 int mask = 0;
    -
    44 switch (category) {
    -
    45 case LC_ALL : mask = LC_ALL_MASK ; break;
    -
    46 case LC_COLLATE : mask = LC_COLLATE_MASK ; break;
    -
    47 case LC_CTYPE : mask = LC_CTYPE_MASK ; break;
    -
    48 case LC_MESSAGES: mask = LC_MESSAGES_MASK; break;
    -
    49 case LC_MONETARY: mask = LC_MONETARY_MASK; break;
    -
    50 case LC_NUMERIC : mask = LC_NUMERIC_MASK ; break;
    -
    51 case LC_TIME : mask = LC_TIME_MASK ; break;
    -
    52 }
    -
    53 return newlocale(mask, locale, LC_GLOBAL_LOCALE);
    -
    54 }
    +
    18#elif defined(__APPLE__)
    +
    19#include <xlocale.h>
    +
    20#endif
    +
    21#include <algorithm>
    +
    22#include <climits>
    +
    23#include <locale>
    +
    24#include <memory>
    +
    25#include <stdexcept>
    +
    26
    +
    27namespace stdex
    +
    28{
    +
    29#ifdef _WIN32
    +
    30 using locale_t = _locale_t;
    +
    31
    +
    32 inline locale_t create_locale(_In_ int category, _In_z_ const char* locale) { return _create_locale(category, locale); }
    +
    33 inline locale_t create_locale(_In_ int category, _In_z_ const wchar_t* locale) { return _wcreate_locale(category, locale); }
    +
    34 inline void free_locale(_In_opt_ locale_t locale) { _free_locale(locale); }
    +
    35#else
    +
    36 using locale_t = ::locale_t;
    +
    37
    +
    38 inline locale_t create_locale(_In_ int category, _In_z_ const char* locale)
    +
    39 {
    +
    40 int mask = 0;
    +
    41 switch (category) {
    +
    42 case LC_ALL : mask = LC_ALL_MASK ; break;
    +
    43 case LC_COLLATE : mask = LC_COLLATE_MASK ; break;
    +
    44 case LC_CTYPE : mask = LC_CTYPE_MASK ; break;
    +
    45 case LC_MESSAGES: mask = LC_MESSAGES_MASK; break;
    +
    46 case LC_MONETARY: mask = LC_MONETARY_MASK; break;
    +
    47 case LC_NUMERIC : mask = LC_NUMERIC_MASK ; break;
    +
    48 case LC_TIME : mask = LC_TIME_MASK ; break;
    +
    49 }
    +
    50 return newlocale(mask, locale, LC_GLOBAL_LOCALE);
    +
    51 }
    +
    52
    +
    53 inline void free_locale(_In_opt_ locale_t locale) { freelocale(locale); }
    +
    54#endif
    55
    -
    56 inline void free_locale(_In_opt_ locale_t locale) { freelocale(locale); }
    -
    57#endif
    -
    58
    -
    - -
    63 {
    -
    -
    67 void operator()(_In_ locale_t locale) const
    -
    68 {
    -
    69 free_locale(locale);
    -
    70 }
    +
    + +
    60 {
    +
    +
    64 void operator()(_In_ locale_t locale) const
    +
    65 {
    +
    66 free_locale(locale);
    +
    67 }
    -
    71 };
    +
    68 };
    -
    72
    -
    76#if defined(_WIN32)
    -
    77 using locale = std::unique_ptr<__crt_locale_pointers, free_locale_delete>;
    -
    78#elif defined(__APPLE__)
    -
    79 using locale = std::unique_ptr<struct _xlocale, free_locale_delete>;
    -
    80#else
    -
    81 using locale = std::unique_ptr<struct __locale_struct, free_locale_delete>;
    -
    82#endif
    -
    83
    -
    87 const locale locale_C(create_locale(LC_ALL, "C"));
    -
    88
    -
    92#ifdef _WIN32
    -
    93 typedef wchar_t utf16_t;
    -
    94#else
    -
    95 typedef char16_t utf16_t;
    -
    96#endif
    -
    97
    -
    103 inline bool is_high_surrogate(_In_ utf16_t chr)
    -
    104 {
    -
    105 return 0xd800 < chr && chr < 0xdc00;
    -
    106 }
    -
    107
    -
    113 inline bool is_low_surrogate(_In_ utf16_t chr)
    -
    114 {
    -
    115 return 0xdc00 < chr && chr < 0xe000;
    -
    116 }
    -
    117
    -
    123 inline bool is_surrogate_pair(_In_reads_(2) const utf16_t* str)
    -
    124 {
    -
    125 return is_high_surrogate(str[0]) && is_low_surrogate(str[1]);
    -
    126 }
    -
    127
    -
    133 inline char32_t surrogate_pair_to_ucs4(_In_reads_(2) const utf16_t* str)
    -
    134 {
    -
    135 _Assume_(is_surrogate_pair(str));
    -
    136 return
    -
    137 ((char32_t)(str[0] - 0xd800) << 10) +
    -
    138 (char32_t)(str[1] - 0xdc00) +
    -
    139 0x10000;
    -
    140 }
    -
    141
    -
    147 inline void ucs4_to_surrogate_pair(_Out_writes_(2) utf16_t* str, _In_ char32_t chr)
    -
    148 {
    -
    149 _Assume_(chr >= 0x10000);
    -
    150 chr -= 0x10000;
    -
    151 str[0] = 0xd800 + (char32_t)((chr >> 10) & 0x3ff);
    -
    152 str[1] = 0xdc00 + (char32_t)(chr & 0x3ff);
    -
    153 }
    -
    154
    -
    160 inline bool iscombining(_In_ char32_t chr)
    -
    161 {
    -
    162 return
    -
    163 (0x0300 <= chr && chr < 0x0370) ||
    -
    164 (0x1dc0 <= chr && chr < 0x1e00) ||
    -
    165 (0x20d0 <= chr && chr < 0x2100) ||
    -
    166 (0xfe20 <= chr && chr < 0xfe30);
    -
    167 }
    -
    168
    -
    174 template <class T>
    -
    175 inline size_t islbreak(_In_ T chr)
    -
    176 {
    -
    177 return chr == '\n' || chr == '\r';
    -
    178 }
    -
    179
    -
    186 template <class T>
    -
    187 inline size_t islbreak(_In_reads_or_z_opt_(count) const T* chr, _In_ size_t count)
    -
    188 {
    -
    189 _Assume_(chr || !count);
    -
    190 if (count >= 2 && ((chr[0] == '\r' && chr[1] == '\n') || (chr[0] == '\n' && chr[1] == '\r')))
    -
    191 return 2;
    -
    192 if (count > 1 && (chr[0] == '\n' || chr[0] == '\r'))
    -
    193 return 1;
    -
    194 return 0;
    -
    195 }
    -
    196
    -
    203 inline size_t glyphlen(_In_reads_or_z_opt_(count) const wchar_t* glyph, _In_ size_t count)
    -
    204 {
    -
    205 _Assume_(glyph || !count);
    -
    206 if (count) {
    -
    207#ifdef _WIN32
    -
    208 size_t i = count < 2 || !is_surrogate_pair(glyph) ? 1 : 2;
    -
    209#else
    -
    210 size_t i = 1;
    -
    211#endif
    -
    212 for (; i < count && iscombining(glyph[i]); ++i);
    -
    213 return i;
    -
    214 }
    -
    215 return 0;
    -
    216 }
    -
    217
    -
    225 template <class T>
    -
    226 inline size_t strlen(_In_z_ const T* str)
    -
    227 {
    -
    228 _Assume_(str);
    -
    229 size_t i;
    -
    230 for (i = 0; str[i]; ++i);
    -
    231 return i;
    -
    232 }
    -
    233
    -
    242 template <class T>
    -
    243 inline size_t strnlen(_In_reads_or_z_opt_(count) const T* str, _In_ size_t count)
    -
    244 {
    -
    245 _Assume_(str || !count);
    -
    246 size_t i;
    -
    247 for (i = 0; i < count && str[i]; ++i);
    -
    248 return i;
    -
    249 }
    -
    250
    -
    251 constexpr auto npos{ static_cast<size_t>(-1) };
    -
    252
    -
    261 template <class T>
    -
    262 inline size_t strchr(_In_z_ const T* str, _In_ T chr)
    -
    263 {
    -
    264 _Assume_(str);
    -
    265 for (size_t i = 0; str[i]; ++i)
    -
    266 if (str[i] == chr) return i;
    -
    267 return npos;
    -
    268 }
    -
    269
    -
    279 template <class T>
    -
    280 inline size_t strnchr(
    -
    281 _In_reads_or_z_opt_(count) const T* str,
    -
    282 _In_ size_t count,
    -
    283 _In_ T chr)
    -
    284 {
    -
    285 _Assume_(str || !count);
    -
    286 for (size_t i = 0; i < count && str[i]; ++i)
    -
    287 if (str[i] == chr) return i;
    -
    288 return npos;
    -
    289 }
    -
    290
    -
    300 template <class T>
    -
    301 inline size_t strrnchr(
    -
    302 _In_reads_or_z_opt_(count) const T* str,
    -
    303 _In_ size_t count,
    -
    304 _In_ T chr)
    -
    305 {
    -
    306 _Assume_(str || !count);
    -
    307 size_t z = npos;
    -
    308 for (size_t i = 0; i < count && str[i]; ++i)
    -
    309 if (str[i] == chr) z = i;
    -
    310 return z;
    -
    311 }
    -
    312
    -
    322 template <class T>
    -
    323 inline size_t strnichr(
    -
    324 _In_reads_or_z_opt_(count) const T* str,
    -
    325 _In_ size_t count,
    -
    326 _In_ T chr,
    -
    327 _In_ const std::locale& locale)
    -
    328 {
    -
    329 _Assume_(str || !count);
    -
    330 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
    -
    331 chr = ctype.tolower(chr);
    -
    332 for (size_t i = 0; i < count && str[i]; ++i)
    -
    333 if (ctype.tolower(str[i]) == chr) return i;
    -
    334 return npos;
    -
    335 }
    -
    336
    -
    346 template <class T>
    -
    347 inline size_t strrnichr(
    -
    348 _In_reads_or_z_opt_(count) const T* str,
    -
    349 _In_ size_t count,
    -
    350 _In_ T chr,
    -
    351 _In_ const std::locale& locale)
    -
    352 {
    -
    353 _Assume_(str || !count);
    -
    354 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
    -
    355 chr = ctype.tolower(chr);
    -
    356 size_t z = npos;
    -
    357 for (size_t i = 0; i < count && str[i]; ++i)
    -
    358 if (ctype.tolower(str[i]) == chr) z = i;
    -
    359 return z;
    -
    360 }
    -
    361
    -
    370 template <class T1, class T2>
    -
    371 inline int strcmp(const T1* str1, const T2* str2)
    -
    372 {
    -
    373 _Assume_(str1 && str2);
    -
    374 T1 a; T2 b;
    -
    375 for (size_t i = 0; (a = str1[i]) | (b = str2[i]); ++i) {
    -
    376 if (a > b) return +1;
    -
    377 if (a < b) return -1;
    -
    378 }
    -
    379 return 0;
    -
    380 }
    -
    381
    -
    392 template <class T1, class T2>
    -
    393 inline int strncmp(
    -
    394 _In_reads_or_z_opt_(count1) const T1* str1, _In_ size_t count1,
    -
    395 _In_reads_or_z_opt_(count2) const T2* str2, _In_ size_t count2)
    -
    396 {
    -
    397 _Assume_(str1 || !count1);
    -
    398 _Assume_(str2 || !count2);
    -
    399 size_t i; T1 a; T2 b;
    -
    400 for (i = 0; i < count1 && i < count2 && ((a = str1[i]) | (b = str2[i])); ++i) {
    -
    401 if (a > b) return +1;
    -
    402 if (a < b) return -1;
    -
    403 }
    -
    404 if (i < count1 && str1[i]) return +1;
    -
    405 if (i < count2 && str2[i]) return -1;
    -
    406 return 0;
    -
    407 }
    -
    408
    -
    418 template <class T1, class T2>
    -
    419 inline int strncmp(_In_reads_or_z_opt_(count) const T1* str1, _In_reads_or_z_opt_(count) const T2* str2, _In_ size_t count)
    -
    420 {
    -
    421 _Assume_((str1 && str2) || !count);
    -
    422 size_t i; T1 a; T2 b;
    -
    423 for (i = 0; i < count && ((a = str1[i]) | (b = str2[i])); ++i) {
    -
    424 if (a > b) return +1;
    -
    425 if (a < b) return -1;
    -
    426 }
    -
    427 if (i < count && str1[i]) return +1;
    -
    428 if (i < count && str2[i]) return -1;
    -
    429 return 0;
    -
    430 }
    -
    431
    -
    442 template <class T>
    -
    443 inline int strncoll(
    -
    444 _In_reads_or_z_opt_(count1) const T* str1, _In_ size_t count1,
    -
    445 _In_reads_or_z_opt_(count2) const T* str2, _In_ size_t count2,
    -
    446 _In_ const std::locale& locale)
    -
    447 {
    -
    448 _Assume_(str1 || !count1);
    -
    449 _Assume_(str2 || !count2);
    -
    450 auto& collate = std::use_facet<std::collate<T>>(locale);
    -
    451 return collate.compare(str1, str1 + count1, str2, str2 + count2);
    -
    452 }
    -
    453
    -
    462 template <class T1, class T2>
    -
    463 inline int stricmp(_In_z_ const T1* str1, _In_z_ const T2* str2, _In_ const std::locale& locale)
    -
    464 {
    -
    465 _Assume_(str1);
    -
    466 _Assume_(str2);
    -
    467 size_t i; T1 a; T2 b;
    -
    468 const auto& ctype1 = std::use_facet<std::ctype<T1>>(locale);
    -
    469 const auto& ctype2 = std::use_facet<std::ctype<T2>>(locale);
    -
    470 for (i = 0; (a = ctype1.tolower(str1[i])) | (b = ctype2.tolower(str2[i])); i++) {
    -
    471 if (a > b) return +1;
    -
    472 if (a < b) return -1;
    -
    473 }
    -
    474 if (str1[i]) return +1;
    -
    475 if (str2[i]) return -1;
    -
    476 return 0;
    -
    477 }
    -
    478
    -
    488 template <class T1, class T2>
    -
    489 inline int strnicmp(_In_reads_or_z_opt_(count) const T1* str1, _In_reads_or_z_opt_(count) const T2* str2, _In_ size_t count, _In_ const std::locale& locale)
    -
    490 {
    -
    491 _Assume_(str1 || !count);
    -
    492 _Assume_(str2 || !count);
    -
    493 size_t i; T1 a; T2 b;
    -
    494 const auto& ctype1 = std::use_facet<std::ctype<T1>>(locale);
    -
    495 const auto& ctype2 = std::use_facet<std::ctype<T2>>(locale);
    -
    496 for (i = 0; i < count && ((a = ctype1.tolower(str1[i])) | (b = ctype2.tolower(str2[i]))); i++) {
    -
    497 if (a > b) return +1;
    -
    498 if (a < b) return -1;
    -
    499 }
    -
    500 if (i < count && str1[i]) return +1;
    -
    501 if (i < count && str2[i]) return -1;
    -
    502 return 0;
    -
    503 }
    -
    504
    -
    515 template <class T1, class T2>
    -
    516 inline int strnicmp(
    -
    517 _In_reads_or_z_opt_(count1) const T1* str1, _In_ size_t count1,
    -
    518 _In_reads_or_z_opt_(count2) const T2* str2, _In_ size_t count2,
    -
    519 _In_ const std::locale& locale)
    -
    520 {
    -
    521 _Assume_(str1 || !count1);
    -
    522 _Assume_(str2 || !count2);
    -
    523 size_t i; T1 a; T2 b;
    -
    524 const auto& ctype1 = std::use_facet<std::ctype<T1>>(locale);
    -
    525 const auto& ctype2 = std::use_facet<std::ctype<T2>>(locale);
    -
    526 for (i = 0; i < count1 && i < count2 && ((a = ctype1.tolower(str1[i])) | (b = ctype2.tolower(str2[i]))); i++) {
    -
    527 if (a > b) return +1;
    -
    528 if (a < b) return -1;
    -
    529 }
    -
    530 if (i < count1 && str1[i]) return +1;
    -
    531 if (i < count2 && str2[i]) return -1;
    -
    532 return 0;
    -
    533 }
    -
    534
    -
    543 template <class T1, class T2>
    -
    544 inline size_t strstr(
    -
    545 _In_z_ const T1* str,
    -
    546 _In_z_ const T2* sample)
    -
    547 {
    -
    548 _Assume_(str);
    -
    549 _Assume_(sample);
    -
    550 for (size_t offset = 0;; ++offset) {
    -
    551 for (size_t i = offset, j = 0;; ++i, ++j) {
    -
    552 if (!sample[j])
    -
    553 return offset;
    -
    554 if (!str[i])
    -
    555 return npos;
    -
    556 if (str[i] != sample[j])
    -
    557 break;
    -
    558 }
    -
    559 }
    -
    560 }
    -
    561
    -
    571 template <class T1, class T2>
    -
    572 inline size_t strnstr(
    -
    573 _In_reads_or_z_opt_(count) const T1* str,
    -
    574 _In_ size_t count,
    -
    575 _In_z_ const T2* sample)
    -
    576 {
    -
    577 _Assume_(str || !count);
    -
    578 _Assume_(sample);
    -
    579 for (size_t offset = 0;; ++offset) {
    -
    580 for (size_t i = offset, j = 0;; ++i, ++j) {
    -
    581 if (!sample[j])
    -
    582 return offset;
    -
    583 if (i >= count || !str[i])
    -
    584 return npos;
    -
    585 if (str[i] != sample[j])
    -
    586 break;
    -
    587 }
    -
    588 }
    -
    589 }
    -
    590
    -
    599 template <class T1, class T2>
    -
    600 inline size_t stristr(
    -
    601 _In_z_ const T1* str,
    -
    602 _In_z_ const T2* sample,
    -
    603 _In_ const std::locale& locale)
    -
    604 {
    -
    605 _Assume_(str);
    -
    606 _Assume_(sample);
    -
    607 const auto& ctype1 = std::use_facet<std::ctype<T1>>(locale);
    -
    608 const auto& ctype2 = std::use_facet<std::ctype<T2>>(locale);
    -
    609 for (size_t offset = 0;; ++offset) {
    -
    610 for (size_t i = offset, j = 0;; ++i, ++j) {
    -
    611 if (!sample[j])
    -
    612 return offset;
    -
    613 if (!str[i])
    -
    614 return npos;
    -
    615 if (ctype1.tolower(str[i]) != ctype2.tolower(sample[j]))
    -
    616 break;
    -
    617 }
    -
    618 }
    -
    619 }
    -
    620
    -
    630 template <class T1, class T2>
    -
    631 inline size_t strnistr(
    -
    632 _In_reads_or_z_opt_(count) const T1* str,
    -
    633 _In_ size_t count,
    -
    634 _In_z_ const T2* sample,
    -
    635 _In_ const std::locale& locale)
    -
    636 {
    -
    637 _Assume_(str || !count);
    -
    638 _Assume_(sample);
    -
    639 const auto& ctype1 = std::use_facet<std::ctype<T1>>(locale);
    -
    640 const auto& ctype2 = std::use_facet<std::ctype<T2>>(locale);
    -
    641 for (size_t offset = 0;; ++offset) {
    -
    642 for (size_t i = offset, j = 0;; ++i, ++j) {
    -
    643 if (!sample[j])
    -
    644 return offset;
    -
    645 if (i >= count || !str[i])
    -
    646 return npos;
    -
    647 if (ctype1.tolower(str[i]) != ctype2.tolower(sample[j]))
    -
    648 break;
    -
    649 }
    -
    650 }
    -
    651 }
    -
    652
    -
    661 template <class T1, class T2>
    -
    662 inline size_t strcpy(
    -
    663 _Out_writes_z_(_String_length_(src) + 1) T1* dst,
    -
    664 _In_z_ const T2* src)
    -
    665 {
    -
    666 _Assume_(dst && src);
    -
    667 for (size_t i = 0; ; ++i) {
    -
    668 if ((dst[i] = src[i]) == 0)
    -
    669 return i;
    -
    670 }
    -
    671 }
    -
    672
    -
    682 template <class T1, class T2>
    -
    683 inline size_t strncpy(
    -
    684 _Out_writes_(count) _Post_maybez_ T1* dst,
    -
    685 _In_reads_or_z_opt_(count) const T2* src, _In_ size_t count)
    -
    686 {
    -
    687 _Assume_(dst && src || !count);
    -
    688 for (size_t i = 0; ; ++i) {
    -
    689 if (i >= count)
    -
    690 return i;
    -
    691 if ((dst[i] = src[i]) == 0)
    -
    692 return i;
    -
    693 }
    -
    694 }
    -
    695
    -
    706 template <class T1, class T2>
    -
    707 inline size_t strncpy(
    -
    708 _Out_writes_(count_dst) _Post_maybez_ T1* dst, _In_ size_t count_dst,
    -
    709 _In_reads_or_z_opt_(count_src) const T2* src, _In_ size_t count_src)
    -
    710 {
    -
    711 _Assume_(dst || !count_dst);
    -
    712 _Assume_(src || !count_src);
    -
    713 for (size_t i = 0; ; ++i)
    -
    714 {
    -
    715 if (i >= count_dst)
    +
    69
    +
    73#if defined(_WIN32)
    +
    74 using locale = std::unique_ptr<__crt_locale_pointers, free_locale_delete>;
    +
    75#elif defined(__APPLE__)
    +
    76 using locale = std::unique_ptr<struct _xlocale, free_locale_delete>;
    +
    77#else
    +
    78 using locale = std::unique_ptr<struct __locale_struct, free_locale_delete>;
    +
    79#endif
    +
    80
    +
    84 const locale locale_C(create_locale(LC_ALL, "C"));
    +
    85
    +
    89#ifdef _WIN32
    +
    90 typedef wchar_t utf16_t;
    +
    91#else
    +
    92 typedef char16_t utf16_t;
    +
    93#endif
    +
    94
    +
    100 inline bool is_high_surrogate(_In_ utf16_t chr)
    +
    101 {
    +
    102 return 0xd800 < chr && chr < 0xdc00;
    +
    103 }
    +
    104
    +
    110 inline bool is_low_surrogate(_In_ utf16_t chr)
    +
    111 {
    +
    112 return 0xdc00 < chr && chr < 0xe000;
    +
    113 }
    +
    114
    +
    120 inline bool is_surrogate_pair(_In_reads_(2) const utf16_t* str)
    +
    121 {
    +
    122 return is_high_surrogate(str[0]) && is_low_surrogate(str[1]);
    +
    123 }
    +
    124
    +
    130 inline char32_t surrogate_pair_to_ucs4(_In_reads_(2) const utf16_t* str)
    +
    131 {
    +
    132 _Assume_(is_surrogate_pair(str));
    +
    133 return
    +
    134 ((char32_t)(str[0] - 0xd800) << 10) +
    +
    135 (char32_t)(str[1] - 0xdc00) +
    +
    136 0x10000;
    +
    137 }
    +
    138
    +
    144 inline void ucs4_to_surrogate_pair(_Out_writes_(2) utf16_t* str, _In_ char32_t chr)
    +
    145 {
    +
    146 _Assume_(chr >= 0x10000);
    +
    147 chr -= 0x10000;
    +
    148 str[0] = 0xd800 + (char32_t)((chr >> 10) & 0x3ff);
    +
    149 str[1] = 0xdc00 + (char32_t)(chr & 0x3ff);
    +
    150 }
    +
    151
    +
    157 inline bool iscombining(_In_ char32_t chr)
    +
    158 {
    +
    159 return
    +
    160 (0x0300 <= chr && chr < 0x0370) ||
    +
    161 (0x1dc0 <= chr && chr < 0x1e00) ||
    +
    162 (0x20d0 <= chr && chr < 0x2100) ||
    +
    163 (0xfe20 <= chr && chr < 0xfe30);
    +
    164 }
    +
    165
    +
    171 template <class T>
    +
    172 inline size_t islbreak(_In_ T chr)
    +
    173 {
    +
    174 return chr == '\n' || chr == '\r';
    +
    175 }
    +
    176
    +
    183 template <class T>
    +
    184 inline size_t islbreak(_In_reads_or_z_opt_(count) const T* chr, _In_ size_t count)
    +
    185 {
    +
    186 _Assume_(chr || !count);
    +
    187 if (count >= 2 && ((chr[0] == '\r' && chr[1] == '\n') || (chr[0] == '\n' && chr[1] == '\r')))
    +
    188 return 2;
    +
    189 if (count > 1 && (chr[0] == '\n' || chr[0] == '\r'))
    +
    190 return 1;
    +
    191 return 0;
    +
    192 }
    +
    193
    +
    200 inline size_t glyphlen(_In_reads_or_z_opt_(count) const wchar_t* glyph, _In_ size_t count)
    +
    201 {
    +
    202 _Assume_(glyph || !count);
    +
    203 if (count) {
    +
    204#ifdef _WIN32
    +
    205 size_t i = count < 2 || !is_surrogate_pair(glyph) ? 1 : 2;
    +
    206#else
    +
    207 size_t i = 1;
    +
    208#endif
    +
    209 for (; i < count && iscombining(glyph[i]); ++i);
    +
    210 return i;
    +
    211 }
    +
    212 return 0;
    +
    213 }
    +
    214
    +
    222 template <class T>
    +
    223 inline size_t strlen(_In_z_ const T* str)
    +
    224 {
    +
    225 _Assume_(str);
    +
    226 size_t i;
    +
    227 for (i = 0; str[i]; ++i);
    +
    228 return i;
    +
    229 }
    +
    230
    +
    239 template <class T>
    +
    240 inline size_t strnlen(_In_reads_or_z_opt_(count) const T* str, _In_ size_t count)
    +
    241 {
    +
    242 _Assume_(str || !count);
    +
    243 size_t i;
    +
    244 for (i = 0; i < count && str[i]; ++i);
    +
    245 return i;
    +
    246 }
    +
    247
    +
    248 constexpr auto npos{ static_cast<size_t>(-1) };
    +
    249
    +
    258 template <class T>
    +
    259 inline size_t strchr(_In_z_ const T* str, _In_ T chr)
    +
    260 {
    +
    261 _Assume_(str);
    +
    262 for (size_t i = 0; str[i]; ++i)
    +
    263 if (str[i] == chr) return i;
    +
    264 return npos;
    +
    265 }
    +
    266
    +
    276 template <class T>
    +
    277 inline size_t strnchr(
    +
    278 _In_reads_or_z_opt_(count) const T* str,
    +
    279 _In_ size_t count,
    +
    280 _In_ T chr)
    +
    281 {
    +
    282 _Assume_(str || !count);
    +
    283 for (size_t i = 0; i < count && str[i]; ++i)
    +
    284 if (str[i] == chr) return i;
    +
    285 return npos;
    +
    286 }
    +
    287
    +
    297 template <class T>
    +
    298 inline size_t strrnchr(
    +
    299 _In_reads_or_z_opt_(count) const T* str,
    +
    300 _In_ size_t count,
    +
    301 _In_ T chr)
    +
    302 {
    +
    303 _Assume_(str || !count);
    +
    304 size_t z = npos;
    +
    305 for (size_t i = 0; i < count && str[i]; ++i)
    +
    306 if (str[i] == chr) z = i;
    +
    307 return z;
    +
    308 }
    +
    309
    +
    319 template <class T>
    +
    320 inline size_t strnichr(
    +
    321 _In_reads_or_z_opt_(count) const T* str,
    +
    322 _In_ size_t count,
    +
    323 _In_ T chr,
    +
    324 _In_ const std::locale& locale)
    +
    325 {
    +
    326 _Assume_(str || !count);
    +
    327 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
    +
    328 chr = ctype.tolower(chr);
    +
    329 for (size_t i = 0; i < count && str[i]; ++i)
    +
    330 if (ctype.tolower(str[i]) == chr) return i;
    +
    331 return npos;
    +
    332 }
    +
    333
    +
    343 template <class T>
    +
    344 inline size_t strrnichr(
    +
    345 _In_reads_or_z_opt_(count) const T* str,
    +
    346 _In_ size_t count,
    +
    347 _In_ T chr,
    +
    348 _In_ const std::locale& locale)
    +
    349 {
    +
    350 _Assume_(str || !count);
    +
    351 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
    +
    352 chr = ctype.tolower(chr);
    +
    353 size_t z = npos;
    +
    354 for (size_t i = 0; i < count && str[i]; ++i)
    +
    355 if (ctype.tolower(str[i]) == chr) z = i;
    +
    356 return z;
    +
    357 }
    +
    358
    +
    367 template <class T1, class T2>
    +
    368 inline int strcmp(const T1* str1, const T2* str2)
    +
    369 {
    +
    370 _Assume_(str1 && str2);
    +
    371 T1 a; T2 b;
    +
    372 for (size_t i = 0; (a = str1[i]) | (b = str2[i]); ++i) {
    +
    373 if (a > b) return +1;
    +
    374 if (a < b) return -1;
    +
    375 }
    +
    376 return 0;
    +
    377 }
    +
    378
    +
    389 template <class T1, class T2>
    +
    390 inline int strncmp(
    +
    391 _In_reads_or_z_opt_(count1) const T1* str1, _In_ size_t count1,
    +
    392 _In_reads_or_z_opt_(count2) const T2* str2, _In_ size_t count2)
    +
    393 {
    +
    394 _Assume_(str1 || !count1);
    +
    395 _Assume_(str2 || !count2);
    +
    396 size_t i; T1 a; T2 b;
    +
    397 for (i = 0; i < count1 && i < count2 && ((a = str1[i]) | (b = str2[i])); ++i) {
    +
    398 if (a > b) return +1;
    +
    399 if (a < b) return -1;
    +
    400 }
    +
    401 if (i < count1 && str1[i]) return +1;
    +
    402 if (i < count2 && str2[i]) return -1;
    +
    403 return 0;
    +
    404 }
    +
    405
    +
    415 template <class T1, class T2>
    +
    416 inline int strncmp(_In_reads_or_z_opt_(count) const T1* str1, _In_reads_or_z_opt_(count) const T2* str2, _In_ size_t count)
    +
    417 {
    +
    418 _Assume_((str1 && str2) || !count);
    +
    419 size_t i; T1 a; T2 b;
    +
    420 for (i = 0; i < count && ((a = str1[i]) | (b = str2[i])); ++i) {
    +
    421 if (a > b) return +1;
    +
    422 if (a < b) return -1;
    +
    423 }
    +
    424 if (i < count && str1[i]) return +1;
    +
    425 if (i < count && str2[i]) return -1;
    +
    426 return 0;
    +
    427 }
    +
    428
    +
    439 template <class T>
    +
    440 inline int strncoll(
    +
    441 _In_reads_or_z_opt_(count1) const T* str1, _In_ size_t count1,
    +
    442 _In_reads_or_z_opt_(count2) const T* str2, _In_ size_t count2,
    +
    443 _In_ const std::locale& locale)
    +
    444 {
    +
    445 _Assume_(str1 || !count1);
    +
    446 _Assume_(str2 || !count2);
    +
    447 auto& collate = std::use_facet<std::collate<T>>(locale);
    +
    448 return collate.compare(str1, str1 + count1, str2, str2 + count2);
    +
    449 }
    +
    450
    +
    459 template <class T1, class T2>
    +
    460 inline int stricmp(_In_z_ const T1* str1, _In_z_ const T2* str2, _In_ const std::locale& locale)
    +
    461 {
    +
    462 _Assume_(str1);
    +
    463 _Assume_(str2);
    +
    464 size_t i; T1 a; T2 b;
    +
    465 const auto& ctype1 = std::use_facet<std::ctype<T1>>(locale);
    +
    466 const auto& ctype2 = std::use_facet<std::ctype<T2>>(locale);
    +
    467 for (i = 0; (a = ctype1.tolower(str1[i])) | (b = ctype2.tolower(str2[i])); i++) {
    +
    468 if (a > b) return +1;
    +
    469 if (a < b) return -1;
    +
    470 }
    +
    471 if (str1[i]) return +1;
    +
    472 if (str2[i]) return -1;
    +
    473 return 0;
    +
    474 }
    +
    475
    +
    485 template <class T1, class T2>
    +
    486 inline int strnicmp(_In_reads_or_z_opt_(count) const T1* str1, _In_reads_or_z_opt_(count) const T2* str2, _In_ size_t count, _In_ const std::locale& locale)
    +
    487 {
    +
    488 _Assume_(str1 || !count);
    +
    489 _Assume_(str2 || !count);
    +
    490 size_t i; T1 a; T2 b;
    +
    491 const auto& ctype1 = std::use_facet<std::ctype<T1>>(locale);
    +
    492 const auto& ctype2 = std::use_facet<std::ctype<T2>>(locale);
    +
    493 for (i = 0; i < count && ((a = ctype1.tolower(str1[i])) | (b = ctype2.tolower(str2[i]))); i++) {
    +
    494 if (a > b) return +1;
    +
    495 if (a < b) return -1;
    +
    496 }
    +
    497 if (i < count && str1[i]) return +1;
    +
    498 if (i < count && str2[i]) return -1;
    +
    499 return 0;
    +
    500 }
    +
    501
    +
    512 template <class T1, class T2>
    +
    513 inline int strnicmp(
    +
    514 _In_reads_or_z_opt_(count1) const T1* str1, _In_ size_t count1,
    +
    515 _In_reads_or_z_opt_(count2) const T2* str2, _In_ size_t count2,
    +
    516 _In_ const std::locale& locale)
    +
    517 {
    +
    518 _Assume_(str1 || !count1);
    +
    519 _Assume_(str2 || !count2);
    +
    520 size_t i; T1 a; T2 b;
    +
    521 const auto& ctype1 = std::use_facet<std::ctype<T1>>(locale);
    +
    522 const auto& ctype2 = std::use_facet<std::ctype<T2>>(locale);
    +
    523 for (i = 0; i < count1 && i < count2 && ((a = ctype1.tolower(str1[i])) | (b = ctype2.tolower(str2[i]))); i++) {
    +
    524 if (a > b) return +1;
    +
    525 if (a < b) return -1;
    +
    526 }
    +
    527 if (i < count1 && str1[i]) return +1;
    +
    528 if (i < count2 && str2[i]) return -1;
    +
    529 return 0;
    +
    530 }
    +
    531
    +
    540 template <class T1, class T2>
    +
    541 inline size_t strstr(
    +
    542 _In_z_ const T1* str,
    +
    543 _In_z_ const T2* sample)
    +
    544 {
    +
    545 _Assume_(str);
    +
    546 _Assume_(sample);
    +
    547 for (size_t offset = 0;; ++offset) {
    +
    548 for (size_t i = offset, j = 0;; ++i, ++j) {
    +
    549 if (!sample[j])
    +
    550 return offset;
    +
    551 if (!str[i])
    +
    552 return npos;
    +
    553 if (str[i] != sample[j])
    +
    554 break;
    +
    555 }
    +
    556 }
    +
    557 }
    +
    558
    +
    568 template <class T1, class T2>
    +
    569 inline size_t strnstr(
    +
    570 _In_reads_or_z_opt_(count) const T1* str,
    +
    571 _In_ size_t count,
    +
    572 _In_z_ const T2* sample)
    +
    573 {
    +
    574 _Assume_(str || !count);
    +
    575 _Assume_(sample);
    +
    576 for (size_t offset = 0;; ++offset) {
    +
    577 for (size_t i = offset, j = 0;; ++i, ++j) {
    +
    578 if (!sample[j])
    +
    579 return offset;
    +
    580 if (i >= count || !str[i])
    +
    581 return npos;
    +
    582 if (str[i] != sample[j])
    +
    583 break;
    +
    584 }
    +
    585 }
    +
    586 }
    +
    587
    +
    596 template <class T1, class T2>
    +
    597 inline size_t stristr(
    +
    598 _In_z_ const T1* str,
    +
    599 _In_z_ const T2* sample,
    +
    600 _In_ const std::locale& locale)
    +
    601 {
    +
    602 _Assume_(str);
    +
    603 _Assume_(sample);
    +
    604 const auto& ctype1 = std::use_facet<std::ctype<T1>>(locale);
    +
    605 const auto& ctype2 = std::use_facet<std::ctype<T2>>(locale);
    +
    606 for (size_t offset = 0;; ++offset) {
    +
    607 for (size_t i = offset, j = 0;; ++i, ++j) {
    +
    608 if (!sample[j])
    +
    609 return offset;
    +
    610 if (!str[i])
    +
    611 return npos;
    +
    612 if (ctype1.tolower(str[i]) != ctype2.tolower(sample[j]))
    +
    613 break;
    +
    614 }
    +
    615 }
    +
    616 }
    +
    617
    +
    627 template <class T1, class T2>
    +
    628 inline size_t strnistr(
    +
    629 _In_reads_or_z_opt_(count) const T1* str,
    +
    630 _In_ size_t count,
    +
    631 _In_z_ const T2* sample,
    +
    632 _In_ const std::locale& locale)
    +
    633 {
    +
    634 _Assume_(str || !count);
    +
    635 _Assume_(sample);
    +
    636 const auto& ctype1 = std::use_facet<std::ctype<T1>>(locale);
    +
    637 const auto& ctype2 = std::use_facet<std::ctype<T2>>(locale);
    +
    638 for (size_t offset = 0;; ++offset) {
    +
    639 for (size_t i = offset, j = 0;; ++i, ++j) {
    +
    640 if (!sample[j])
    +
    641 return offset;
    +
    642 if (i >= count || !str[i])
    +
    643 return npos;
    +
    644 if (ctype1.tolower(str[i]) != ctype2.tolower(sample[j]))
    +
    645 break;
    +
    646 }
    +
    647 }
    +
    648 }
    +
    649
    +
    658 template <class T1, class T2>
    +
    659 inline size_t strcpy(
    +
    660 _Out_writes_z_(_String_length_(src) + 1) T1* dst,
    +
    661 _In_z_ const T2* src)
    +
    662 {
    +
    663 _Assume_(dst && src);
    +
    664 for (size_t i = 0; ; ++i) {
    +
    665 if ((dst[i] = src[i]) == 0)
    +
    666 return i;
    +
    667 }
    +
    668 }
    +
    669
    +
    679 template <class T1, class T2>
    +
    680 inline size_t strncpy(
    +
    681 _Out_writes_(count) _Post_maybez_ T1* dst,
    +
    682 _In_reads_or_z_opt_(count) const T2* src, _In_ size_t count)
    +
    683 {
    +
    684 _Assume_(dst && src || !count);
    +
    685 for (size_t i = 0; ; ++i) {
    +
    686 if (i >= count)
    +
    687 return i;
    +
    688 if ((dst[i] = src[i]) == 0)
    +
    689 return i;
    +
    690 }
    +
    691 }
    +
    692
    +
    703 template <class T1, class T2>
    +
    704 inline size_t strncpy(
    +
    705 _Out_writes_(count_dst) _Post_maybez_ T1* dst, _In_ size_t count_dst,
    +
    706 _In_reads_or_z_opt_(count_src) const T2* src, _In_ size_t count_src)
    +
    707 {
    +
    708 _Assume_(dst || !count_dst);
    +
    709 _Assume_(src || !count_src);
    +
    710 for (size_t i = 0; ; ++i)
    +
    711 {
    +
    712 if (i >= count_dst)
    +
    713 return i;
    +
    714 if (i >= count_src) {
    +
    715 dst[i] = 0;
    716 return i;
    -
    717 if (i >= count_src) {
    -
    718 dst[i] = 0;
    +
    717 }
    +
    718 if ((dst[i] = src[i]) == 0)
    719 return i;
    -
    720 }
    -
    721 if ((dst[i] = src[i]) == 0)
    -
    722 return i;
    -
    723 }
    -
    724 }
    -
    725
    -
    734 template <class T1, class T2>
    -
    735 inline size_t strcat(
    -
    736 _In_z_ _Out_writes_z_(_String_length_(dst) + _String_length_(src) + 1) T1* dst,
    -
    737 _In_z_ const T2* src)
    -
    738 {
    -
    739 _Assume_(dst && src);
    -
    740 for (size_t i = 0, j = stdex::strlen<T1>(dst); ; ++i, ++j) {
    -
    741 if ((dst[j] = src[i]) == 0)
    -
    742 return j;
    -
    743 }
    -
    744 }
    -
    745
    -
    755 template <class T1, class T2>
    -
    756 inline size_t strncat(
    -
    757 _Inout_z_ T1* dst,
    -
    758 _In_reads_or_z_opt_(count) const T2* src, _In_ size_t count)
    -
    759 {
    -
    760 _Assume_(dst && src || !count);
    -
    761 for (size_t i = 0, j = stdex::strlen<T1>(dst); ; ++i, ++j) {
    -
    762 if (i >= count)
    -
    763 return j;
    -
    764 if ((dst[j] = src[i]) == 0)
    -
    765 return j;
    -
    766 }
    -
    767 }
    -
    768
    -
    779 template <class T1, class T2>
    -
    780 inline size_t strncat(
    -
    781 _Out_writes_(count_dst) _Post_maybez_ T1* dst, _In_ size_t count_dst,
    -
    782 _In_reads_or_z_opt_(count_src) const T2* src, _In_ size_t count_src)
    -
    783 {
    -
    784 _Assume_(dst || !count_dst);
    -
    785 _Assume_(src || !count_src);
    -
    786 for (size_t i = 0, j = stdex::strnlen<T1>(dst, count_dst); ; ++i, ++j)
    -
    787 {
    -
    788 if (j >= count_dst)
    +
    720 }
    +
    721 }
    +
    722
    +
    731 template <class T1, class T2>
    +
    732 inline size_t strcat(
    +
    733 _In_z_ _Out_writes_z_(_String_length_(dst) + _String_length_(src) + 1) T1* dst,
    +
    734 _In_z_ const T2* src)
    +
    735 {
    +
    736 _Assume_(dst && src);
    +
    737 for (size_t i = 0, j = stdex::strlen<T1>(dst); ; ++i, ++j) {
    +
    738 if ((dst[j] = src[i]) == 0)
    +
    739 return j;
    +
    740 }
    +
    741 }
    +
    742
    +
    752 template <class T1, class T2>
    +
    753 inline size_t strncat(
    +
    754 _Inout_z_ T1* dst,
    +
    755 _In_reads_or_z_opt_(count) const T2* src, _In_ size_t count)
    +
    756 {
    +
    757 _Assume_(dst && src || !count);
    +
    758 for (size_t i = 0, j = stdex::strlen<T1>(dst); ; ++i, ++j) {
    +
    759 if (i >= count)
    +
    760 return j;
    +
    761 if ((dst[j] = src[i]) == 0)
    +
    762 return j;
    +
    763 }
    +
    764 }
    +
    765
    +
    776 template <class T1, class T2>
    +
    777 inline size_t strncat(
    +
    778 _Out_writes_(count_dst) _Post_maybez_ T1* dst, _In_ size_t count_dst,
    +
    779 _In_reads_or_z_opt_(count_src) const T2* src, _In_ size_t count_src)
    +
    780 {
    +
    781 _Assume_(dst || !count_dst);
    +
    782 _Assume_(src || !count_src);
    +
    783 for (size_t i = 0, j = stdex::strnlen<T1>(dst, count_dst); ; ++i, ++j)
    +
    784 {
    +
    785 if (j >= count_dst)
    +
    786 return j;
    +
    787 if (i >= count_src) {
    +
    788 dst[j] = 0;
    789 return j;
    -
    790 if (i >= count_src) {
    -
    791 dst[j] = 0;
    +
    790 }
    +
    791 if ((dst[j] = src[i]) == 0)
    792 return j;
    -
    793 }
    -
    794 if ((dst[j] = src[i]) == 0)
    -
    795 return j;
    -
    796 }
    -
    797 }
    -
    798
    -
    809 template <class T>
    -
    810 inline _Check_return_ _Ret_maybenull_z_ T* strdup(_In_opt_z_ const T* str)
    -
    811 {
    -
    812 if (!str) _Unlikely_
    -
    813 return nullptr;
    -
    814 size_t count = strlen(str) + 1;
    -
    815 T* dst = new T[count];
    -
    816 strncpy(dst, count, str, SIZE_MAX);
    -
    817 return dst;
    -
    818 }
    -
    819
    -
    831 template <class T>
    -
    832 inline _Ret_z_ T* strndup(
    -
    833 _In_reads_or_z_opt_(count) const T* str,
    -
    834 _In_ size_t count)
    -
    835 {
    -
    836 T* dst = new T[count];
    -
    837 strncpy(dst, count, str, SIZE_MAX);
    -
    838 return dst;
    -
    839 }
    -
    840
    -
    850 template <class T>
    -
    851 inline size_t crlf2nl(_Out_writes_z_(strlen(src)) T* dst, _In_z_ const T* src)
    -
    852 {
    -
    853 _Assume_(dst);
    -
    854 _Assume_(src);
    -
    855 size_t i, j;
    -
    856 for (i = j = 0; src[j];) {
    -
    857 if (src[j] != '\r' || src[j + 1] != '\n')
    -
    858 dst[i++] = src[j++];
    -
    859 else {
    -
    860 dst[i++] = '\n';
    -
    861 j += 2;
    -
    862 }
    -
    863 }
    -
    864 dst[i] = 0;
    -
    865 return i;
    -
    866 }
    -
    867
    -
    874 template<class _Elem, class _Traits = std::char_traits<_Elem>, class _Ax = std::allocator<_Elem>>
    -
    875 inline void crlf2nl(_Inout_ std::basic_string<_Elem, _Traits, _Ax> &dst, _In_z_ const _Elem* src)
    -
    876 {
    -
    877 _Assume_(src);
    -
    878 _Assume_(src != dst.c_str());
    -
    879 dst.clear();
    -
    880 dst.reserve(strlen(src));
    -
    881 for (size_t j = 0; src[j];) {
    -
    882 if (src[j] != '\r' || src[j + 1] != '\n')
    -
    883 dst += src[j++];
    -
    884 else {
    -
    885 dst += '\n';
    -
    886 j += 2;
    -
    887 }
    -
    888 }
    -
    889 }
    -
    890
    -
    896 template<class _Elem, class _Traits = std::char_traits<_Elem>, class _Ax = std::allocator<_Elem>>
    -
    897 inline void crlf2nl(_Inout_ std::basic_string<_Elem, _Traits, _Ax>& str)
    -
    898 {
    -
    899 size_t i, j, n;
    -
    900 for (i = j = 0, n = str.size(); j < n;) {
    -
    901 if (str[j] != '\r' || str[j + 1] != '\n')
    -
    902 str[i++] = str[j++];
    -
    903 else {
    -
    904 str[i++] = '\n';
    -
    905 j += 2;
    -
    906 }
    -
    907 }
    -
    908 str.resize(i);
    -
    909 }
    -
    910
    -
    912 template <class T, class T_bin>
    -
    913 inline T_bin strtoint(
    -
    914 _In_reads_or_z_opt_(count) const T* str, _In_ size_t count,
    -
    915 _Out_opt_ size_t* end,
    -
    916 _In_ int radix,
    -
    917 _Out_ uint8_t& flags)
    -
    918 {
    -
    919 _Assume_(str || !count);
    -
    920 _Assume_(radix == 0 || 2 <= radix && radix <= 36);
    -
    921
    -
    922 size_t i = 0;
    -
    923 T_bin value = 0, digit,
    -
    924 max_ui = (T_bin)-1,
    -
    925 max_ui_pre1, max_ui_pre2;
    -
    926
    -
    927 flags = 0;
    -
    928
    -
    929 // Skip leading spaces.
    -
    930 for (;; ++i) {
    -
    931 if (i >= count || !str[i]) goto error;
    -
    932 if (!isspace(str[i])) break;
    -
    933 }
    -
    934
    -
    935 // Read the sign.
    -
    936 if (str[i] == '+') {
    -
    937 flags &= ~0x01;
    -
    938 ++i;
    -
    939 if (i >= count || !str[i]) goto error;
    -
    940 }
    -
    941 else if (str[i] == '-') {
    -
    942 flags |= 0x01;
    -
    943 ++i;
    -
    944 if (i >= count || !str[i]) goto error;
    -
    945 }
    -
    946
    -
    947 if (radix == 16) {
    -
    948 // On hexadecimal, allow leading 0x.
    -
    949 if (str[i] == '0' && i + 1 < count && (str[i + 1] == 'x' || str[i + 1] == 'X')) {
    -
    950 i += 2;
    -
    951 if (i >= count || !str[i]) goto error;
    -
    952 }
    -
    953 }
    -
    954 else if (!radix) {
    -
    955 // Autodetect radix.
    -
    956 if (str[i] == '0') {
    -
    957 ++i;
    -
    958 if (i >= count || !str[i]) goto error;
    -
    959 if (str[i] == 'x' || str[i] == 'X') {
    -
    960 radix = 16;
    -
    961 ++i;
    -
    962 if (i >= count || !str[i]) goto error;
    -
    963 }
    -
    964 else
    -
    965 radix = 8;
    -
    966 }
    -
    967 else
    -
    968 radix = 10;
    -
    969 }
    -
    970
    -
    971 // We have the radix.
    -
    972 max_ui_pre1 = max_ui / (T_bin)radix;
    -
    973 max_ui_pre2 = max_ui % (T_bin)radix;
    -
    974 for (;;) {
    -
    975 if ('0' <= str[i] && str[i] <= '9')
    -
    976 digit = (T_bin)str[i] - '0';
    -
    977 else if ('A' <= str[i] && str[i] <= 'Z')
    -
    978 digit = (T_bin)str[i] - 'A' + '\x0a';
    -
    979 else if ('a' <= str[i] && str[i] <= 'z')
    -
    980 digit = (T_bin)str[i] - 'a' + '\x0a';
    -
    981 else
    -
    982 goto error;
    -
    983 if (digit >= (T_bin)radix)
    -
    984 goto error;
    -
    985
    -
    986 if (value < max_ui_pre1 || // Multiplication nor addition will not overflow.
    -
    987 (value == max_ui_pre1 && digit <= max_ui_pre2)) // Small digits will not overflow.
    -
    988 value = value * (T_bin)radix + digit;
    -
    989 else {
    -
    990 // Overflow!
    -
    991 flags |= 0x02;
    -
    992 }
    -
    993
    -
    994 ++i;
    -
    995 if (i >= count || !str[i])
    -
    996 goto error;
    -
    997 }
    -
    998
    -
    999 error:
    -
    1000 if (end) *end = i;
    -
    1001 return value;
    -
    1002 }
    -
    1004
    -
    1015 template <class T, class T_bin>
    -
    1016 T_bin strtoint(
    -
    1017 _In_reads_or_z_opt_(count) const T* str, _In_ size_t count,
    -
    1018 _Out_opt_ size_t* end,
    -
    1019 _In_ int radix)
    -
    1020 {
    -
    1021 uint8_t flags;
    -
    1022 T_bin value;
    -
    1023
    -
    1024 switch (sizeof(T_bin)) {
    -
    1025 case 1:
    -
    1026 value = (T_bin)strtoint<T, uint8_t>(str, count, end, radix, flags);
    -
    1027 if ((flags & 0x01) && (value & 0x80)) {
    -
    1028 // Sign bit is 1 => overflow.
    -
    1029 flags |= 0x02;
    -
    1030 }
    -
    1031 return (flags & 0x02) ?
    -
    1032 (flags & 0x01) ? (T_bin)0x80 : (T_bin)0x7f :
    -
    1033 (flags & 0x01) ? -value : value;
    -
    1034
    -
    1035 case 2:
    -
    1036 value = (T_bin)strtoint<T, uint16_t>(str, count, end, radix, flags);
    -
    1037 if ((flags & 0x01) && (value & 0x8000)) {
    -
    1038 // Sign bit is 1 => overflow.
    -
    1039 flags |= 0x02;
    -
    1040 }
    -
    1041 return (flags & 0x02) ?
    -
    1042 (flags & 0x01) ? (T_bin)0x8000 : (T_bin)0x7fff :
    -
    1043 (flags & 0x01) ? -value : value;
    -
    1044
    -
    1045 case 4:
    -
    1046 value = (T_bin)strtoint<T, uint32_t>(str, count, end, radix, flags);
    -
    1047 if ((flags & 0x01) && (value & 0x80000000)) {
    -
    1048 // Sign bit is 1 => overflow.
    -
    1049 flags |= 0x02;
    -
    1050 }
    -
    1051 return (flags & 0x02) ?
    -
    1052 (flags & 0x01) ? (T_bin)0x80000000 : (T_bin)0x7fffffff :
    -
    1053 (flags & 0x01) ? -value : value;
    -
    1054
    -
    1055 case 8:
    -
    1056 value = (T_bin)strtoint<T, uint64_t>(str, count, end, radix, flags);
    -
    1057 if ((flags & 0x01) && (value & 0x8000000000000000)) {
    -
    1058 // Sign bit is 1 => overflow.
    -
    1059 flags |= 0x02;
    -
    1060 }
    -
    1061 return (flags & 0x02) ?
    -
    1062 (flags & 0x01) ? (T_bin)0x8000000000000000 : (T_bin)0x7fffffffffffffff :
    -
    1063 (flags & 0x01) ? -value : value;
    -
    1064
    -
    1065 default:
    -
    1066 throw std::invalid_argument("Unsupported bit length");
    -
    1067 }
    -
    1068 }
    -
    1069
    -
    1080 template <class T, class T_bin>
    -
    1081 inline T_bin strtouint(
    -
    1082 _In_reads_or_z_opt_(count) const T* str,
    -
    1083 _In_ size_t count,
    -
    1084 _Out_opt_ size_t* end,
    -
    1085 _In_ int radix)
    -
    1086 {
    -
    1087 uint8_t flags;
    -
    1088 T_bin value;
    -
    1089
    -
    1090 switch (sizeof(T_bin)) {
    -
    1091 case 1: value = (T_bin)strtoint<T, uint8_t>(str, count, end, radix, flags); break;
    -
    1092 case 2: value = (T_bin)strtoint<T, uint16_t>(str, count, end, radix, flags); break;
    -
    1093 case 4: value = (T_bin)strtoint<T, uint32_t>(str, count, end, radix, flags); break;
    -
    1094 case 8: value = (T_bin)strtoint<T, uint64_t>(str, count, end, radix, flags); break;
    -
    1095 default: throw std::invalid_argument("Unsupported bit length");
    -
    1096 }
    -
    1097
    -
    1098 return (flags & 0x02) ?
    -
    1099 (flags & 0x01) ? (T_bin)0 : (T_bin)-1 :
    -
    1100 (flags & 0x01) ? ~value : value;
    -
    1101 }
    -
    1102
    -
    1113 template <class T>
    -
    1114 inline int32_t strto32(
    -
    1115 _In_reads_or_z_opt_(count) const T* str, _In_ size_t count,
    -
    1116 _Out_opt_ size_t* end,
    -
    1117 _In_ int radix)
    -
    1118 {
    -
    1119 return strtoint<T, int32_t>(str, count, end, radix);
    -
    1120 }
    -
    1121
    -
    1132 template <class T>
    -
    1133 inline int64_t strto64(
    -
    1134 _In_reads_or_z_opt_(count) const T* str, _In_ size_t count,
    -
    1135 _Out_opt_ size_t* end,
    -
    1136 _In_ int radix)
    -
    1137 {
    -
    1138 return strtoint<T, int64_t>(str, count, end, radix);
    -
    1139 }
    -
    1140
    -
    1152 template <class T>
    -
    1153 inline intptr_t strtoi(
    -
    1154 _In_reads_or_z_opt_(count) const T* str, _In_ size_t count,
    -
    1155 _Out_opt_ size_t* end,
    -
    1156 _In_ int radix)
    -
    1157 {
    -
    1158#if defined(_WIN64) || defined(__LP64__)
    -
    1159 return (intptr_t)strto64(str, count, end, radix);
    -
    1160#else
    -
    1161 return (intptr_t)strto32(str, count, end, radix);
    -
    1162#endif
    -
    1163 }
    -
    1164
    -
    1175 template <class T>
    -
    1176 inline uint32_t strtou32(
    -
    1177 _In_reads_or_z_opt_(count) const T* str, _In_ size_t count,
    -
    1178 _Out_opt_ size_t* end,
    -
    1179 _In_ int radix)
    -
    1180 {
    -
    1181 return strtouint<T, uint32_t>(str, count, end, radix);
    -
    1182 }
    -
    1183
    -
    1194 template <class T>
    -
    1195 inline uint64_t strtou64(
    -
    1196 _In_reads_or_z_opt_(count) const T* str, _In_ size_t count,
    -
    1197 _Out_opt_ size_t* end,
    -
    1198 _In_ int radix)
    -
    1199 {
    -
    1200 return strtouint<T, uint64_t>(str, count, end, radix);
    -
    1201 }
    -
    1202
    -
    1214 template <class T>
    -
    1215 inline size_t strtoui(
    -
    1216 _In_reads_or_z_opt_(count) const T* str, _In_ size_t count,
    -
    1217 _Out_opt_ size_t* end,
    -
    1218 _In_ int radix)
    -
    1219 {
    -
    1220#if defined(_WIN64) || defined(__LP64__)
    -
    1221 return (size_t)strtou64(str, count, end, radix);
    -
    1222#else
    -
    1223 return (size_t)strtou32(str, count, end, radix);
    -
    1224#endif
    -
    1225 }
    -
    1226
    -
    1228 inline int vsnprintf(_Out_z_cap_(capacity) char *str, _In_ size_t capacity, _In_z_ _Printf_format_string_params_(2) const char *format, _In_opt_ locale_t locale, _In_ va_list arg)
    -
    1229 {
    -
    1230 int r;
    -
    1231#ifdef _WIN32
    -
    1232 // Don't use _vsnprintf_s(). It terminates the string even if we want to print to the edge of the buffer.
    -
    1233#pragma warning(suppress: 4996)
    -
    1234 r = _vsnprintf_l(str, capacity, format, locale, arg);
    -
    1235#else
    -
    1236 r = ::vsnprintf(str, capacity, format, arg);
    -
    1237#endif
    -
    1238 if (r == -1 && strnlen(str, capacity) == capacity) {
    -
    1239 // Buffer overrun. Estimate buffer size for the next iteration.
    -
    1240 capacity += std::max<size_t>(capacity / 8, 0x80);
    -
    1241 if (capacity > INT_MAX)
    -
    1242 throw std::invalid_argument("string too big");
    -
    1243 return (int)capacity;
    -
    1244 }
    -
    1245 return r;
    -
    1246 }
    -
    1247
    -
    1248 inline int vsnprintf(_Out_z_cap_(capacity) wchar_t *str, _In_ size_t capacity, _In_z_ _Printf_format_string_params_(2) const wchar_t *format, _In_opt_ locale_t locale, _In_ va_list arg)
    -
    1249 {
    -
    1250 int r;
    -
    1251#ifdef _WIN32
    -
    1252 // Don't use _vsnwprintf_s(). It terminates the string even if we want to print to the edge of the buffer.
    -
    1253#pragma warning(suppress: 4996)
    -
    1254 r = _vsnwprintf_l(str, capacity, format, locale, arg);
    -
    1255#else
    -
    1256 r = vswprintf(str, capacity, format, arg);
    -
    1257#endif
    -
    1258 if (r == -1 && strnlen(str, capacity) == capacity) {
    -
    1259 // Buffer overrun. Estimate buffer size for the next iteration.
    -
    1260 capacity += std::max<size_t>(capacity / 8, 0x80);
    -
    1261 if (capacity > INT_MAX)
    -
    1262 throw std::invalid_argument("string too big");
    -
    1263 return (int)capacity;
    -
    1264 }
    -
    1265 return r;
    -
    1266 }
    -
    1268
    -
    1277 template<class _Elem, class _Traits, class _Ax>
    -
    1278 inline void vappendf(_Inout_ std::basic_string<_Elem, _Traits, _Ax> &str, _In_z_ _Printf_format_string_params_(2) const _Elem *format, _In_opt_ locale_t locale, _In_ va_list arg)
    -
    1279 {
    -
    1280 _Elem buf[1024/sizeof(_Elem)];
    -
    1281
    -
    1282 // Try with stack buffer first.
    -
    1283 int count = vsnprintf(buf, _countof(buf) - 1, format, locale, arg);
    -
    1284 if (count >= 0) {
    -
    1285 // Copy from stack.
    -
    1286 str.append(buf, count);
    -
    1287 } else {
    -
    1288 for (size_t capacity = 2*1024/sizeof(_Elem);; capacity *= 2) {
    -
    1289 // Allocate on heap and retry.
    -
    1290 auto buf_dyn = std::make_unique<_Elem[]>(capacity);
    -
    1291 count = vsnprintf(buf_dyn.get(), capacity - 1, format, locale, arg);
    -
    1292 if (count >= 0) {
    -
    1293 str.append(buf_dyn.get(), count);
    -
    1294 break;
    -
    1295 }
    -
    1296 }
    -
    1297 }
    -
    1298 }
    -
    1299
    -
    1307 template<class _Elem, class _Traits, class _Ax>
    -
    1308 inline void appendf(_Inout_ std::basic_string<_Elem, _Traits, _Ax> &str, _In_z_ _Printf_format_string_params_(2) const _Elem *format, _In_opt_ locale_t locale, ...)
    -
    1309 {
    -
    1310 va_list arg;
    -
    1311 va_start(arg, locale);
    -
    1312 vappendf(str, format, locale, arg);
    -
    1313 va_end(arg);
    -
    1314 }
    -
    1315
    -
    1324 template<class _Elem, class _Traits, class _Ax>
    -
    1325 inline void vsprintf(_Inout_ std::basic_string<_Elem, _Traits, _Ax> &str, _In_z_ _Printf_format_string_params_(2) const _Elem *format, _In_opt_ locale_t locale, _In_ va_list arg)
    -
    1326 {
    -
    1327 str.clear();
    -
    1328 vappendf(str, format, locale, arg);
    -
    1329 }
    -
    1330
    -
    1338 template<class _Elem, class _Traits, class _Ax>
    -
    1339 inline void sprintf(_Inout_ std::basic_string<_Elem, _Traits, _Ax> &str, _In_z_ _Printf_format_string_params_(2) const _Elem *format, _In_opt_ locale_t locale, ...)
    -
    1340 {
    -
    1341 va_list arg;
    -
    1342 va_start(arg, locale);
    -
    1343 vsprintf(str, format, locale, arg);
    -
    1344 va_end(arg);
    -
    1345 }
    -
    1346
    -
    1356 template<class _Elem, class _Traits = std::char_traits<_Elem>, class _Ax = std::allocator<_Elem>>
    -
    1357 inline std::basic_string<_Elem, _Traits, _Ax> vsprintf(_In_z_ _Printf_format_string_params_(2) const _Elem *format, _In_opt_ locale_t locale, _In_ va_list arg)
    -
    1358 {
    -
    1359 std::basic_string<_Elem, _Traits, _Ax> str;
    -
    1360 vappendf(str, format, locale, arg);
    -
    1361 return str;
    -
    1362 }
    -
    1363
    -
    1372 template<class _Elem, class _Traits = std::char_traits<_Elem>, class _Ax = std::allocator<_Elem>>
    -
    1373 inline std::basic_string<_Elem, _Traits, _Ax> sprintf(_In_z_ _Printf_format_string_params_(2) const _Elem *format, _In_opt_ locale_t locale, ...)
    -
    1374 {
    -
    1375 va_list arg;
    -
    1376 va_start(arg, locale);
    -
    1377 auto str = vsprintf(format, locale, arg);
    -
    1378 va_end(arg);
    -
    1379 return str;
    -
    1380 }
    -
    1381
    -
    1383 inline size_t strftime(_Out_z_cap_(capacity) char *str, _In_ size_t capacity, _In_z_ _Printf_format_string_ const char *format, _In_ const struct tm* time, _In_opt_ locale_t locale)
    -
    1384 {
    -
    1385#ifdef _WIN32
    -
    1386 return _strftime_l(str, capacity, format, time, locale);
    -
    1387#else
    -
    1388 return strftime_l(str, capacity, format, time, locale);
    -
    1389#endif
    -
    1390 }
    -
    1391
    -
    1392 inline size_t strftime(_Out_z_cap_(capacity) wchar_t *str, _In_ size_t capacity, _In_z_ _Printf_format_string_ const wchar_t *format, _In_ const struct tm* time, _In_opt_ locale_t locale)
    -
    1393 {
    -
    1394#ifdef _WIN32
    -
    1395 return _wcsftime_l(str, capacity, format, time, locale);
    -
    1396#else
    -
    1397 return wcsftime_l(str, capacity, format, time, locale);
    -
    1398#endif
    -
    1399 }
    -
    1401
    -
    1410 template<class _Elem, class _Traits, class _Ax>
    -
    1411 inline void strcatftime(_Inout_ std::basic_string<_Elem, _Traits, _Ax> &str, _In_z_ _Printf_format_string_ const _Elem *format, _In_ const struct tm* time, _In_opt_ locale_t locale)
    -
    1412 {
    -
    1413 _Elem buf[1024/sizeof(_Elem)];
    -
    1414
    -
    1415 // Try with stack buffer first.
    -
    1416 size_t count = strftime(buf, _countof(buf), format, time, locale);
    -
    1417 if (count) {
    -
    1418 // Copy from stack.
    -
    1419 str.append(buf, count);
    -
    1420 } else {
    -
    1421 for (size_t capacity = 2*1024/sizeof(_Elem);; capacity *= 2) {
    -
    1422 // Allocate on heap and retry.
    -
    1423 auto buf_dyn = std::make_unique<_Elem[]>(capacity);
    -
    1424 count = strftime(buf_dyn.get(), capacity, format, time, locale);
    -
    1425 if (count) {
    -
    1426 str.append(buf_dyn.get(), count);
    -
    1427 break;
    -
    1428 }
    -
    1429 }
    -
    1430 }
    -
    1431 }
    -
    1432
    -
    1441 template<class _Elem, class _Traits, class _Ax>
    -
    1442 inline void strftime(_Inout_ std::basic_string<_Elem, _Traits, _Ax> &str, _In_z_ _Printf_format_string_ const _Elem *format, _In_ const struct tm* time, _In_opt_ locale_t locale)
    -
    1443 {
    -
    1444 str.clear();
    -
    1445 strcatftime(str, format, time, locale);
    -
    1446 }
    -
    1447
    -
    1458 template<class _Elem, class _Traits = std::char_traits<_Elem>, class _Ax = std::allocator<_Elem>>
    -
    1459 inline std::basic_string<_Elem, _Traits, _Ax> strftime(_In_z_ _Printf_format_string_ const _Elem *format, _In_ const struct tm* time, _In_opt_ locale_t locale)
    -
    1460 {
    -
    1461 std::basic_string<_Elem, _Traits, _Ax> str;
    -
    1462 strcatftime(str, format, time, locale);
    -
    1463 return str;
    -
    1464 }
    -
    1465
    -
    1472 inline void uuidtostr(_Out_writes_z_(39) char str[39], _In_ const uuid_t& id)
    -
    1473 {
    -
    1474 _Assume_(str);
    -
    1475 _snprintf_s_l(str, 39, _TRUNCATE, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", NULL,
    -
    1476#ifdef _WIN32
    -
    1477 id.Data1,
    -
    1478 static_cast<unsigned int>(id.Data2),
    -
    1479 static_cast<unsigned int>(id.Data3),
    -
    1480 static_cast<unsigned int>(id.Data4[0]), static_cast<unsigned int>(id.Data4[1]),
    -
    1481 static_cast<unsigned int>(id.Data4[2]), static_cast<unsigned int>(id.Data4[3]), static_cast<unsigned int>(id.Data4[4]), static_cast<unsigned int>(id.Data4[5]), static_cast<unsigned int>(id.Data4[6]), static_cast<unsigned int>(id.Data4[7]));
    -
    1482#else
    -
    1483 *reinterpret_cast<const uint32_t*>(&id[0]),
    -
    1484 static_cast<unsigned int>(*reinterpret_cast<const uint16_t*>(&id[4])),
    -
    1485 static_cast<unsigned int>(*reinterpret_cast<const uint16_t*>(&id[6])),
    -
    1486 static_cast<unsigned int>(id[8]), static_cast<unsigned int>(id[9]),
    -
    1487 static_cast<unsigned int>(id[10])), static_cast<unsigned int>(id[11]), static_cast<unsigned int>(id[12]), static_cast<unsigned int>(id)), static_cast<unsigned int>(id[14]), static_cast<unsigned int>(id[15]));
    -
    1488#endif
    -
    1489 }
    -
    1490
    -
    1497 inline void uuidtostr(_Out_writes_z_(39) wchar_t str[39], _In_ const uuid_t& id)
    -
    1498 {
    -
    1499 _Assume_(str);
    -
    1500 _snwprintf_s_l(str, 39, _TRUNCATE, L"{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", NULL,
    -
    1501#ifdef _WIN32
    -
    1502 id.Data1,
    -
    1503 static_cast<unsigned int>(id.Data2),
    -
    1504 static_cast<unsigned int>(id.Data3),
    -
    1505 static_cast<unsigned int>(id.Data4[0]), static_cast<unsigned int>(id.Data4[1]),
    -
    1506 static_cast<unsigned int>(id.Data4[2]), static_cast<unsigned int>(id.Data4[3]), static_cast<unsigned int>(id.Data4[4]), static_cast<unsigned int>(id.Data4[5]), static_cast<unsigned int>(id.Data4[6]), static_cast<unsigned int>(id.Data4[7]));
    -
    1507#else
    -
    1508 *reinterpret_cast<const uint32_t*>(&id[0]),
    -
    1509 static_cast<unsigned int>(*reinterpret_cast<const uint16_t*>(&id[4])),
    -
    1510 static_cast<unsigned int>(*reinterpret_cast<const uint16_t*>(&id[6])),
    -
    1511 static_cast<unsigned int>(id[8]), static_cast<unsigned int>(id[9]),
    -
    1512 static_cast<unsigned int>(id[10])), static_cast<unsigned int>(id[11]), static_cast<unsigned int>(id[12]), static_cast<unsigned int>(id)), static_cast<unsigned int>(id[14]), static_cast<unsigned int>(id[15]));
    -
    1513#endif
    -
    1514 }
    -
    1515
    -
    1523 template<class T>
    -
    1524 inline void strlwr(_Inout_z_ T* str, _In_ const std::locale& locale)
    -
    1525 {
    -
    1526 _Assume_(str);
    -
    1527 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
    -
    1528 for (size_t i = 0; str[i]; ++i)
    -
    1529 str[i] = ctype.tolower(str[i]);
    -
    1530 }
    -
    1531
    -
    1540 template<class T>
    -
    1541 inline void strlwr(_Inout_updates_z_(count) T* str, _In_ size_t count, _In_ const std::locale& locale)
    -
    1542 {
    -
    1543 _Assume_(str || !count);
    -
    1544 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
    -
    1545 for (size_t i = 0; i < count && str[i]; ++i)
    -
    1546 str[i] = ctype.tolower(str[i]);
    -
    1547 }
    -
    1548
    -
    1556 template<class T>
    -
    1557 inline void strupr(_Inout_z_ T* str, _In_ const std::locale& locale)
    -
    1558 {
    -
    1559 _Assume_(str);
    -
    1560 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
    -
    1561 for (size_t i = 0; str[i]; ++i)
    -
    1562 str[i] = ctype.toupper(str[i]);
    -
    1563 }
    -
    1564
    -
    1573 template<class T>
    -
    1574 inline void strupr(_Inout_updates_z_(count) T* str, _In_ size_t count, _In_ const std::locale& locale)
    -
    1575 {
    -
    1576 _Assume_(str || !count);
    -
    1577 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
    -
    1578 for (size_t i = 0; i < count && str[i]; ++i)
    -
    1579 str[i] = ctype.toupper(str[i]);
    -
    1580 }
    -
    1581
    -
    1589 template<class _Elem, class _Traits = std::char_traits<_Elem>, class _Ax = std::allocator<_Elem>>
    -
    1590 inline void strupr(_Inout_ std::basic_string<_Elem, _Traits, _Ax>& str, _In_ const std::locale& locale)
    -
    1591 {
    -
    1592 const auto& ctype = std::use_facet<std::ctype<_Elem>>(locale);
    -
    1593 for (size_t i = 0; i < str.size(); ++i)
    -
    1594 str[i] = ctype.toupper(str[i]);
    -
    1595 }
    -
    1596
    -
    1605 template<class T>
    -
    1606 inline size_t ltrim(
    -
    1607 _Inout_z_count_(count) T* str, _In_ size_t count,
    -
    1608 _In_ const std::locale& locale)
    -
    1609 {
    -
    1610 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
    -
    1611 for (size_t i = 0;; ++i) {
    -
    1612 if (i >= count) {
    -
    1613 if (count) str[0] = 0;
    -
    1614 return 0;
    -
    1615 }
    -
    1616 if (!str[i]) {
    -
    1617 str[0] = 0;
    -
    1618 return 0;
    -
    1619 }
    -
    1620 if (!ctype.is(ctype.space, str[i])) {
    -
    1621 if (!i)
    -
    1622 return strnlen(str, count);
    -
    1623 size_t n = count != SIZE_MAX ? strncpy(str, str + i, count - i) : strcpy(str, str + i);
    -
    1624 str[n] = 0;
    -
    1625 return n;
    -
    1626 }
    -
    1627 }
    -
    1628 }
    -
    1629
    -
    1635 template<class _Elem, class _Traits = std::char_traits<_Elem>, class _Ax = std::allocator<_Elem>>
    -
    1636 inline void ltrim(_Inout_ std::basic_string<_Elem, _Traits, _Ax> &s, _In_ const std::locale& locale)
    -
    1637 {
    -
    1638 const auto& ctype = std::use_facet<std::ctype<_Elem>>(locale);
    -
    1639 s.erase(
    -
    1640 s.begin(),
    -
    1641 std::find_if(
    -
    1642 s.begin(),
    -
    1643 s.end(),
    -
    1644 [&](_Elem ch) { return !ctype.is(ctype.space, ch); }));
    -
    1645 }
    -
    1646
    -
    1655 template<class T>
    -
    1656 inline size_t rtrim(
    -
    1657 _Inout_z_count_(count) T* str, _In_ size_t count,
    -
    1658 _In_ const std::locale& locale)
    -
    1659 {
    -
    1660 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
    -
    1661 for (size_t i = 0, j = 0;;) {
    -
    1662 if (i >= count || !str[i]) {
    -
    1663 if (j < count) str[j] = 0;
    -
    1664 return j;
    -
    1665 }
    -
    1666 if (!ctype.is(ctype.space, str[i]))
    -
    1667 j = ++i;
    -
    1668 else
    -
    1669 ++i;
    -
    1670 }
    -
    1671 }
    -
    1672
    -
    1678 template<class _Elem, class _Traits = std::char_traits<_Elem>, class _Ax = std::allocator<_Elem>>
    -
    1679 static inline void rtrim(_Inout_ std::basic_string<_Elem, _Traits, _Ax> &s, _In_ const std::locale& locale)
    -
    1680 {
    -
    1681 const auto& ctype = std::use_facet<std::ctype<_Elem>>(locale);
    -
    1682 s.erase(
    -
    1683 std::find_if(
    -
    1684 s.rbegin(),
    -
    1685 s.rend(),
    -
    1686 [&](_Elem ch) { return !ctype.is(ctype.space, ch); }).base(),
    -
    1687 s.end());
    -
    1688 }
    -
    1689
    -
    1698 template<class T>
    -
    1699 inline size_t trim(
    -
    1700 _Inout_z_count_(count) T* str, _In_ size_t count,
    -
    1701 _In_ const std::locale& locale)
    -
    1702 {
    -
    1703 return ltrim(str, rtrim(str, count, locale), locale);
    -
    1704 }
    -
    1705
    -
    1711 template<class _Elem, class _Traits = std::char_traits<_Elem>, class _Ax = std::allocator<_Elem>>
    -
    1712 static inline void trim(_Inout_ std::basic_string<_Elem, _Traits, _Ax> &s, _In_ const std::locale& locale)
    -
    1713 {
    -
    1714 const auto& ctype = std::use_facet<std::ctype<_Elem>>(locale);
    -
    1715 s.erase(
    -
    1716 s.begin(),
    -
    1717 std::find_if(
    -
    1718 s.begin(),
    -
    1719 s.end(),
    -
    1720 [&](_Elem ch) { return !ctype.is(ctype.space, ch); }));
    -
    1721 s.erase(
    -
    1722 std::find_if(
    -
    1723 s.rbegin(),
    -
    1724 s.rend(),
    -
    1725 [&](_Elem ch) { return !ctype.is(ctype.space, ch); }).base(),
    -
    1726 s.end());
    -
    1727 }
    -
    1728}
    -
    Deleter for unique_ptr using free_locale.
    Definition string.hpp:63
    -
    void operator()(locale_t locale) const
    Delete a pointer.
    Definition string.hpp:67
    +
    793 }
    +
    794 }
    +
    795
    +
    806 template <class T>
    +
    807 inline _Check_return_ _Ret_maybenull_z_ T* strdup(_In_opt_z_ const T* str)
    +
    808 {
    +
    809 if (!str) _Unlikely_
    +
    810 return nullptr;
    +
    811 size_t count = strlen(str) + 1;
    +
    812 T* dst = new T[count];
    +
    813 strncpy(dst, count, str, SIZE_MAX);
    +
    814 return dst;
    +
    815 }
    +
    816
    +
    828 template <class T>
    +
    829 inline _Ret_z_ T* strndup(
    +
    830 _In_reads_or_z_opt_(count) const T* str,
    +
    831 _In_ size_t count)
    +
    832 {
    +
    833 T* dst = new T[count];
    +
    834 strncpy(dst, count, str, SIZE_MAX);
    +
    835 return dst;
    +
    836 }
    +
    837
    +
    847 template <class T>
    +
    848 inline size_t crlf2nl(_Out_writes_z_(strlen(src)) T* dst, _In_z_ const T* src)
    +
    849 {
    +
    850 _Assume_(dst);
    +
    851 _Assume_(src);
    +
    852 size_t i, j;
    +
    853 for (i = j = 0; src[j];) {
    +
    854 if (src[j] != '\r' || src[j + 1] != '\n')
    +
    855 dst[i++] = src[j++];
    +
    856 else {
    +
    857 dst[i++] = '\n';
    +
    858 j += 2;
    +
    859 }
    +
    860 }
    +
    861 dst[i] = 0;
    +
    862 return i;
    +
    863 }
    +
    864
    +
    871 template<class _Elem, class _Traits = std::char_traits<_Elem>, class _Ax = std::allocator<_Elem>>
    +
    872 inline void crlf2nl(_Inout_ std::basic_string<_Elem, _Traits, _Ax> &dst, _In_z_ const _Elem* src)
    +
    873 {
    +
    874 _Assume_(src);
    +
    875 _Assume_(src != dst.c_str());
    +
    876 dst.clear();
    +
    877 dst.reserve(strlen(src));
    +
    878 for (size_t j = 0; src[j];) {
    +
    879 if (src[j] != '\r' || src[j + 1] != '\n')
    +
    880 dst += src[j++];
    +
    881 else {
    +
    882 dst += '\n';
    +
    883 j += 2;
    +
    884 }
    +
    885 }
    +
    886 }
    +
    887
    +
    893 template<class _Elem, class _Traits = std::char_traits<_Elem>, class _Ax = std::allocator<_Elem>>
    +
    894 inline void crlf2nl(_Inout_ std::basic_string<_Elem, _Traits, _Ax>& str)
    +
    895 {
    +
    896 size_t i, j, n;
    +
    897 for (i = j = 0, n = str.size(); j < n;) {
    +
    898 if (str[j] != '\r' || str[j + 1] != '\n')
    +
    899 str[i++] = str[j++];
    +
    900 else {
    +
    901 str[i++] = '\n';
    +
    902 j += 2;
    +
    903 }
    +
    904 }
    +
    905 str.resize(i);
    +
    906 }
    +
    907
    +
    909 template <class T, class T_bin>
    +
    910 inline T_bin strtoint(
    +
    911 _In_reads_or_z_opt_(count) const T* str, _In_ size_t count,
    +
    912 _Out_opt_ size_t* end,
    +
    913 _In_ int radix,
    +
    914 _Out_ uint8_t& flags)
    +
    915 {
    +
    916 _Assume_(str || !count);
    +
    917 _Assume_(radix == 0 || 2 <= radix && radix <= 36);
    +
    918
    +
    919 size_t i = 0;
    +
    920 T_bin value = 0, digit,
    +
    921 max_ui = (T_bin)-1,
    +
    922 max_ui_pre1, max_ui_pre2;
    +
    923
    +
    924 flags = 0;
    +
    925
    +
    926 // Skip leading spaces.
    +
    927 for (;; ++i) {
    +
    928 if (i >= count || !str[i]) goto error;
    +
    929 if (!isspace(str[i])) break;
    +
    930 }
    +
    931
    +
    932 // Read the sign.
    +
    933 if (str[i] == '+') {
    +
    934 flags &= ~0x01;
    +
    935 ++i;
    +
    936 if (i >= count || !str[i]) goto error;
    +
    937 }
    +
    938 else if (str[i] == '-') {
    +
    939 flags |= 0x01;
    +
    940 ++i;
    +
    941 if (i >= count || !str[i]) goto error;
    +
    942 }
    +
    943
    +
    944 if (radix == 16) {
    +
    945 // On hexadecimal, allow leading 0x.
    +
    946 if (str[i] == '0' && i + 1 < count && (str[i + 1] == 'x' || str[i + 1] == 'X')) {
    +
    947 i += 2;
    +
    948 if (i >= count || !str[i]) goto error;
    +
    949 }
    +
    950 }
    +
    951 else if (!radix) {
    +
    952 // Autodetect radix.
    +
    953 if (str[i] == '0') {
    +
    954 ++i;
    +
    955 if (i >= count || !str[i]) goto error;
    +
    956 if (str[i] == 'x' || str[i] == 'X') {
    +
    957 radix = 16;
    +
    958 ++i;
    +
    959 if (i >= count || !str[i]) goto error;
    +
    960 }
    +
    961 else
    +
    962 radix = 8;
    +
    963 }
    +
    964 else
    +
    965 radix = 10;
    +
    966 }
    +
    967
    +
    968 // We have the radix.
    +
    969 max_ui_pre1 = max_ui / (T_bin)radix;
    +
    970 max_ui_pre2 = max_ui % (T_bin)radix;
    +
    971 for (;;) {
    +
    972 if ('0' <= str[i] && str[i] <= '9')
    +
    973 digit = (T_bin)str[i] - '0';
    +
    974 else if ('A' <= str[i] && str[i] <= 'Z')
    +
    975 digit = (T_bin)str[i] - 'A' + '\x0a';
    +
    976 else if ('a' <= str[i] && str[i] <= 'z')
    +
    977 digit = (T_bin)str[i] - 'a' + '\x0a';
    +
    978 else
    +
    979 goto error;
    +
    980 if (digit >= (T_bin)radix)
    +
    981 goto error;
    +
    982
    +
    983 if (value < max_ui_pre1 || // Multiplication nor addition will not overflow.
    +
    984 (value == max_ui_pre1 && digit <= max_ui_pre2)) // Small digits will not overflow.
    +
    985 value = value * (T_bin)radix + digit;
    +
    986 else {
    +
    987 // Overflow!
    +
    988 flags |= 0x02;
    +
    989 }
    +
    990
    +
    991 ++i;
    +
    992 if (i >= count || !str[i])
    +
    993 goto error;
    +
    994 }
    +
    995
    +
    996 error:
    +
    997 if (end) *end = i;
    +
    998 return value;
    +
    999 }
    +
    1001
    +
    1012 template <class T, class T_bin>
    +
    1013 T_bin strtoint(
    +
    1014 _In_reads_or_z_opt_(count) const T* str, _In_ size_t count,
    +
    1015 _Out_opt_ size_t* end,
    +
    1016 _In_ int radix)
    +
    1017 {
    +
    1018 uint8_t flags;
    +
    1019 T_bin value;
    +
    1020
    +
    1021 switch (sizeof(T_bin)) {
    +
    1022 case 1:
    +
    1023 value = (T_bin)strtoint<T, uint8_t>(str, count, end, radix, flags);
    +
    1024 if ((flags & 0x01) && (value & 0x80)) {
    +
    1025 // Sign bit is 1 => overflow.
    +
    1026 flags |= 0x02;
    +
    1027 }
    +
    1028 return (flags & 0x02) ?
    +
    1029 (flags & 0x01) ? (T_bin)0x80 : (T_bin)0x7f :
    +
    1030 (flags & 0x01) ? -value : value;
    +
    1031
    +
    1032 case 2:
    +
    1033 value = (T_bin)strtoint<T, uint16_t>(str, count, end, radix, flags);
    +
    1034 if ((flags & 0x01) && (value & 0x8000)) {
    +
    1035 // Sign bit is 1 => overflow.
    +
    1036 flags |= 0x02;
    +
    1037 }
    +
    1038 return (flags & 0x02) ?
    +
    1039 (flags & 0x01) ? (T_bin)0x8000 : (T_bin)0x7fff :
    +
    1040 (flags & 0x01) ? -value : value;
    +
    1041
    +
    1042 case 4:
    +
    1043 value = (T_bin)strtoint<T, uint32_t>(str, count, end, radix, flags);
    +
    1044 if ((flags & 0x01) && (value & 0x80000000)) {
    +
    1045 // Sign bit is 1 => overflow.
    +
    1046 flags |= 0x02;
    +
    1047 }
    +
    1048 return (flags & 0x02) ?
    +
    1049 (flags & 0x01) ? (T_bin)0x80000000 : (T_bin)0x7fffffff :
    +
    1050 (flags & 0x01) ? -value : value;
    +
    1051
    +
    1052 case 8:
    +
    1053 value = (T_bin)strtoint<T, uint64_t>(str, count, end, radix, flags);
    +
    1054 if ((flags & 0x01) && (value & 0x8000000000000000)) {
    +
    1055 // Sign bit is 1 => overflow.
    +
    1056 flags |= 0x02;
    +
    1057 }
    +
    1058 return (flags & 0x02) ?
    +
    1059 (flags & 0x01) ? (T_bin)0x8000000000000000 : (T_bin)0x7fffffffffffffff :
    +
    1060 (flags & 0x01) ? -value : value;
    +
    1061
    +
    1062 default:
    +
    1063 throw std::invalid_argument("Unsupported bit length");
    +
    1064 }
    +
    1065 }
    +
    1066
    +
    1077 template <class T, class T_bin>
    +
    1078 inline T_bin strtouint(
    +
    1079 _In_reads_or_z_opt_(count) const T* str,
    +
    1080 _In_ size_t count,
    +
    1081 _Out_opt_ size_t* end,
    +
    1082 _In_ int radix)
    +
    1083 {
    +
    1084 uint8_t flags;
    +
    1085 T_bin value;
    +
    1086
    +
    1087 switch (sizeof(T_bin)) {
    +
    1088 case 1: value = (T_bin)strtoint<T, uint8_t>(str, count, end, radix, flags); break;
    +
    1089 case 2: value = (T_bin)strtoint<T, uint16_t>(str, count, end, radix, flags); break;
    +
    1090 case 4: value = (T_bin)strtoint<T, uint32_t>(str, count, end, radix, flags); break;
    +
    1091 case 8: value = (T_bin)strtoint<T, uint64_t>(str, count, end, radix, flags); break;
    +
    1092 default: throw std::invalid_argument("Unsupported bit length");
    +
    1093 }
    +
    1094
    +
    1095 return (flags & 0x02) ?
    +
    1096 (flags & 0x01) ? (T_bin)0 : (T_bin)-1 :
    +
    1097 (flags & 0x01) ? ~value : value;
    +
    1098 }
    +
    1099
    +
    1110 template <class T>
    +
    1111 inline int32_t strto32(
    +
    1112 _In_reads_or_z_opt_(count) const T* str, _In_ size_t count,
    +
    1113 _Out_opt_ size_t* end,
    +
    1114 _In_ int radix)
    +
    1115 {
    +
    1116 return strtoint<T, int32_t>(str, count, end, radix);
    +
    1117 }
    +
    1118
    +
    1129 template <class T>
    +
    1130 inline int64_t strto64(
    +
    1131 _In_reads_or_z_opt_(count) const T* str, _In_ size_t count,
    +
    1132 _Out_opt_ size_t* end,
    +
    1133 _In_ int radix)
    +
    1134 {
    +
    1135 return strtoint<T, int64_t>(str, count, end, radix);
    +
    1136 }
    +
    1137
    +
    1149 template <class T>
    +
    1150 inline intptr_t strtoi(
    +
    1151 _In_reads_or_z_opt_(count) const T* str, _In_ size_t count,
    +
    1152 _Out_opt_ size_t* end,
    +
    1153 _In_ int radix)
    +
    1154 {
    +
    1155#if defined(_WIN64) || defined(__LP64__)
    +
    1156 return (intptr_t)strto64(str, count, end, radix);
    +
    1157#else
    +
    1158 return (intptr_t)strto32(str, count, end, radix);
    +
    1159#endif
    +
    1160 }
    +
    1161
    +
    1172 template <class T>
    +
    1173 inline uint32_t strtou32(
    +
    1174 _In_reads_or_z_opt_(count) const T* str, _In_ size_t count,
    +
    1175 _Out_opt_ size_t* end,
    +
    1176 _In_ int radix)
    +
    1177 {
    +
    1178 return strtouint<T, uint32_t>(str, count, end, radix);
    +
    1179 }
    +
    1180
    +
    1191 template <class T>
    +
    1192 inline uint64_t strtou64(
    +
    1193 _In_reads_or_z_opt_(count) const T* str, _In_ size_t count,
    +
    1194 _Out_opt_ size_t* end,
    +
    1195 _In_ int radix)
    +
    1196 {
    +
    1197 return strtouint<T, uint64_t>(str, count, end, radix);
    +
    1198 }
    +
    1199
    +
    1211 template <class T>
    +
    1212 inline size_t strtoui(
    +
    1213 _In_reads_or_z_opt_(count) const T* str, _In_ size_t count,
    +
    1214 _Out_opt_ size_t* end,
    +
    1215 _In_ int radix)
    +
    1216 {
    +
    1217#if defined(_WIN64) || defined(__LP64__)
    +
    1218 return (size_t)strtou64(str, count, end, radix);
    +
    1219#else
    +
    1220 return (size_t)strtou32(str, count, end, radix);
    +
    1221#endif
    +
    1222 }
    +
    1223
    +
    1225 inline int vsnprintf(_Out_z_cap_(capacity) char *str, _In_ size_t capacity, _In_z_ _Printf_format_string_params_(2) const char *format, _In_opt_ locale_t locale, _In_ va_list arg)
    +
    1226 {
    +
    1227 int r;
    +
    1228#ifdef _WIN32
    +
    1229 // Don't use _vsnprintf_s(). It terminates the string even if we want to print to the edge of the buffer.
    +
    1230#pragma warning(suppress: 4996)
    +
    1231 r = _vsnprintf_l(str, capacity, format, locale, arg);
    +
    1232#else
    +
    1233 r = ::vsnprintf(str, capacity, format, arg);
    +
    1234#endif
    +
    1235 if (r == -1 && strnlen(str, capacity) == capacity) {
    +
    1236 // Buffer overrun. Estimate buffer size for the next iteration.
    +
    1237 capacity += std::max<size_t>(capacity / 8, 0x80);
    +
    1238 if (capacity > INT_MAX)
    +
    1239 throw std::invalid_argument("string too big");
    +
    1240 return (int)capacity;
    +
    1241 }
    +
    1242 return r;
    +
    1243 }
    +
    1244
    +
    1245 inline int vsnprintf(_Out_z_cap_(capacity) wchar_t *str, _In_ size_t capacity, _In_z_ _Printf_format_string_params_(2) const wchar_t *format, _In_opt_ locale_t locale, _In_ va_list arg)
    +
    1246 {
    +
    1247 int r;
    +
    1248#ifdef _WIN32
    +
    1249 // Don't use _vsnwprintf_s(). It terminates the string even if we want to print to the edge of the buffer.
    +
    1250#pragma warning(suppress: 4996)
    +
    1251 r = _vsnwprintf_l(str, capacity, format, locale, arg);
    +
    1252#else
    +
    1253 r = vswprintf(str, capacity, format, arg);
    +
    1254#endif
    +
    1255 if (r == -1 && strnlen(str, capacity) == capacity) {
    +
    1256 // Buffer overrun. Estimate buffer size for the next iteration.
    +
    1257 capacity += std::max<size_t>(capacity / 8, 0x80);
    +
    1258 if (capacity > INT_MAX)
    +
    1259 throw std::invalid_argument("string too big");
    +
    1260 return (int)capacity;
    +
    1261 }
    +
    1262 return r;
    +
    1263 }
    +
    1265
    +
    1274 template<class _Elem, class _Traits, class _Ax>
    +
    1275 inline void vappendf(_Inout_ std::basic_string<_Elem, _Traits, _Ax> &str, _In_z_ _Printf_format_string_params_(2) const _Elem *format, _In_opt_ locale_t locale, _In_ va_list arg)
    +
    1276 {
    +
    1277 _Elem buf[1024/sizeof(_Elem)];
    +
    1278
    +
    1279 // Try with stack buffer first.
    +
    1280 int count = vsnprintf(buf, _countof(buf) - 1, format, locale, arg);
    +
    1281 if (count >= 0) {
    +
    1282 // Copy from stack.
    +
    1283 str.append(buf, count);
    +
    1284 } else {
    +
    1285 for (size_t capacity = 2*1024/sizeof(_Elem);; capacity *= 2) {
    +
    1286 // Allocate on heap and retry.
    +
    1287 auto buf_dyn = std::make_unique<_Elem[]>(capacity);
    +
    1288 count = vsnprintf(buf_dyn.get(), capacity - 1, format, locale, arg);
    +
    1289 if (count >= 0) {
    +
    1290 str.append(buf_dyn.get(), count);
    +
    1291 break;
    +
    1292 }
    +
    1293 }
    +
    1294 }
    +
    1295 }
    +
    1296
    +
    1304 template<class _Elem, class _Traits, class _Ax>
    +
    1305 inline void appendf(_Inout_ std::basic_string<_Elem, _Traits, _Ax> &str, _In_z_ _Printf_format_string_params_(2) const _Elem *format, _In_opt_ locale_t locale, ...)
    +
    1306 {
    +
    1307 va_list arg;
    +
    1308 va_start(arg, locale);
    +
    1309 vappendf(str, format, locale, arg);
    +
    1310 va_end(arg);
    +
    1311 }
    +
    1312
    +
    1321 template<class _Elem, class _Traits, class _Ax>
    +
    1322 inline void vsprintf(_Inout_ std::basic_string<_Elem, _Traits, _Ax> &str, _In_z_ _Printf_format_string_params_(2) const _Elem *format, _In_opt_ locale_t locale, _In_ va_list arg)
    +
    1323 {
    +
    1324 str.clear();
    +
    1325 vappendf(str, format, locale, arg);
    +
    1326 }
    +
    1327
    +
    1335 template<class _Elem, class _Traits, class _Ax>
    +
    1336 inline void sprintf(_Inout_ std::basic_string<_Elem, _Traits, _Ax> &str, _In_z_ _Printf_format_string_params_(2) const _Elem *format, _In_opt_ locale_t locale, ...)
    +
    1337 {
    +
    1338 va_list arg;
    +
    1339 va_start(arg, locale);
    +
    1340 vsprintf(str, format, locale, arg);
    +
    1341 va_end(arg);
    +
    1342 }
    +
    1343
    +
    1353 template<class _Elem, class _Traits = std::char_traits<_Elem>, class _Ax = std::allocator<_Elem>>
    +
    1354 inline std::basic_string<_Elem, _Traits, _Ax> vsprintf(_In_z_ _Printf_format_string_params_(2) const _Elem *format, _In_opt_ locale_t locale, _In_ va_list arg)
    +
    1355 {
    +
    1356 std::basic_string<_Elem, _Traits, _Ax> str;
    +
    1357 vappendf(str, format, locale, arg);
    +
    1358 return str;
    +
    1359 }
    +
    1360
    +
    1369 template<class _Elem, class _Traits = std::char_traits<_Elem>, class _Ax = std::allocator<_Elem>>
    +
    1370 inline std::basic_string<_Elem, _Traits, _Ax> sprintf(_In_z_ _Printf_format_string_params_(2) const _Elem *format, _In_opt_ locale_t locale, ...)
    +
    1371 {
    +
    1372 va_list arg;
    +
    1373 va_start(arg, locale);
    +
    1374 auto str = vsprintf(format, locale, arg);
    +
    1375 va_end(arg);
    +
    1376 return str;
    +
    1377 }
    +
    1378
    +
    1380 inline size_t strftime(_Out_z_cap_(capacity) char *str, _In_ size_t capacity, _In_z_ _Printf_format_string_ const char *format, _In_ const struct tm* time, _In_opt_ locale_t locale)
    +
    1381 {
    +
    1382#ifdef _WIN32
    +
    1383 return _strftime_l(str, capacity, format, time, locale);
    +
    1384#else
    +
    1385 return strftime_l(str, capacity, format, time, locale);
    +
    1386#endif
    +
    1387 }
    +
    1388
    +
    1389 inline size_t strftime(_Out_z_cap_(capacity) wchar_t *str, _In_ size_t capacity, _In_z_ _Printf_format_string_ const wchar_t *format, _In_ const struct tm* time, _In_opt_ locale_t locale)
    +
    1390 {
    +
    1391#ifdef _WIN32
    +
    1392 return _wcsftime_l(str, capacity, format, time, locale);
    +
    1393#else
    +
    1394 return wcsftime_l(str, capacity, format, time, locale);
    +
    1395#endif
    +
    1396 }
    +
    1398
    +
    1407 template<class _Elem, class _Traits, class _Ax>
    +
    1408 inline void strcatftime(_Inout_ std::basic_string<_Elem, _Traits, _Ax> &str, _In_z_ _Printf_format_string_ const _Elem *format, _In_ const struct tm* time, _In_opt_ locale_t locale)
    +
    1409 {
    +
    1410 _Elem buf[1024/sizeof(_Elem)];
    +
    1411
    +
    1412 // Try with stack buffer first.
    +
    1413 size_t count = strftime(buf, _countof(buf), format, time, locale);
    +
    1414 if (count) {
    +
    1415 // Copy from stack.
    +
    1416 str.append(buf, count);
    +
    1417 } else {
    +
    1418 for (size_t capacity = 2*1024/sizeof(_Elem);; capacity *= 2) {
    +
    1419 // Allocate on heap and retry.
    +
    1420 auto buf_dyn = std::make_unique<_Elem[]>(capacity);
    +
    1421 count = strftime(buf_dyn.get(), capacity, format, time, locale);
    +
    1422 if (count) {
    +
    1423 str.append(buf_dyn.get(), count);
    +
    1424 break;
    +
    1425 }
    +
    1426 }
    +
    1427 }
    +
    1428 }
    +
    1429
    +
    1438 template<class _Elem, class _Traits, class _Ax>
    +
    1439 inline void strftime(_Inout_ std::basic_string<_Elem, _Traits, _Ax> &str, _In_z_ _Printf_format_string_ const _Elem *format, _In_ const struct tm* time, _In_opt_ locale_t locale)
    +
    1440 {
    +
    1441 str.clear();
    +
    1442 strcatftime(str, format, time, locale);
    +
    1443 }
    +
    1444
    +
    1455 template<class _Elem, class _Traits = std::char_traits<_Elem>, class _Ax = std::allocator<_Elem>>
    +
    1456 inline std::basic_string<_Elem, _Traits, _Ax> strftime(_In_z_ _Printf_format_string_ const _Elem *format, _In_ const struct tm* time, _In_opt_ locale_t locale)
    +
    1457 {
    +
    1458 std::basic_string<_Elem, _Traits, _Ax> str;
    +
    1459 strcatftime(str, format, time, locale);
    +
    1460 return str;
    +
    1461 }
    +
    1462
    +
    1470 template<class T>
    +
    1471 inline void strlwr(_Inout_z_ T* str, _In_ const std::locale& locale)
    +
    1472 {
    +
    1473 _Assume_(str);
    +
    1474 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
    +
    1475 for (size_t i = 0; str[i]; ++i)
    +
    1476 str[i] = ctype.tolower(str[i]);
    +
    1477 }
    +
    1478
    +
    1487 template<class T>
    +
    1488 inline void strlwr(_Inout_updates_z_(count) T* str, _In_ size_t count, _In_ const std::locale& locale)
    +
    1489 {
    +
    1490 _Assume_(str || !count);
    +
    1491 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
    +
    1492 for (size_t i = 0; i < count && str[i]; ++i)
    +
    1493 str[i] = ctype.tolower(str[i]);
    +
    1494 }
    +
    1495
    +
    1503 template<class T>
    +
    1504 inline void strupr(_Inout_z_ T* str, _In_ const std::locale& locale)
    +
    1505 {
    +
    1506 _Assume_(str);
    +
    1507 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
    +
    1508 for (size_t i = 0; str[i]; ++i)
    +
    1509 str[i] = ctype.toupper(str[i]);
    +
    1510 }
    +
    1511
    +
    1520 template<class T>
    +
    1521 inline void strupr(_Inout_updates_z_(count) T* str, _In_ size_t count, _In_ const std::locale& locale)
    +
    1522 {
    +
    1523 _Assume_(str || !count);
    +
    1524 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
    +
    1525 for (size_t i = 0; i < count && str[i]; ++i)
    +
    1526 str[i] = ctype.toupper(str[i]);
    +
    1527 }
    +
    1528
    +
    1536 template<class _Elem, class _Traits = std::char_traits<_Elem>, class _Ax = std::allocator<_Elem>>
    +
    1537 inline void strupr(_Inout_ std::basic_string<_Elem, _Traits, _Ax>& str, _In_ const std::locale& locale)
    +
    1538 {
    +
    1539 const auto& ctype = std::use_facet<std::ctype<_Elem>>(locale);
    +
    1540 for (size_t i = 0; i < str.size(); ++i)
    +
    1541 str[i] = ctype.toupper(str[i]);
    +
    1542 }
    +
    1543
    +
    1552 template<class T>
    +
    1553 inline size_t ltrim(
    +
    1554 _Inout_z_count_(count) T* str, _In_ size_t count,
    +
    1555 _In_ const std::locale& locale)
    +
    1556 {
    +
    1557 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
    +
    1558 for (size_t i = 0;; ++i) {
    +
    1559 if (i >= count) {
    +
    1560 if (count) str[0] = 0;
    +
    1561 return 0;
    +
    1562 }
    +
    1563 if (!str[i]) {
    +
    1564 str[0] = 0;
    +
    1565 return 0;
    +
    1566 }
    +
    1567 if (!ctype.is(ctype.space, str[i])) {
    +
    1568 if (!i)
    +
    1569 return strnlen(str, count);
    +
    1570 size_t n = count != SIZE_MAX ? strncpy(str, str + i, count - i) : strcpy(str, str + i);
    +
    1571 str[n] = 0;
    +
    1572 return n;
    +
    1573 }
    +
    1574 }
    +
    1575 }
    +
    1576
    +
    1582 template<class _Elem, class _Traits = std::char_traits<_Elem>, class _Ax = std::allocator<_Elem>>
    +
    1583 inline void ltrim(_Inout_ std::basic_string<_Elem, _Traits, _Ax> &s, _In_ const std::locale& locale)
    +
    1584 {
    +
    1585 const auto& ctype = std::use_facet<std::ctype<_Elem>>(locale);
    +
    1586 s.erase(
    +
    1587 s.begin(),
    +
    1588 std::find_if(
    +
    1589 s.begin(),
    +
    1590 s.end(),
    +
    1591 [&](_Elem ch) { return !ctype.is(ctype.space, ch); }));
    +
    1592 }
    +
    1593
    +
    1602 template<class T>
    +
    1603 inline size_t rtrim(
    +
    1604 _Inout_z_count_(count) T* str, _In_ size_t count,
    +
    1605 _In_ const std::locale& locale)
    +
    1606 {
    +
    1607 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
    +
    1608 for (size_t i = 0, j = 0;;) {
    +
    1609 if (i >= count || !str[i]) {
    +
    1610 if (j < count) str[j] = 0;
    +
    1611 return j;
    +
    1612 }
    +
    1613 if (!ctype.is(ctype.space, str[i]))
    +
    1614 j = ++i;
    +
    1615 else
    +
    1616 ++i;
    +
    1617 }
    +
    1618 }
    +
    1619
    +
    1625 template<class _Elem, class _Traits = std::char_traits<_Elem>, class _Ax = std::allocator<_Elem>>
    +
    1626 static inline void rtrim(_Inout_ std::basic_string<_Elem, _Traits, _Ax> &s, _In_ const std::locale& locale)
    +
    1627 {
    +
    1628 const auto& ctype = std::use_facet<std::ctype<_Elem>>(locale);
    +
    1629 s.erase(
    +
    1630 std::find_if(
    +
    1631 s.rbegin(),
    +
    1632 s.rend(),
    +
    1633 [&](_Elem ch) { return !ctype.is(ctype.space, ch); }).base(),
    +
    1634 s.end());
    +
    1635 }
    +
    1636
    +
    1645 template<class T>
    +
    1646 inline size_t trim(
    +
    1647 _Inout_z_count_(count) T* str, _In_ size_t count,
    +
    1648 _In_ const std::locale& locale)
    +
    1649 {
    +
    1650 return ltrim(str, rtrim(str, count, locale), locale);
    +
    1651 }
    +
    1652
    +
    1658 template<class _Elem, class _Traits = std::char_traits<_Elem>, class _Ax = std::allocator<_Elem>>
    +
    1659 static inline void trim(_Inout_ std::basic_string<_Elem, _Traits, _Ax> &s, _In_ const std::locale& locale)
    +
    1660 {
    +
    1661 const auto& ctype = std::use_facet<std::ctype<_Elem>>(locale);
    +
    1662 s.erase(
    +
    1663 s.begin(),
    +
    1664 std::find_if(
    +
    1665 s.begin(),
    +
    1666 s.end(),
    +
    1667 [&](_Elem ch) { return !ctype.is(ctype.space, ch); }));
    +
    1668 s.erase(
    +
    1669 std::find_if(
    +
    1670 s.rbegin(),
    +
    1671 s.rend(),
    +
    1672 [&](_Elem ch) { return !ctype.is(ctype.space, ch); }).base(),
    +
    1673 s.end());
    +
    1674 }
    +
    1675}
    +
    Deleter for unique_ptr using free_locale.
    Definition string.hpp:60
    +
    void operator()(locale_t locale) const
    Delete a pointer.
    Definition string.hpp:64
    diff --git a/structstdex_1_1chrono_1_1aosn__date-members.html b/structstdex_1_1chrono_1_1aosn__date-members.html index a855dccf9..2eb050152 100644 --- a/structstdex_1_1chrono_1_1aosn__date-members.html +++ b/structstdex_1_1chrono_1_1aosn__date-members.html @@ -96,7 +96,7 @@ $(function() {
    diff --git a/structstdex_1_1chrono_1_1aosn__date.html b/structstdex_1_1chrono_1_1aosn__date.html index 25abde57b..e98e06852 100644 --- a/structstdex_1_1chrono_1_1aosn__date.html +++ b/structstdex_1_1chrono_1_1aosn__date.html @@ -152,7 +152,7 @@ static constexpr bool is_s
    diff --git a/structstdex_1_1chrono_1_1aosn__timestamp-members.html b/structstdex_1_1chrono_1_1aosn__timestamp-members.html index 8365fecc6..16920021d 100644 --- a/structstdex_1_1chrono_1_1aosn__timestamp-members.html +++ b/structstdex_1_1chrono_1_1aosn__timestamp-members.html @@ -110,7 +110,7 @@ $(function() {
    diff --git a/structstdex_1_1chrono_1_1aosn__timestamp.html b/structstdex_1_1chrono_1_1aosn__timestamp.html index 6dbfdef19..86412cfc4 100644 --- a/structstdex_1_1chrono_1_1aosn__timestamp.html +++ b/structstdex_1_1chrono_1_1aosn__timestamp.html @@ -197,7 +197,7 @@ static constexpr rep one_w
    diff --git a/structstdex_1_1free__locale__delete-members.html b/structstdex_1_1free__locale__delete-members.html index 63252f7f5..126d8c9e2 100644 --- a/structstdex_1_1free__locale__delete-members.html +++ b/structstdex_1_1free__locale__delete-members.html @@ -84,7 +84,7 @@ $(function() {
    diff --git a/structstdex_1_1free__locale__delete.html b/structstdex_1_1free__locale__delete.html index f3312996b..93b534a3b 100644 --- a/structstdex_1_1free__locale__delete.html +++ b/structstdex_1_1free__locale__delete.html @@ -101,7 +101,7 @@ void operator() (local
    diff --git a/structstdex_1_1interval-members.html b/structstdex_1_1interval-members.html index 96323f696..817a8cd42 100644 --- a/structstdex_1_1interval-members.html +++ b/structstdex_1_1interval-members.html @@ -103,7 +103,7 @@ $(function() {
    diff --git a/structstdex_1_1interval.html b/structstdex_1_1interval.html index cc89bd60a..36c99c1a9 100644 --- a/structstdex_1_1interval.html +++ b/structstdex_1_1interval.html @@ -722,7 +722,7 @@ template<class T >
    diff --git a/structstdex_1_1mapping-members.html b/structstdex_1_1mapping-members.html index f2b95b33b..77e7a5ca2 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 5682fdfd5..acb62e207 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 e441588d1..bff6bc884 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 6594cdb3c..c043ae6d5 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 9bce384a1..45703b43c 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 b23c42466..980e406e3 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 a4049951b..e97e5e958 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 9320a615d..ef2dd519c 100644 --- a/structstdex_1_1parser_1_1http__factor__more.html +++ b/structstdex_1_1parser_1_1http__factor__more.html @@ -93,7 +93,7 @@ Public Member Functions
    diff --git a/structstdex_1_1stream_1_1buffer_1_1buffer__t-members.html b/structstdex_1_1stream_1_1buffer_1_1buffer__t-members.html index 2258758d9..9261d873e 100644 --- a/structstdex_1_1stream_1_1buffer_1_1buffer__t-members.html +++ b/structstdex_1_1stream_1_1buffer_1_1buffer__t-members.html @@ -89,7 +89,7 @@ $(function() {
    diff --git a/structstdex_1_1stream_1_1buffer_1_1buffer__t.html b/structstdex_1_1stream_1_1buffer_1_1buffer__t.html index de9218693..61f689f96 100644 --- a/structstdex_1_1stream_1_1buffer_1_1buffer__t.html +++ b/structstdex_1_1stream_1_1buffer_1_1buffer__t.html @@ -109,7 +109,7 @@ size_t capacity diff --git a/structstdex_1_1stream_1_1fifo_1_1node__t-members.html b/structstdex_1_1stream_1_1fifo_1_1node__t-members.html index d7853f3f0..52c50ad76 100644 --- a/structstdex_1_1stream_1_1fifo_1_1node__t-members.html +++ b/structstdex_1_1stream_1_1fifo_1_1node__t-members.html @@ -86,7 +86,7 @@ $(function() {
    diff --git a/structstdex_1_1stream_1_1fifo_1_1node__t.html b/structstdex_1_1stream_1_1fifo_1_1node__t.html index 77a84830f..0d52ec09f 100644 --- a/structstdex_1_1stream_1_1fifo_1_1node__t.html +++ b/structstdex_1_1stream_1_1fifo_1_1node__t.html @@ -99,7 +99,7 @@ uint8_t data [0]<
    diff --git a/structstdex_1_1sys__info__t-members.html b/structstdex_1_1sys__info__t-members.html index a24a2d992..781dc30d3 100644 --- a/structstdex_1_1sys__info__t-members.html +++ b/structstdex_1_1sys__info__t-members.html @@ -89,7 +89,7 @@ $(function() {
    diff --git a/structstdex_1_1sys__info__t.html b/structstdex_1_1sys__info__t.html index 2390f36d3..f253db667 100644 --- a/structstdex_1_1sys__info__t.html +++ b/structstdex_1_1sys__info__t.html @@ -137,7 +137,7 @@ struct utsname m_utsn<
    diff --git a/sys__info_8hpp_source.html b/sys__info_8hpp_source.html index f2f55bb2a..d86aee3a5 100644 --- a/sys__info_8hpp_source.html +++ b/sys__info_8hpp_source.html @@ -95,193 +95,197 @@ $(document).ready(function() { init_codefold(0); });
    11#include "windows.h"
    12#include <stdlib.h>
    13#include <tchar.h>
    -
    14#endif
    -
    15#include <memory>
    -
    16
    -
    17namespace stdex
    -
    18{
    -
    22#ifdef _WIN32
    -
    23 typedef uint16_t platform_id;
    -
    24#else
    -
    25 typedef const char* platform_id;
    -
    26
    -
    27 inline bool operator ==(_In_ const platform_id a, _In_ const platform_id b) { return a == b; }
    -
    28 inline bool operator !=(_In_ const platform_id a, _In_ const platform_id b) { return a != b; }
    -
    29 inline bool operator <(_In_ const platform_id a, _In_ const platform_id b) { return a == IMAGE_FILE_MACHINE_UNKNOWN && b != IMAGE_FILE_MACHINE_UNKNOWN || a != IMAGE_FILE_MACHINE_UNKNOWN && b != IMAGE_FILE_MACHINE_UNKNOWN && strcmp(a, b) < 0; }
    -
    30 inline bool operator <=(_In_ const platform_id a, _In_ const platform_id b) { return a == IMAGE_FILE_MACHINE_UNKNOWN || a != IMAGE_FILE_MACHINE_UNKNOWN && b != IMAGE_FILE_MACHINE_UNKNOWN && strcmp(a, b) <= 0; }
    -
    31 inline bool operator >(_In_ const platform_id a, _In_ const platform_id b) { return a != IMAGE_FILE_MACHINE_UNKNOWN && b == IMAGE_FILE_MACHINE_UNKNOWN || a != IMAGE_FILE_MACHINE_UNKNOWN && b != IMAGE_FILE_MACHINE_UNKNOWN && strcmp(a, b) > 0; }
    -
    32 inline bool operator >=(_In_ const platform_id a, _In_ const platform_id b) { return b == IMAGE_FILE_MACHINE_UNKNOWN || a != IMAGE_FILE_MACHINE_UNKNOWN && b != IMAGE_FILE_MACHINE_UNKNOWN && strcmp(a, b) >= 0; }
    -
    33#endif
    -
    34}
    -
    35
    -
    36#ifndef _WIN32
    -
    37constexpr stdex::platform_id IMAGE_FILE_MACHINE_UNKNOWN = nullptr;
    -
    38constexpr stdex::platform_id IMAGE_FILE_MACHINE_I386 = "i386";
    -
    39constexpr stdex::platform_id IMAGE_FILE_MACHINE_AMD64 = "x86_64";
    -
    40constexpr stdex::platform_id IMAGE_FILE_MACHINE_ARMNT = "arm";
    -
    41constexpr stdex::platform_id IMAGE_FILE_MACHINE_ARM64 = "aarch64";
    -
    42#endif
    -
    43
    -
    44namespace stdex
    -
    45{
    -
    -
    49 const struct sys_info_t
    -
    50 {
    -
    54#if _M_IX86
    -
    55 static constexpr platform_id process_platform = IMAGE_FILE_MACHINE_I386;
    -
    56#elif _M_X64 // _M_ARM64EC is introducing as x64
    -
    57 static constexpr platform_id process_platform = IMAGE_FILE_MACHINE_AMD64;
    -
    58#elif _M_ARM
    -
    59 static constexpr platform_id process_platform = IMAGE_FILE_MACHINE_ARMNT;
    -
    60#elif _M_ARM64
    -
    61 static constexpr platform_id process_platform = IMAGE_FILE_MACHINE_ARM64;
    -
    62#elif __i386__
    -
    63 static constexpr platform_id process_platform = "i386";
    -
    64#elif __x86_64__
    -
    65 static constexpr platform_id process_platform = "x86_64";
    -
    66#elif __aarch64__
    -
    67 static constexpr platform_id process_platform = "aarch64";
    -
    68#else
    -
    69 #error Unknown platform
    -
    70#endif
    -
    71
    -
    75 platform_id os_platform;
    -
    76
    -
    77#ifdef _WIN32
    -
    81 bool wow64;
    -
    82#endif
    -
    83
    - -
    88
    -
    92 bool admin;
    -
    93
    - -
    98
    -
    99 sys_info_t() :
    -
    100 os_platform(IMAGE_FILE_MACHINE_UNKNOWN),
    -
    101 wow64(false),
    - -
    103 admin(false),
    -
    104 elevated(false)
    -
    105 {
    -
    106#ifdef _WIN32
    -
    107 HMODULE kernel32_handle;
    -
    108 kernel32_handle = LoadLibrary(_T("kernel32.dll"));
    -
    109 _Assume_(kernel32_handle);
    -
    110 BOOL(WINAPI * IsWow64Process2)(HANDLE hProcess, USHORT * pProcessMachine, USHORT * pNativeMachine);
    -
    111 *reinterpret_cast<FARPROC*>(&IsWow64Process2) = GetProcAddress(kernel32_handle, "IsWow64Process2");
    -
    112 HANDLE process = GetCurrentProcess();
    -
    113 USHORT process_machine;
    -
    114#ifndef _WIN64
    -
    115 BOOL Wow64Process;
    -
    116#endif
    -
    117 if (IsWow64Process2 && IsWow64Process2(process, &process_machine, &os_platform)) {
    -
    118 wow64 = process_machine != IMAGE_FILE_MACHINE_UNKNOWN;
    -
    119 }
    -
    120#ifdef _WIN64
    -
    121 else {
    -
    122 os_platform = process_platform;
    -
    123 wow64 = false;
    -
    124 }
    -
    125#else
    -
    126 else if (IsWow64Process(process, &Wow64Process)) {
    -
    127 if (Wow64Process) {
    -
    128 os_platform = IMAGE_FILE_MACHINE_AMD64;
    -
    129 wow64 = true;
    -
    130 }
    -
    131 else {
    -
    132 os_platform = process_platform;
    -
    133 wow64 = false;
    +
    14#else
    +
    15#include <sys/utsname.h>
    +
    16#endif
    +
    17#include <memory>
    +
    18
    +
    19namespace stdex
    +
    20{
    +
    24#ifdef _WIN32
    +
    25 typedef uint16_t platform_id;
    +
    26#else
    +
    27 typedef const char* platform_id;
    +
    28#endif
    +
    29}
    +
    30
    +
    31#ifndef _WIN32
    +
    32constexpr stdex::platform_id IMAGE_FILE_MACHINE_UNKNOWN = nullptr;
    +
    33constexpr stdex::platform_id IMAGE_FILE_MACHINE_I386 = "i386";
    +
    34constexpr stdex::platform_id IMAGE_FILE_MACHINE_AMD64 = "x86_64";
    +
    35constexpr stdex::platform_id IMAGE_FILE_MACHINE_ARMNT = "arm";
    +
    36constexpr stdex::platform_id IMAGE_FILE_MACHINE_ARM64 = "aarch64";
    +
    37
    +
    38inline bool operator ==(_In_ const stdex::platform_id a, _In_ const stdex::platform_id b) { return a == b; }
    +
    39inline bool operator !=(_In_ const stdex::platform_id a, _In_ const stdex::platform_id b) { return a != b; }
    +
    40inline bool operator <(_In_ const stdex::platform_id a, _In_ const stdex::platform_id b) { return a == IMAGE_FILE_MACHINE_UNKNOWN && b != IMAGE_FILE_MACHINE_UNKNOWN || a != IMAGE_FILE_MACHINE_UNKNOWN && b != IMAGE_FILE_MACHINE_UNKNOWN && strcmp(a, b) < 0; }
    +
    41inline bool operator <=(_In_ const stdex::platform_id a, _In_ const stdex::platform_id b) { return a == IMAGE_FILE_MACHINE_UNKNOWN || a != IMAGE_FILE_MACHINE_UNKNOWN && b != IMAGE_FILE_MACHINE_UNKNOWN && strcmp(a, b) <= 0; }
    +
    42inline bool operator >(_In_ const stdex::platform_id a, _In_ const stdex::platform_id b) { return a != IMAGE_FILE_MACHINE_UNKNOWN && b == IMAGE_FILE_MACHINE_UNKNOWN || a != IMAGE_FILE_MACHINE_UNKNOWN && b != IMAGE_FILE_MACHINE_UNKNOWN && strcmp(a, b) > 0; }
    +
    43inline bool operator >=(_In_ const stdex::platform_id a, _In_ const stdex::platform_id b) { return b == IMAGE_FILE_MACHINE_UNKNOWN || a != IMAGE_FILE_MACHINE_UNKNOWN && b != IMAGE_FILE_MACHINE_UNKNOWN && strcmp(a, b) >= 0; }
    +
    44#endif
    +
    45
    +
    46namespace stdex
    +
    47{
    +
    +
    51 const struct sys_info_t
    +
    52 {
    +
    56#if _M_IX86
    +
    57 static constexpr platform_id process_platform = IMAGE_FILE_MACHINE_I386;
    +
    58#elif _M_X64 // _M_ARM64EC is introducing as x64
    +
    59 static constexpr platform_id process_platform = IMAGE_FILE_MACHINE_AMD64;
    +
    60#elif _M_ARM
    +
    61 static constexpr platform_id process_platform = IMAGE_FILE_MACHINE_ARMNT;
    +
    62#elif _M_ARM64
    +
    63 static constexpr platform_id process_platform = IMAGE_FILE_MACHINE_ARM64;
    +
    64#elif __i386__
    +
    65 static constexpr platform_id process_platform = "i386";
    +
    66#elif __x86_64__
    +
    67 static constexpr platform_id process_platform = "x86_64";
    +
    68#elif __aarch64__
    +
    69 static constexpr platform_id process_platform = "aarch64";
    +
    70#else
    +
    71 #error Unknown platform
    +
    72#endif
    +
    73
    +
    77 platform_id os_platform;
    +
    78
    +
    79#ifdef _WIN32
    +
    83 bool wow64;
    +
    84#endif
    +
    85
    + +
    90
    +
    94 bool admin;
    +
    95
    + +
    100
    +
    101 sys_info_t() :
    +
    102 os_platform(IMAGE_FILE_MACHINE_UNKNOWN),
    +
    103#ifdef _WIN32
    +
    104 wow64(false),
    +
    105#endif
    + +
    107 admin(false),
    +
    108 elevated(false)
    +
    109 {
    +
    110#ifdef _WIN32
    +
    111 HMODULE kernel32_handle;
    +
    112 kernel32_handle = LoadLibrary(_T("kernel32.dll"));
    +
    113 _Assume_(kernel32_handle);
    +
    114 BOOL(WINAPI * IsWow64Process2)(HANDLE hProcess, USHORT * pProcessMachine, USHORT * pNativeMachine);
    +
    115 *reinterpret_cast<FARPROC*>(&IsWow64Process2) = GetProcAddress(kernel32_handle, "IsWow64Process2");
    +
    116 HANDLE process = GetCurrentProcess();
    +
    117 USHORT process_machine;
    +
    118#ifndef _WIN64
    +
    119 BOOL Wow64Process;
    +
    120#endif
    +
    121 if (IsWow64Process2 && IsWow64Process2(process, &process_machine, &os_platform)) {
    +
    122 wow64 = process_machine != IMAGE_FILE_MACHINE_UNKNOWN;
    +
    123 }
    +
    124#ifdef _WIN64
    +
    125 else {
    +
    126 os_platform = process_platform;
    +
    127 wow64 = false;
    +
    128 }
    +
    129#else
    +
    130 else if (IsWow64Process(process, &Wow64Process)) {
    +
    131 if (Wow64Process) {
    +
    132 os_platform = IMAGE_FILE_MACHINE_AMD64;
    +
    133 wow64 = true;
    134 }
    -
    135 }
    -
    136#endif
    -
    137 FreeLibrary(kernel32_handle);
    -
    138#else
    -
    139 memset(&m_utsn, 0, sizeof(m_utsn));
    -
    140 if (uname(&m_utsn) != -1)
    -
    141 os_platform = reinterpret_cast<platform_id>(m_utsn.machine);
    -
    142#endif
    -
    143
    -
    144#ifdef _WIN32
    -
    145 HWINSTA hWinSta = GetProcessWindowStation();
    -
    146 if (hWinSta) {
    -
    147 TCHAR sName[MAX_PATH];
    -
    148 if (GetUserObjectInformation(hWinSta, UOI_NAME, sName, sizeof(sName), NULL)) {
    -
    149 sName[_countof(sName) - 1] = 0;
    -
    150 // Only "WinSta0" is interactive (Source: KB171890)
    -
    151 interactive_process = _tcsicmp(sName, _T("WinSta0")) == 0;
    -
    152 }
    -
    153 }
    -
    154#else
    -
    155 // TODO: Research interactive process vs service/agent/daemon on this platform.
    -
    156#endif
    -
    157
    -
    158#if defined(_WIN32)
    -
    159 {
    -
    160 HANDLE token_h;
    -
    161 if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token_h)) {
    -
    162 sys_object token(token_h);
    -
    163
    -
    164 TOKEN_ELEVATION elevation;
    -
    165 DWORD size = sizeof(TOKEN_ELEVATION);
    -
    166 if (GetTokenInformation(token_h, TokenElevation, &elevation, sizeof(elevation), &size))
    -
    167 elevated = elevation.TokenIsElevated;
    -
    168
    -
    169 GetTokenInformation(token.get(), TokenGroups, NULL, 0, &size);
    -
    170 std::unique_ptr<TOKEN_GROUPS> groups((TOKEN_GROUPS*)new uint8_t[size]);
    -
    171 if (GetTokenInformation(token.get(), TokenGroups, (LPVOID)groups.get(), size, &size)) {
    -
    172 SID_IDENTIFIER_AUTHORITY authority = SECURITY_NT_AUTHORITY;
    -
    173 PSID sid_admins_h = NULL;
    -
    174 if (AllocateAndInitializeSid(&authority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &sid_admins_h)) {
    -
    175 struct SID_delete { void operator()(_In_ PSID p) const { FreeSid(p); } };
    -
    176 std::unique_ptr<void, SID_delete> sid_admins(sid_admins_h);
    -
    177 for (DWORD i = 0; i < groups->GroupCount; ++i)
    -
    178 if (EqualSid(sid_admins.get(), groups->Groups[i].Sid)) {
    -
    179 admin = true;
    -
    180 break;
    -
    181 }
    -
    182 }
    -
    183 }
    -
    184 }
    -
    185 }
    -
    186#elif defined(__APPLE__)
    -
    187 {
    -
    188 gid_t gids[NGROUPS + 1]; // A user cannot be member in more than NGROUPS groups, not counting the default group (hence the + 1)
    -
    189 for (int i = 0, n = getgroups(_countof(gids), gids); i < n; ++i) {
    -
    190 struct group* group = getgrgid(gids[i]);
    -
    191 if (!group) continue;
    -
    192 if (strcmp(group->gr_name, "admin") == 0) {
    -
    193 admin = true;
    -
    194 break;
    -
    195 }
    -
    196 }
    -
    197 }
    -
    198
    -
    199 elevated = geteuid() == 0;
    -
    200#else
    -
    201 // TODO: Set admin.
    -
    202 elevated = geteuid() == 0;
    -
    203#endif
    -
    204 }
    -
    205
    -
    206 protected:
    -
    207#ifndef _WIN32
    -
    208 struct utsname m_utsn;
    -
    209#endif
    -
    210 } sys_info;
    +
    135 else {
    +
    136 os_platform = process_platform;
    +
    137 wow64 = false;
    +
    138 }
    +
    139 }
    +
    140#endif
    +
    141 FreeLibrary(kernel32_handle);
    +
    142#else
    +
    143 memset(&m_utsn, 0, sizeof(m_utsn));
    +
    144 if (uname(&m_utsn) != -1)
    +
    145 os_platform = reinterpret_cast<platform_id>(m_utsn.machine);
    +
    146#endif
    +
    147
    +
    148#ifdef _WIN32
    +
    149 HWINSTA hWinSta = GetProcessWindowStation();
    +
    150 if (hWinSta) {
    +
    151 TCHAR sName[MAX_PATH];
    +
    152 if (GetUserObjectInformation(hWinSta, UOI_NAME, sName, sizeof(sName), NULL)) {
    +
    153 sName[_countof(sName) - 1] = 0;
    +
    154 // Only "WinSta0" is interactive (Source: KB171890)
    +
    155 interactive_process = _tcsicmp(sName, _T("WinSta0")) == 0;
    +
    156 }
    +
    157 }
    +
    158#else
    +
    159 // TODO: Research interactive process vs service/agent/daemon on this platform.
    +
    160#endif
    +
    161
    +
    162#if defined(_WIN32)
    +
    163 {
    +
    164 HANDLE token_h;
    +
    165 if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token_h)) {
    +
    166 sys_object token(token_h);
    +
    167
    +
    168 TOKEN_ELEVATION elevation;
    +
    169 DWORD size = sizeof(TOKEN_ELEVATION);
    +
    170 if (GetTokenInformation(token_h, TokenElevation, &elevation, sizeof(elevation), &size))
    +
    171 elevated = elevation.TokenIsElevated;
    +
    172
    +
    173 GetTokenInformation(token.get(), TokenGroups, NULL, 0, &size);
    +
    174 std::unique_ptr<TOKEN_GROUPS> groups((TOKEN_GROUPS*)new uint8_t[size]);
    +
    175 if (GetTokenInformation(token.get(), TokenGroups, (LPVOID)groups.get(), size, &size)) {
    +
    176 SID_IDENTIFIER_AUTHORITY authority = SECURITY_NT_AUTHORITY;
    +
    177 PSID sid_admins_h = NULL;
    +
    178 if (AllocateAndInitializeSid(&authority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &sid_admins_h)) {
    +
    179 struct SID_delete { void operator()(_In_ PSID p) const { FreeSid(p); } };
    +
    180 std::unique_ptr<void, SID_delete> sid_admins(sid_admins_h);
    +
    181 for (DWORD i = 0; i < groups->GroupCount; ++i)
    +
    182 if (EqualSid(sid_admins.get(), groups->Groups[i].Sid)) {
    +
    183 admin = true;
    +
    184 break;
    +
    185 }
    +
    186 }
    +
    187 }
    +
    188 }
    +
    189 }
    +
    190#elif defined(__APPLE__)
    +
    191 {
    +
    192 gid_t gids[NGROUPS + 1]; // A user cannot be member in more than NGROUPS groups, not counting the default group (hence the + 1)
    +
    193 for (int i = 0, n = getgroups(_countof(gids), gids); i < n; ++i) {
    +
    194 struct group* group = getgrgid(gids[i]);
    +
    195 if (!group) continue;
    +
    196 if (strcmp(group->gr_name, "admin") == 0) {
    +
    197 admin = true;
    +
    198 break;
    +
    199 }
    +
    200 }
    +
    201 }
    +
    202
    +
    203 elevated = geteuid() == 0;
    +
    204#else
    +
    205 // TODO: Set admin.
    +
    206 elevated = geteuid() == 0;
    +
    207#endif
    +
    208 }
    +
    209
    +
    210 protected:
    +
    211#ifndef _WIN32
    +
    212 struct utsname m_utsn;
    +
    213#endif
    +
    214 } sys_info;
    -
    211}
    -
    Operating system object (file, pipe, anything with an OS handle etc.)
    Definition system.hpp:91
    -
    sys_handle get() const noexcept
    Returns object handle.
    Definition system.hpp:148
    -
    System information.
    Definition sys_info.hpp:50
    -
    bool admin
    Is member of local group Administrators (Windows) or member of group wheel/sudoers (others)?
    Definition sys_info.hpp:92
    -
    bool elevated
    Is elevated process (Windows) or running as root (others)?
    Definition sys_info.hpp:97
    -
    platform_id os_platform
    The platform this process was compiled for.
    Definition sys_info.hpp:75
    -
    bool interactive_process
    Is interactive process?
    Definition sys_info.hpp:87
    +
    215}
    +
    Operating system object (file, pipe, anything with an OS handle etc.)
    Definition system.hpp:93
    +
    sys_handle get() const noexcept
    Returns object handle.
    Definition system.hpp:150
    +
    System information.
    Definition sys_info.hpp:52
    +
    bool admin
    Is member of local group Administrators (Windows) or member of group wheel/sudoers (others)?
    Definition sys_info.hpp:94
    +
    bool elevated
    Is elevated process (Windows) or running as root (others)?
    Definition sys_info.hpp:99
    +
    platform_id os_platform
    The platform this process was compiled for.
    Definition sys_info.hpp:77
    +
    bool interactive_process
    Is interactive process?
    Definition sys_info.hpp:89
    diff --git a/system_8hpp_source.html b/system_8hpp_source.html index 0b6e1afb1..fc683cabf 100644 --- a/system_8hpp_source.html +++ b/system_8hpp_source.html @@ -95,199 +95,201 @@ $(document).ready(function() { init_codefold(0); });
    11#include <oaidl.h>
    12#include <tchar.h>
    13#else
    -
    14#define _LARGEFILE64_SOURCE // TODO: Make this -D compile-time project setting
    -
    15#include <grp.h>
    -
    16#include <pwd.h>
    -
    17#include <string.h>
    -
    18#include <sys/types.h>
    -
    19#include <unistd.h>
    -
    20#endif
    -
    21#include <regex>
    -
    22#include <stdexcept>
    -
    23#include <string>
    -
    24
    -
    25#if defined(_WIN32)
    -
    26#define PATH_SEPARATOR '\\'
    -
    27#define PATH_SEPARATOR_STR "\\"
    -
    28#else
    -
    29#define PATH_SEPARATOR '/'
    -
    30#define PATH_SEPARATOR_STR "/"
    -
    31#endif
    -
    32
    -
    33namespace stdex
    -
    34{
    -
    38#if defined(_WIN32)
    -
    39 using sys_handle = HANDLE;
    -
    40 const sys_handle invalid_handle = INVALID_HANDLE_VALUE;
    -
    41#else
    -
    42 using sys_handle = int;
    -
    43 const sys_handle invalid_handle = (sys_handle)-1;
    -
    44#endif
    -
    45
    -
    49#if defined(_WIN32)
    -
    50 inline DWORD sys_error() { return GetLastError(); }
    -
    51#else
    -
    52 inline int sys_error() { return errno; }
    -
    53#endif
    -
    54
    -
    58#if defined(_WIN32)
    -
    59 using schar_t = TCHAR;
    -
    60#else
    -
    61 using schar_t = char;
    -
    62#define _T(x) x
    -
    63#endif
    -
    64
    -
    69 using sys_char = schar_t;
    -
    70
    -
    74 using sstring = std::basic_string<stdex::schar_t>;
    -
    75
    -
    80 using sys_string = sstring;
    -
    81
    -
    85 using sregex = std::basic_regex<stdex::schar_t>;
    -
    86
    -
    - -
    91 {
    -
    92 public:
    -
    93 sys_object(_In_opt_ sys_handle h = invalid_handle) : m_h(h) {}
    -
    94
    -
    95 sys_object(_In_ const sys_object& other) : m_h(other.m_h != invalid_handle ? duplicate(other.m_h, false) : invalid_handle) {}
    +
    14#ifndef _LARGEFILE64_SOURCE
    +
    15#define _LARGEFILE64_SOURCE // TODO: Make this -D compile-time project setting
    +
    16#endif
    +
    17#include <grp.h>
    +
    18#include <pwd.h>
    +
    19#include <string.h>
    +
    20#include <sys/types.h>
    +
    21#include <unistd.h>
    +
    22#endif
    +
    23#include <regex>
    +
    24#include <stdexcept>
    +
    25#include <string>
    +
    26
    +
    27#if defined(_WIN32)
    +
    28#define PATH_SEPARATOR '\\'
    +
    29#define PATH_SEPARATOR_STR "\\"
    +
    30#else
    +
    31#define PATH_SEPARATOR '/'
    +
    32#define PATH_SEPARATOR_STR "/"
    +
    33#endif
    +
    34
    +
    35namespace stdex
    +
    36{
    +
    40#if defined(_WIN32)
    +
    41 using sys_handle = HANDLE;
    +
    42 const sys_handle invalid_handle = INVALID_HANDLE_VALUE;
    +
    43#else
    +
    44 using sys_handle = int;
    +
    45 const sys_handle invalid_handle = (sys_handle)-1;
    +
    46#endif
    +
    47
    +
    51#if defined(_WIN32)
    +
    52 inline DWORD sys_error() { return GetLastError(); }
    +
    53#else
    +
    54 inline int sys_error() { return errno; }
    +
    55#endif
    +
    56
    +
    60#if defined(_WIN32)
    +
    61 using schar_t = TCHAR;
    +
    62#else
    +
    63 using schar_t = char;
    +
    64#define _T(x) x
    +
    65#endif
    +
    66
    +
    71 using sys_char = schar_t;
    +
    72
    +
    76 using sstring = std::basic_string<stdex::schar_t>;
    +
    77
    +
    82 using sys_string = sstring;
    +
    83
    +
    87 using sregex = std::basic_regex<stdex::schar_t>;
    +
    88
    +
    + +
    93 {
    +
    94 public:
    +
    95 sys_object(_In_opt_ sys_handle h = invalid_handle) : m_h(h) {}
    96
    -
    97 sys_object& operator =(_In_ const sys_object& other)
    -
    98 {
    -
    99 if (this != std::addressof(other)) {
    -
    100 if (m_h != invalid_handle)
    -
    101 close(m_h);
    -
    102 m_h = other.m_h != invalid_handle ? duplicate(other.m_h, false) : invalid_handle;
    -
    103 }
    -
    104 return *this;
    -
    105 }
    -
    106
    -
    107 sys_object(_Inout_ sys_object&& other) noexcept : m_h(other.m_h)
    -
    108 {
    -
    109 other.m_h = invalid_handle;
    -
    110 }
    -
    111
    -
    112 sys_object& operator =(_Inout_ sys_object&& other) noexcept
    -
    113 {
    -
    114 if (this != std::addressof(other)) {
    -
    115 if (m_h != invalid_handle)
    -
    116 close(m_h);
    -
    117 m_h = other.m_h;
    -
    118 other.m_h = invalid_handle;
    -
    119 }
    -
    120 return *this;
    -
    121 }
    -
    122
    -
    123 virtual ~sys_object() noexcept(false)
    -
    124 {
    -
    125 if (m_h != invalid_handle)
    -
    126 close(m_h);
    -
    127 }
    -
    128
    -
    -
    132 virtual void close()
    -
    133 {
    -
    134 if (m_h != invalid_handle) {
    -
    135 close(m_h);
    -
    136 m_h = invalid_handle;
    -
    137 }
    -
    138 }
    +
    97 sys_object(_In_ const sys_object& other) : m_h(other.m_h != invalid_handle ? duplicate(other.m_h, false) : invalid_handle) {}
    +
    98
    +
    99 sys_object& operator =(_In_ const sys_object& other)
    +
    100 {
    +
    101 if (this != std::addressof(other)) {
    +
    102 if (m_h != invalid_handle)
    +
    103 close(m_h);
    +
    104 m_h = other.m_h != invalid_handle ? duplicate(other.m_h, false) : invalid_handle;
    +
    105 }
    +
    106 return *this;
    +
    107 }
    +
    108
    +
    109 sys_object(_Inout_ sys_object&& other) noexcept : m_h(other.m_h)
    +
    110 {
    +
    111 other.m_h = invalid_handle;
    +
    112 }
    +
    113
    +
    114 sys_object& operator =(_Inout_ sys_object&& other) noexcept
    +
    115 {
    +
    116 if (this != std::addressof(other)) {
    +
    117 if (m_h != invalid_handle)
    +
    118 close(m_h);
    +
    119 m_h = other.m_h;
    +
    120 other.m_h = invalid_handle;
    +
    121 }
    +
    122 return *this;
    +
    123 }
    +
    124
    +
    125 virtual ~sys_object() noexcept(false)
    +
    126 {
    +
    127 if (m_h != invalid_handle)
    +
    128 close(m_h);
    +
    129 }
    +
    130
    +
    +
    134 virtual void close()
    +
    135 {
    +
    136 if (m_h != invalid_handle) {
    +
    137 close(m_h);
    +
    138 m_h = invalid_handle;
    +
    139 }
    +
    140 }
    -
    139
    -
    143 inline operator bool() const noexcept { return m_h != invalid_handle; }
    -
    144
    -
    148 inline sys_handle get() const noexcept { return m_h; }
    -
    149
    -
    150 protected:
    -
    -
    154 static void close(_In_ sys_handle h)
    -
    155 {
    -
    156#ifdef _WIN32
    -
    157 if (CloseHandle(h) || GetLastError() == ERROR_INVALID_HANDLE)
    -
    158 return;
    -
    159 throw std::system_error(GetLastError(), std::system_category(), "CloseHandle failed");
    -
    160#else
    -
    161 if (::close(h) >= 0 || errno == EBADF)
    -
    162 return;
    -
    163 throw std::system_error(errno, std::system_category(), "close failed");
    -
    164#endif
    -
    165 }
    +
    141
    +
    145 inline operator bool() const noexcept { return m_h != invalid_handle; }
    +
    146
    +
    150 inline sys_handle get() const noexcept { return m_h; }
    +
    151
    +
    152 protected:
    +
    +
    156 static void close(_In_ sys_handle h)
    +
    157 {
    +
    158#ifdef _WIN32
    +
    159 if (CloseHandle(h) || GetLastError() == ERROR_INVALID_HANDLE)
    +
    160 return;
    +
    161 throw std::system_error(GetLastError(), std::system_category(), "CloseHandle failed");
    +
    162#else
    +
    163 if (::close(h) >= 0 || errno == EBADF)
    +
    164 return;
    +
    165 throw std::system_error(errno, std::system_category(), "close failed");
    +
    166#endif
    +
    167 }
    -
    166
    -
    -
    170 static sys_handle duplicate(_In_ sys_handle h, _In_ bool inherit)
    -
    171 {
    -
    172 sys_handle h_new;
    -
    173#ifdef _WIN32
    -
    174 HANDLE process = GetCurrentProcess();
    -
    175 if (DuplicateHandle(process, h, process, &h_new, 0, inherit, DUPLICATE_SAME_ACCESS))
    -
    176 return h_new;
    -
    177 throw std::system_error(GetLastError(), std::system_category(), "DuplicateHandle failed");
    -
    178#else
    -
    179 _Unreferenced_(inherit);
    -
    180 if ((h_new = dup(h)) >= 0)
    -
    181 return h_new;
    -
    182 throw std::system_error(errno, std::system_category(), "dup failed");
    -
    183#endif
    -
    184 }
    +
    168
    +
    +
    172 static sys_handle duplicate(_In_ sys_handle h, _In_ bool inherit)
    +
    173 {
    +
    174 sys_handle h_new;
    +
    175#ifdef _WIN32
    +
    176 HANDLE process = GetCurrentProcess();
    +
    177 if (DuplicateHandle(process, h, process, &h_new, 0, inherit, DUPLICATE_SAME_ACCESS))
    +
    178 return h_new;
    +
    179 throw std::system_error(GetLastError(), std::system_category(), "DuplicateHandle failed");
    +
    180#else
    +
    181 _Unreferenced_(inherit);
    +
    182 if ((h_new = dup(h)) >= 0)
    +
    183 return h_new;
    +
    184 throw std::system_error(errno, std::system_category(), "dup failed");
    +
    185#endif
    +
    186 }
    -
    185
    -
    186 protected:
    -
    187 sys_handle m_h;
    -
    188 };
    +
    187
    +
    188 protected:
    +
    189 sys_handle m_h;
    +
    190 };
    -
    189
    -
    190#ifdef _WIN32
    -
    191 template <class T>
    -
    192 class safearray_accessor
    -
    193 {
    -
    194 public:
    -
    195 safearray_accessor(_In_ LPSAFEARRAY sa) : m_sa(sa)
    -
    196 {
    -
    197 HRESULT hr = SafeArrayAccessData(sa, reinterpret_cast<void HUGEP**>(&m_data));
    -
    198 if (FAILED(hr))
    -
    199 throw std::system_error(hr, std::system_category(), "SafeArrayAccessData failed");
    -
    200 }
    -
    201
    -
    202 ~safearray_accessor()
    -
    203 {
    -
    204 SafeArrayUnaccessData(m_sa);
    -
    205 }
    -
    206
    -
    207 T* data() const { return m_data; }
    +
    191
    +
    192#ifdef _WIN32
    +
    193 template <class T>
    +
    194 class safearray_accessor
    +
    195 {
    +
    196 public:
    +
    197 safearray_accessor(_In_ LPSAFEARRAY sa) : m_sa(sa)
    +
    198 {
    +
    199 HRESULT hr = SafeArrayAccessData(sa, reinterpret_cast<void HUGEP**>(&m_data));
    +
    200 if (FAILED(hr))
    +
    201 throw std::system_error(hr, std::system_category(), "SafeArrayAccessData failed");
    +
    202 }
    +
    203
    +
    204 ~safearray_accessor()
    +
    205 {
    +
    206 SafeArrayUnaccessData(m_sa);
    +
    207 }
    208
    -
    209 protected:
    -
    210 LPSAFEARRAY m_sa;
    -
    211 T* m_data;
    -
    212 };
    -
    213
    -
    217 struct SafeArrayDestroy_delete
    -
    218 {
    -
    222 void operator()(_In_ LPSAFEARRAY sa) const
    -
    223 {
    -
    224 SafeArrayDestroy(sa);
    -
    225 }
    -
    226 };
    -
    227
    -
    231 struct SysFreeString_delete
    -
    232 {
    -
    236 void operator()(_In_ BSTR sa) const
    -
    237 {
    -
    238 SysFreeString(sa);
    -
    239 }
    -
    240 };
    -
    241#endif
    -
    242}
    -
    Operating system object (file, pipe, anything with an OS handle etc.)
    Definition system.hpp:91
    -
    sys_handle get() const noexcept
    Returns object handle.
    Definition system.hpp:148
    -
    virtual void close()
    Closes object.
    Definition system.hpp:132
    -
    static sys_handle duplicate(sys_handle h, bool inherit)
    Duplicates given object.
    Definition system.hpp:170
    -
    static void close(sys_handle h)
    Closes object.
    Definition system.hpp:154
    +
    209 T* data() const { return m_data; }
    +
    210
    +
    211 protected:
    +
    212 LPSAFEARRAY m_sa;
    +
    213 T* m_data;
    +
    214 };
    +
    215
    +
    219 struct SafeArrayDestroy_delete
    +
    220 {
    +
    224 void operator()(_In_ LPSAFEARRAY sa) const
    +
    225 {
    +
    226 SafeArrayDestroy(sa);
    +
    227 }
    +
    228 };
    +
    229
    +
    233 struct SysFreeString_delete
    +
    234 {
    +
    238 void operator()(_In_ BSTR sa) const
    +
    239 {
    +
    240 SysFreeString(sa);
    +
    241 }
    +
    242 };
    +
    243#endif
    +
    244}
    +
    Operating system object (file, pipe, anything with an OS handle etc.)
    Definition system.hpp:93
    +
    sys_handle get() const noexcept
    Returns object handle.
    Definition system.hpp:150
    +
    virtual void close()
    Closes object.
    Definition system.hpp:134
    +
    static sys_handle duplicate(sys_handle h, bool inherit)
    Duplicates given object.
    Definition system.hpp:172
    +
    static void close(sys_handle h)
    Closes object.
    Definition system.hpp:156
    diff --git a/unicode_8cpp_source.html b/unicode_8cpp_source.html index 0ab46b193..34a633eeb 100644 --- a/unicode_8cpp_source.html +++ b/unicode_8cpp_source.html @@ -177,11 +177,11 @@ $(document).ready(function() { init_codefold(0); });
    93#ifndef _WIN32
    94#pragma GCC diagnostic pop
    95#endif
    -
    Encoding converter context.
    Definition unicode.hpp:64
    +
    Encoding converter context.
    Definition unicode.hpp:70
    diff --git a/unicode_8hpp_source.html b/unicode_8hpp_source.html index 377223b1b..4a1ddcb84 100644 --- a/unicode_8hpp_source.html +++ b/unicode_8hpp_source.html @@ -92,604 +92,614 @@ $(document).ready(function() { init_codefold(0); });
    8#include "compat.hpp"
    9#include "endian.hpp"
    10#include "math.hpp"
    -
    11#include <stdint.h>
    -
    12#ifndef _WIN32
    -
    13#include <iconv.h>
    -
    14#include <langinfo.h>
    -
    15#endif
    -
    16#include <map>
    -
    17#include <memory>
    -
    18#include <string>
    -
    19
    -
    20namespace stdex
    -
    21{
    -
    22 enum class charset_id : uint16_t {
    -
    23#ifdef _WIN32
    -
    24 system = CP_ACP,
    -
    25 oem = CP_OEMCP,
    -
    26 utf7 = CP_UTF7,
    -
    27 utf8 = CP_UTF8,
    -
    28 utf16 = 1200 /*CP_WINUNICODE*/,
    -
    29 utf32 = 12000,
    -
    30 windows1250 = 1250,
    -
    31 windows1251 = 1251,
    -
    32 windows1252 = 1252,
    -
    33#else
    -
    34 system = 0,
    -
    35 utf7,
    -
    36 utf8,
    -
    37 utf16,
    -
    38 utf32,
    -
    39 windows1250,
    -
    40 windows1251,
    -
    41 windows1252,
    -
    42
    -
    43 _max
    -
    44#endif
    -
    45 };
    -
    46
    -
    47#ifdef _WIN32
    -
    48 constexpr charset_id wchar_t_charset = charset_id::utf16;
    -
    49#ifdef _UNICODE
    -
    50 constexpr charset_id system_charset = charset_id::utf16;
    -
    51#else
    -
    52 constexpr charset_id system_charset = charset_id::system;
    -
    53#endif
    -
    54#else
    -
    55 constexpr charset_id wchar_t_charset = charset_id::utf32;
    -
    56 constexpr charset_id system_charset = charset_id::system;
    -
    57#endif
    -
    58
    -
    62 template <typename T_from, typename T_to>
    -
    - -
    64 {
    -
    65 protected:
    -
    66 charset_id m_from, m_to;
    -
    67
    -
    68 public:
    -
    69 charset_encoder(_In_ charset_id from, _In_ charset_id to) :
    -
    70 m_from(from),
    -
    71 m_to(to)
    -
    72 {
    -
    73#ifdef _WIN32
    -
    74 m_from_wincp = to_encoding(from);
    -
    75 m_to_wincp = to_encoding(to);
    -
    76#else
    -
    77 m_handle = iconv_open(to_encoding(to), to_encoding(from));
    -
    78 if (m_handle == (iconv_t)-1)
    -
    79 throw std::system_error(errno, std::system_category(), "iconv_open failed");
    -
    80#endif
    -
    81 }
    -
    82
    -
    83#ifndef _WIN32
    - -
    85 {
    -
    86 iconv_close(m_handle);
    +
    11#include "string.hpp"
    +
    12#include <stdint.h>
    +
    13#ifndef _WIN32
    +
    14#include <iconv.h>
    +
    15#include <langinfo.h>
    +
    16#endif
    +
    17#include <map>
    +
    18#include <memory>
    +
    19#include <string>
    +
    20
    +
    21#ifndef _WIN32
    +
    22#pragma GCC diagnostic push
    +
    23#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
    +
    24#endif
    +
    25
    +
    26namespace stdex
    +
    27{
    +
    28 enum class charset_id : uint16_t {
    +
    29#ifdef _WIN32
    +
    30 system = CP_ACP,
    +
    31 oem = CP_OEMCP,
    +
    32 utf7 = CP_UTF7,
    +
    33 utf8 = CP_UTF8,
    +
    34 utf16 = 1200 /*CP_WINUNICODE*/,
    +
    35 utf32 = 12000,
    +
    36 windows1250 = 1250,
    +
    37 windows1251 = 1251,
    +
    38 windows1252 = 1252,
    +
    39#else
    +
    40 system = 0,
    +
    41 utf7,
    +
    42 utf8,
    +
    43 utf16,
    +
    44 utf32,
    +
    45 windows1250,
    +
    46 windows1251,
    +
    47 windows1252,
    +
    48
    +
    49 _max
    +
    50#endif
    +
    51 };
    +
    52
    +
    53#ifdef _WIN32
    +
    54 constexpr charset_id wchar_t_charset = charset_id::utf16;
    +
    55#ifdef _UNICODE
    +
    56 constexpr charset_id system_charset = charset_id::utf16;
    +
    57#else
    +
    58 constexpr charset_id system_charset = charset_id::system;
    +
    59#endif
    +
    60#else
    +
    61 constexpr charset_id wchar_t_charset = charset_id::utf32;
    +
    62 constexpr charset_id system_charset = charset_id::system;
    +
    63#endif
    +
    64
    +
    68 template <typename T_from, typename T_to>
    +
    + +
    70 {
    +
    71 protected:
    +
    72 charset_id m_from, m_to;
    +
    73
    +
    74 public:
    +
    75 charset_encoder(_In_ charset_id from, _In_ charset_id to) :
    +
    76 m_from(from),
    +
    77 m_to(to)
    +
    78 {
    +
    79#ifdef _WIN32
    +
    80 m_from_wincp = to_encoding(from);
    +
    81 m_to_wincp = to_encoding(to);
    +
    82#else
    +
    83 m_handle = iconv_open(to_encoding(to), to_encoding(from));
    +
    84 if (m_handle == (iconv_t)-1)
    +
    85 throw std::system_error(errno, std::system_category(), "iconv_open failed");
    +
    86#endif
    87 }
    -
    88#endif
    -
    89
    -
    90 inline charset_id from_encoding() const { return m_from; }
    -
    91 inline charset_id to_encoding() const { return m_to; }
    -
    92
    -
    100 template <class _Traits_to = std::char_traits<T_to>, class _Alloc_to = std::allocator<T_to>>
    -
    -
    101 void strcat(
    -
    102 _Inout_ std::basic_string<T_to, _Traits_to, _Alloc_to> &dst,
    -
    103 _In_reads_or_z_opt_(count_src) const T_from* src, _In_ size_t count_src)
    -
    104 {
    -
    105 _Assume_(src || !count_src);
    -
    106 count_src = stdex::strnlen(src, count_src);
    -
    107 if (!count_src) _Unlikely_
    -
    108 return;
    -
    109
    -
    110#ifdef _WIN32
    -
    111 constexpr DWORD dwFlagsMBWC = MB_PRECOMPOSED;
    -
    112 constexpr DWORD dwFlagsWCMB = 0;
    -
    113 constexpr LPCCH lpDefaultChar = NULL;
    -
    114
    -
    115 _Assume_(src);
    -
    116 if (m_from_wincp == m_to_wincp) _Unlikely_{
    -
    117 dst.append(reinterpret_cast<const T_to*>(src), count_src);
    -
    118 return;
    -
    119 }
    +
    88
    +
    89#ifndef _WIN32
    + +
    91 {
    +
    92 iconv_close(m_handle);
    +
    93 }
    +
    94#endif
    +
    95
    +
    96 inline charset_id from_encoding() const { return m_from; }
    +
    97 inline charset_id to_encoding() const { return m_to; }
    +
    98
    +
    106 template <class _Traits_to = std::char_traits<T_to>, class _Alloc_to = std::allocator<T_to>>
    +
    +
    107 void strcat(
    +
    108 _Inout_ std::basic_string<T_to, _Traits_to, _Alloc_to> &dst,
    +
    109 _In_reads_or_z_opt_(count_src) const T_from* src, _In_ size_t count_src)
    +
    110 {
    +
    111 _Assume_(src || !count_src);
    +
    112 count_src = stdex::strnlen<T_from>(src, count_src);
    +
    113 if (!count_src) _Unlikely_
    +
    114 return;
    +
    115
    +
    116#ifdef _WIN32
    +
    117 constexpr DWORD dwFlagsMBWC = MB_PRECOMPOSED;
    +
    118 constexpr DWORD dwFlagsWCMB = 0;
    +
    119 constexpr LPCCH lpDefaultChar = NULL;
    120
    -
    121#pragma warning(suppress: 4127)
    -
    122 if _Constexpr_ (sizeof(T_from) == sizeof(char) && sizeof(T_to) == sizeof(wchar_t)) {
    -
    123 _Assume_(count_src < INT_MAX || count_src == SIZE_MAX);
    -
    124
    -
    125 // Try to convert to stack buffer first.
    -
    126 WCHAR szStackBuffer[1024 / sizeof(WCHAR)];
    -
    127#pragma warning(suppress: 6387) // Testing indicates src may be NULL when count_src is also 0. Is SAL of the lpMultiByteStr parameter wrong?
    -
    128 int cch = MultiByteToWideChar(static_cast<UINT>(m_from_wincp), dwFlagsMBWC, reinterpret_cast<LPCCH>(src), static_cast<int>(count_src), szStackBuffer, _countof(szStackBuffer));
    -
    129 if (cch) {
    -
    130 // Append from stack.
    -
    131 dst.append(reinterpret_cast<const T_to*>(szStackBuffer), count_src != SIZE_MAX ? wcsnlen(szStackBuffer, cch) : static_cast<size_t>(cch) - 1);
    -
    132 return;
    -
    133 }
    -
    134 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
    -
    135 // Query the required output size. Allocate buffer. Then convert again.
    -
    136 cch = MultiByteToWideChar(static_cast<UINT>(m_from_wincp), dwFlagsMBWC, reinterpret_cast<LPCCH>(src), static_cast<int>(count_src), NULL, 0);
    -
    137 std::unique_ptr<WCHAR[]> szBuffer(new WCHAR[cch]);
    -
    138 cch = MultiByteToWideChar(static_cast<UINT>(m_from_wincp), dwFlagsMBWC, reinterpret_cast<LPCCH>(src), static_cast<int>(count_src), szBuffer.get(), cch);
    -
    139 dst.append(reinterpret_cast<const T_to*>(szBuffer.get()), count_src != SIZE_MAX ? wcsnlen(szBuffer.get(), cch) : static_cast<size_t>(cch) - 1);
    -
    140 return;
    -
    141 }
    -
    142 throw std::system_error(GetLastError(), std::system_category(), "MultiByteToWideChar failed");
    -
    143 }
    -
    144
    -
    145#pragma warning(suppress: 4127)
    -
    146 if _Constexpr_ (sizeof(T_from) == sizeof(wchar_t) && sizeof(T_to) == sizeof(char)) {
    -
    147 _Assume_(count_src < INT_MAX || count_src == SIZE_MAX);
    -
    148
    -
    149 // Try to convert to stack buffer first.
    -
    150 CHAR szStackBuffer[1024 / sizeof(CHAR)];
    -
    151#pragma warning(suppress: 6387) // Testing indicates src may be NULL when count_src is also 0. Is SAL of the lpWideCharStr parameter wrong?
    -
    152 int cch = WideCharToMultiByte(static_cast<UINT>(m_to_wincp), dwFlagsWCMB, reinterpret_cast<LPCWCH>(src), static_cast<int>(count_src), szStackBuffer, _countof(szStackBuffer), lpDefaultChar, NULL);
    -
    153 if (cch) {
    -
    154 // Copy from stack. Be careful not to include zero terminator.
    -
    155 dst.append(reinterpret_cast<const T_to*>(szStackBuffer), count_src != SIZE_MAX ? strnlen(szStackBuffer, cch) : static_cast<size_t>(cch) - 1);
    -
    156 return;
    -
    157 }
    -
    158 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
    -
    159 // Query the required output size. Allocate buffer. Then convert again.
    -
    160 cch = WideCharToMultiByte(static_cast<UINT>(m_to_wincp), dwFlagsWCMB, reinterpret_cast<LPCWCH>(src), static_cast<int>(count_src), NULL, 0, lpDefaultChar, NULL);
    -
    161 std::unique_ptr<CHAR[]> szBuffer(new CHAR[cch]);
    -
    162 cch = WideCharToMultiByte(static_cast<UINT>(m_to_wincp), dwFlagsWCMB, reinterpret_cast<LPCWCH>(src), static_cast<int>(count_src), szBuffer.get(), cch, lpDefaultChar, NULL);
    -
    163 dst.append(reinterpret_cast<const T_to*>(szBuffer.get()), count_src != SIZE_MAX ? strnlen(szBuffer.get(), cch) : static_cast<size_t>(cch) - 1);
    -
    164 return;
    -
    165 }
    -
    166 throw std::system_error(GetLastError(), std::system_category(), "WideCharToMultiByte failed");
    -
    167 }
    -
    168
    -
    169#pragma warning(suppress: 4127)
    -
    170 if _Constexpr_ (sizeof(T_from) == sizeof(char) && sizeof(T_to) == sizeof(char)) {
    -
    171 _Assume_(count_src < INT_MAX || count_src == SIZE_MAX);
    -
    172
    -
    173 // Try to convert to stack buffer first.
    -
    174 WCHAR szStackBufferMBWC[512 / sizeof(WCHAR)];
    -
    175#pragma warning(suppress: 6387) // Testing indicates src may be NULL when count_src is also 0. Is SAL of the lpMultiByteStr parameter wrong?
    -
    176 int cch = MultiByteToWideChar(static_cast<UINT>(m_from_wincp), dwFlagsMBWC, reinterpret_cast<LPCCH>(src), static_cast<int>(count_src), szStackBufferMBWC, _countof(szStackBufferMBWC));
    -
    177 if (cch) {
    -
    178 // Append from stack.
    -
    179 size_t count_inter = count_src != SIZE_MAX ? wcsnlen(szStackBufferMBWC, cch) : static_cast<size_t>(cch) - 1;
    -
    180 _Assume_(count_inter < INT_MAX);
    -
    181
    -
    182 // Try to convert to stack buffer first.
    -
    183 CHAR szStackBufferWCMB[512 / sizeof(CHAR)];
    -
    184#pragma warning(suppress: 6387) // Testing indicates szStackBufferMBWC may be NULL when count_inter is also 0. Is SAL of the lpWideCharStr parameter wrong?
    -
    185 cch = WideCharToMultiByte(static_cast<UINT>(m_to_wincp), dwFlagsWCMB, szStackBufferMBWC, static_cast<int>(count_inter), szStackBufferWCMB, _countof(szStackBufferWCMB), lpDefaultChar, NULL);
    -
    186 if (cch) {
    -
    187 // Copy from stack. Be careful not to include zero terminator.
    -
    188 dst.append(reinterpret_cast<const T_to*>(szStackBufferWCMB), strnlen(szStackBufferWCMB, cch));
    -
    189 return;
    -
    190 }
    -
    191 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
    -
    192 // Query the required output size. Allocate buffer. Then convert again.
    -
    193 cch = WideCharToMultiByte(static_cast<UINT>(m_to_wincp), dwFlagsWCMB, szStackBufferMBWC, static_cast<int>(count_inter), NULL, 0, lpDefaultChar, NULL);
    -
    194 std::unique_ptr<CHAR[]> szBufferWCMB(new CHAR[cch]);
    -
    195 cch = WideCharToMultiByte(static_cast<UINT>(m_to_wincp), dwFlagsWCMB, szStackBufferMBWC, static_cast<int>(count_inter), szBufferWCMB.get(), cch, lpDefaultChar, NULL);
    -
    196 dst.append(reinterpret_cast<const T_to*>(szBufferWCMB.get()), strnlen(szBufferWCMB.get(), cch));
    -
    197 return;
    -
    198 }
    -
    199 throw std::system_error(GetLastError(), std::system_category(), "WideCharToMultiByte failed");
    -
    200 }
    -
    201 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
    -
    202 // Query the required output size. Allocate buffer. Then convert again.
    -
    203 cch = MultiByteToWideChar(static_cast<UINT>(m_from_wincp), dwFlagsMBWC, reinterpret_cast<LPCCH>(src), static_cast<int>(count_src), NULL, 0);
    -
    204 std::unique_ptr<WCHAR[]> szBufferMBWC(new WCHAR[cch]);
    -
    205 cch = MultiByteToWideChar(static_cast<UINT>(m_from_wincp), dwFlagsMBWC, reinterpret_cast<LPCCH>(src), static_cast<int>(count_src), szBufferMBWC.get(), cch);
    -
    206 size_t count_inter = count_src != SIZE_MAX ? wcsnlen(szBufferMBWC.get(), cch) : static_cast<size_t>(cch) - 1;
    -
    207
    +
    121 _Assume_(src);
    +
    122 if (m_from_wincp == m_to_wincp) _Unlikely_{
    +
    123 dst.append(reinterpret_cast<const T_to*>(src), count_src);
    +
    124 return;
    +
    125 }
    +
    126
    +
    127#pragma warning(suppress: 4127)
    +
    128 if _Constexpr_ (sizeof(T_from) == sizeof(char) && sizeof(T_to) == sizeof(wchar_t)) {
    +
    129 _Assume_(count_src < INT_MAX || count_src == SIZE_MAX);
    +
    130
    +
    131 // Try to convert to stack buffer first.
    +
    132 WCHAR szStackBuffer[1024 / sizeof(WCHAR)];
    +
    133#pragma warning(suppress: 6387) // Testing indicates src may be NULL when count_src is also 0. Is SAL of the lpMultiByteStr parameter wrong?
    +
    134 int cch = MultiByteToWideChar(static_cast<UINT>(m_from_wincp), dwFlagsMBWC, reinterpret_cast<LPCCH>(src), static_cast<int>(count_src), szStackBuffer, _countof(szStackBuffer));
    +
    135 if (cch) {
    +
    136 // Append from stack.
    +
    137 dst.append(reinterpret_cast<const T_to*>(szStackBuffer), count_src != SIZE_MAX ? wcsnlen(szStackBuffer, cch) : static_cast<size_t>(cch) - 1);
    +
    138 return;
    +
    139 }
    +
    140 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
    +
    141 // Query the required output size. Allocate buffer. Then convert again.
    +
    142 cch = MultiByteToWideChar(static_cast<UINT>(m_from_wincp), dwFlagsMBWC, reinterpret_cast<LPCCH>(src), static_cast<int>(count_src), NULL, 0);
    +
    143 std::unique_ptr<WCHAR[]> szBuffer(new WCHAR[cch]);
    +
    144 cch = MultiByteToWideChar(static_cast<UINT>(m_from_wincp), dwFlagsMBWC, reinterpret_cast<LPCCH>(src), static_cast<int>(count_src), szBuffer.get(), cch);
    +
    145 dst.append(reinterpret_cast<const T_to*>(szBuffer.get()), count_src != SIZE_MAX ? wcsnlen(szBuffer.get(), cch) : static_cast<size_t>(cch) - 1);
    +
    146 return;
    +
    147 }
    +
    148 throw std::system_error(GetLastError(), std::system_category(), "MultiByteToWideChar failed");
    +
    149 }
    +
    150
    +
    151#pragma warning(suppress: 4127)
    +
    152 if _Constexpr_ (sizeof(T_from) == sizeof(wchar_t) && sizeof(T_to) == sizeof(char)) {
    +
    153 _Assume_(count_src < INT_MAX || count_src == SIZE_MAX);
    +
    154
    +
    155 // Try to convert to stack buffer first.
    +
    156 CHAR szStackBuffer[1024 / sizeof(CHAR)];
    +
    157#pragma warning(suppress: 6387) // Testing indicates src may be NULL when count_src is also 0. Is SAL of the lpWideCharStr parameter wrong?
    +
    158 int cch = WideCharToMultiByte(static_cast<UINT>(m_to_wincp), dwFlagsWCMB, reinterpret_cast<LPCWCH>(src), static_cast<int>(count_src), szStackBuffer, _countof(szStackBuffer), lpDefaultChar, NULL);
    +
    159 if (cch) {
    +
    160 // Copy from stack. Be careful not to include zero terminator.
    +
    161 dst.append(reinterpret_cast<const T_to*>(szStackBuffer), count_src != SIZE_MAX ? strnlen(szStackBuffer, cch) : static_cast<size_t>(cch) - 1);
    +
    162 return;
    +
    163 }
    +
    164 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
    +
    165 // Query the required output size. Allocate buffer. Then convert again.
    +
    166 cch = WideCharToMultiByte(static_cast<UINT>(m_to_wincp), dwFlagsWCMB, reinterpret_cast<LPCWCH>(src), static_cast<int>(count_src), NULL, 0, lpDefaultChar, NULL);
    +
    167 std::unique_ptr<CHAR[]> szBuffer(new CHAR[cch]);
    +
    168 cch = WideCharToMultiByte(static_cast<UINT>(m_to_wincp), dwFlagsWCMB, reinterpret_cast<LPCWCH>(src), static_cast<int>(count_src), szBuffer.get(), cch, lpDefaultChar, NULL);
    +
    169 dst.append(reinterpret_cast<const T_to*>(szBuffer.get()), count_src != SIZE_MAX ? strnlen(szBuffer.get(), cch) : static_cast<size_t>(cch) - 1);
    +
    170 return;
    +
    171 }
    +
    172 throw std::system_error(GetLastError(), std::system_category(), "WideCharToMultiByte failed");
    +
    173 }
    +
    174
    +
    175#pragma warning(suppress: 4127)
    +
    176 if _Constexpr_ (sizeof(T_from) == sizeof(char) && sizeof(T_to) == sizeof(char)) {
    +
    177 _Assume_(count_src < INT_MAX || count_src == SIZE_MAX);
    +
    178
    +
    179 // Try to convert to stack buffer first.
    +
    180 WCHAR szStackBufferMBWC[512 / sizeof(WCHAR)];
    +
    181#pragma warning(suppress: 6387) // Testing indicates src may be NULL when count_src is also 0. Is SAL of the lpMultiByteStr parameter wrong?
    +
    182 int cch = MultiByteToWideChar(static_cast<UINT>(m_from_wincp), dwFlagsMBWC, reinterpret_cast<LPCCH>(src), static_cast<int>(count_src), szStackBufferMBWC, _countof(szStackBufferMBWC));
    +
    183 if (cch) {
    +
    184 // Append from stack.
    +
    185 size_t count_inter = count_src != SIZE_MAX ? wcsnlen(szStackBufferMBWC, cch) : static_cast<size_t>(cch) - 1;
    +
    186 _Assume_(count_inter < INT_MAX);
    +
    187
    +
    188 // Try to convert to stack buffer first.
    +
    189 CHAR szStackBufferWCMB[512 / sizeof(CHAR)];
    +
    190#pragma warning(suppress: 6387) // Testing indicates szStackBufferMBWC may be NULL when count_inter is also 0. Is SAL of the lpWideCharStr parameter wrong?
    +
    191 cch = WideCharToMultiByte(static_cast<UINT>(m_to_wincp), dwFlagsWCMB, szStackBufferMBWC, static_cast<int>(count_inter), szStackBufferWCMB, _countof(szStackBufferWCMB), lpDefaultChar, NULL);
    +
    192 if (cch) {
    +
    193 // Copy from stack. Be careful not to include zero terminator.
    +
    194 dst.append(reinterpret_cast<const T_to*>(szStackBufferWCMB), strnlen(szStackBufferWCMB, cch));
    +
    195 return;
    +
    196 }
    +
    197 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
    +
    198 // Query the required output size. Allocate buffer. Then convert again.
    +
    199 cch = WideCharToMultiByte(static_cast<UINT>(m_to_wincp), dwFlagsWCMB, szStackBufferMBWC, static_cast<int>(count_inter), NULL, 0, lpDefaultChar, NULL);
    +
    200 std::unique_ptr<CHAR[]> szBufferWCMB(new CHAR[cch]);
    +
    201 cch = WideCharToMultiByte(static_cast<UINT>(m_to_wincp), dwFlagsWCMB, szStackBufferMBWC, static_cast<int>(count_inter), szBufferWCMB.get(), cch, lpDefaultChar, NULL);
    +
    202 dst.append(reinterpret_cast<const T_to*>(szBufferWCMB.get()), strnlen(szBufferWCMB.get(), cch));
    +
    203 return;
    +
    204 }
    +
    205 throw std::system_error(GetLastError(), std::system_category(), "WideCharToMultiByte failed");
    +
    206 }
    +
    207 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
    208 // Query the required output size. Allocate buffer. Then convert again.
    -
    209 cch = WideCharToMultiByte(static_cast<UINT>(m_to_wincp), dwFlagsWCMB, szBufferMBWC.get(), static_cast<int>(count_inter), NULL, 0, lpDefaultChar, NULL);
    -
    210 std::unique_ptr<CHAR[]> szBufferWCMB(new CHAR[cch]);
    -
    211 cch = WideCharToMultiByte(static_cast<UINT>(m_to_wincp), dwFlagsWCMB, szBufferMBWC.get(), static_cast<int>(count_inter), szBufferWCMB.get(), cch, lpDefaultChar, NULL);
    -
    212 dst.append(reinterpret_cast<const T_to*>(szBufferWCMB.get()), strnlen(szBufferWCMB.get(), cch));
    -
    213 return;
    -
    214 }
    -
    215 throw std::system_error(GetLastError(), std::system_category(), "MultiByteToWideChar failed");
    -
    216 }
    -
    217#else
    -
    218 dst.reserve(dst.size() + count_src);
    -
    219 T_to buf[1024 / sizeof(T_to)];
    -
    220 size_t src_size = stdex::mul(sizeof(T_from), count_src);
    -
    221 for (;;) {
    -
    222 T_to* output = &buf[0];
    -
    223 size_t output_size = sizeof(buf);
    -
    224 errno = 0;
    -
    225 iconv(m_handle, const_cast<char**>(reinterpret_cast<const char**>(&src)), &src_size, reinterpret_cast<char**>(&output), &output_size);
    -
    226 dst.append(buf, reinterpret_cast<T_to*>(reinterpret_cast<char*>(buf) + sizeof(buf) - output_size));
    -
    227 if (!errno)
    -
    228 break;
    -
    229 if (errno == E2BIG)
    -
    230 continue;
    -
    231 throw std::system_error(errno, std::system_category(), "iconv failed");
    -
    232 }
    -
    233#endif
    -
    234 }
    +
    209 cch = MultiByteToWideChar(static_cast<UINT>(m_from_wincp), dwFlagsMBWC, reinterpret_cast<LPCCH>(src), static_cast<int>(count_src), NULL, 0);
    +
    210 std::unique_ptr<WCHAR[]> szBufferMBWC(new WCHAR[cch]);
    +
    211 cch = MultiByteToWideChar(static_cast<UINT>(m_from_wincp), dwFlagsMBWC, reinterpret_cast<LPCCH>(src), static_cast<int>(count_src), szBufferMBWC.get(), cch);
    +
    212 size_t count_inter = count_src != SIZE_MAX ? wcsnlen(szBufferMBWC.get(), cch) : static_cast<size_t>(cch) - 1;
    +
    213
    +
    214 // Query the required output size. Allocate buffer. Then convert again.
    +
    215 cch = WideCharToMultiByte(static_cast<UINT>(m_to_wincp), dwFlagsWCMB, szBufferMBWC.get(), static_cast<int>(count_inter), NULL, 0, lpDefaultChar, NULL);
    +
    216 std::unique_ptr<CHAR[]> szBufferWCMB(new CHAR[cch]);
    +
    217 cch = WideCharToMultiByte(static_cast<UINT>(m_to_wincp), dwFlagsWCMB, szBufferMBWC.get(), static_cast<int>(count_inter), szBufferWCMB.get(), cch, lpDefaultChar, NULL);
    +
    218 dst.append(reinterpret_cast<const T_to*>(szBufferWCMB.get()), strnlen(szBufferWCMB.get(), cch));
    +
    219 return;
    +
    220 }
    +
    221 throw std::system_error(GetLastError(), std::system_category(), "MultiByteToWideChar failed");
    +
    222 }
    +
    223#else
    +
    224 dst.reserve(dst.size() + count_src);
    +
    225 T_to buf[1024 / sizeof(T_to)];
    +
    226 size_t src_size = stdex::mul(sizeof(T_from), count_src);
    +
    227 for (;;) {
    +
    228 T_to* output = &buf[0];
    +
    229 size_t output_size = sizeof(buf);
    +
    230 errno = 0;
    +
    231 iconv(m_handle, const_cast<char**>(reinterpret_cast<const char**>(&src)), &src_size, reinterpret_cast<char**>(&output), &output_size);
    +
    232 dst.append(buf, reinterpret_cast<T_to*>(reinterpret_cast<char*>(buf) + sizeof(buf) - output_size));
    +
    233 if (!errno)
    +
    234 break;
    +
    235 if (errno == E2BIG)
    +
    236 continue;
    +
    237 throw std::system_error(errno, std::system_category(), "iconv failed");
    +
    238 }
    +
    239#endif
    +
    240 }
    -
    235
    -
    242 template <class _Traits_to = std::char_traits<T_to>, class _Alloc_to = std::allocator<T_to>>
    -
    -
    243 inline void strcat(
    -
    244 _Inout_ std::basic_string<T_to, _Traits_to, _Alloc_to>& dst,
    -
    245 _In_z_ const T_from* src)
    -
    246 {
    -
    247 strcat(dst, src, SIZE_MAX);
    -
    248 }
    +
    241
    +
    248 template <class _Traits_to = std::char_traits<T_to>, class _Alloc_to = std::allocator<T_to>>
    +
    +
    249 inline void strcat(
    +
    250 _Inout_ std::basic_string<T_to, _Traits_to, _Alloc_to>& dst,
    +
    251 _In_z_ const T_from* src)
    +
    252 {
    +
    253 strcat(dst, src, SIZE_MAX);
    +
    254 }
    -
    249
    -
    256 template <class _Traits_to = std::char_traits<T_to>, class _Alloc_to = std::allocator<T_to>, class _Traits_from = std::char_traits<T_from>, class _Alloc_from = std::allocator<T_from>>
    -
    -
    257 inline void strcat(
    -
    258 _Inout_ std::basic_string<T_to, _Traits_to, _Alloc_to>& dst,
    -
    259 _In_ const std::basic_string<T_from, _Traits_from, _Alloc_from>& src)
    -
    260 {
    -
    261 strcat(dst, src.data(), src.size());
    -
    262 }
    +
    255
    +
    262 template <class _Traits_to = std::char_traits<T_to>, class _Alloc_to = std::allocator<T_to>, class _Traits_from = std::char_traits<T_from>, class _Alloc_from = std::allocator<T_from>>
    +
    +
    263 inline void strcat(
    +
    264 _Inout_ std::basic_string<T_to, _Traits_to, _Alloc_to>& dst,
    +
    265 _In_ const std::basic_string<T_from, _Traits_from, _Alloc_from>& src)
    +
    266 {
    +
    267 strcat(dst, src.data(), src.size());
    +
    268 }
    -
    263
    -
    271 template <class _Traits_to = std::char_traits<T_to>, class _Alloc_to = std::allocator<T_to>>
    -
    -
    272 inline void strcpy(
    -
    273 _Inout_ std::basic_string<T_to, _Traits_to, _Alloc_to>& dst,
    -
    274 _In_reads_or_z_opt_(count_src) const T_from* src, _In_ size_t count_src)
    -
    275 {
    -
    276 dst.clear();
    -
    277 strcat(dst, src, count_src);
    -
    278 }
    +
    269
    +
    277 template <class _Traits_to = std::char_traits<T_to>, class _Alloc_to = std::allocator<T_to>>
    +
    +
    278 inline void strcpy(
    +
    279 _Inout_ std::basic_string<T_to, _Traits_to, _Alloc_to>& dst,
    +
    280 _In_reads_or_z_opt_(count_src) const T_from* src, _In_ size_t count_src)
    +
    281 {
    +
    282 dst.clear();
    +
    283 strcat(dst, src, count_src);
    +
    284 }
    -
    279
    -
    286 template <class _Traits_to = std::char_traits<T_to>, class _Alloc_to = std::allocator<T_to>>
    -
    -
    287 inline void strcpy(
    -
    288 _Inout_ std::basic_string<T_to, _Traits_to, _Alloc_to>& dst,
    -
    289 _In_z_ const T_from* src)
    -
    290 {
    -
    291 strcpy(dst, src, SIZE_MAX);
    -
    292 }
    +
    285
    +
    292 template <class _Traits_to = std::char_traits<T_to>, class _Alloc_to = std::allocator<T_to>>
    +
    +
    293 inline void strcpy(
    +
    294 _Inout_ std::basic_string<T_to, _Traits_to, _Alloc_to>& dst,
    +
    295 _In_z_ const T_from* src)
    +
    296 {
    +
    297 strcpy(dst, src, SIZE_MAX);
    +
    298 }
    -
    293
    -
    300 template <class _Traits_to = std::char_traits<T_to>, class _Alloc_to = std::allocator<T_to>, class _Traits_from = std::char_traits<T_from>, class _Alloc_from = std::allocator<T_from>>
    -
    -
    301 inline void strcpy(
    -
    302 _Inout_ std::basic_string<T_to, _Traits_to, _Alloc_to>& dst,
    -
    303 _In_ const std::basic_string<T_from, _Traits_from, _Alloc_from>& src)
    -
    304 {
    -
    305 strcpy(dst, src.data(), src.size());
    -
    306 }
    +
    299
    +
    306 template <class _Traits_to = std::char_traits<T_to>, class _Alloc_to = std::allocator<T_to>, class _Traits_from = std::char_traits<T_from>, class _Alloc_from = std::allocator<T_from>>
    +
    +
    307 inline void strcpy(
    +
    308 _Inout_ std::basic_string<T_to, _Traits_to, _Alloc_to>& dst,
    +
    309 _In_ const std::basic_string<T_from, _Traits_from, _Alloc_from>& src)
    +
    310 {
    +
    311 strcpy(dst, src.data(), src.size());
    +
    312 }
    -
    307
    -
    314 template <class _Traits_to = std::char_traits<T_to>, class _Alloc_to = std::allocator<T_to>>
    -
    -
    315 inline std::basic_string<T_to, _Traits_to, _Alloc_to> convert(_In_reads_or_z_opt_(count_src) const T_from* src, _In_ size_t count_src)
    -
    316 {
    -
    317 std::basic_string<T_to, _Traits_to, _Alloc_to> dst;
    -
    318 strcat(dst, src, count_src);
    -
    319 return dst;
    -
    320 }
    +
    313
    +
    320 template <class _Traits_to = std::char_traits<T_to>, class _Alloc_to = std::allocator<T_to>>
    +
    +
    321 inline std::basic_string<T_to, _Traits_to, _Alloc_to> convert(_In_reads_or_z_opt_(count_src) const T_from* src, _In_ size_t count_src)
    +
    322 {
    +
    323 std::basic_string<T_to, _Traits_to, _Alloc_to> dst;
    +
    324 strcat(dst, src, count_src);
    +
    325 return dst;
    +
    326 }
    -
    321
    -
    327 template <class _Traits_to = std::char_traits<T_to>, class _Alloc_to = std::allocator<T_to>>
    -
    -
    328 inline std::basic_string<T_to, _Traits_to, _Alloc_to> convert(_In_z_ const T_from* src)
    -
    329 {
    -
    330 return convert(src, SIZE_MAX);
    -
    331 }
    +
    327
    +
    333 template <class _Traits_to = std::char_traits<T_to>, class _Alloc_to = std::allocator<T_to>>
    +
    +
    334 inline std::basic_string<T_to, _Traits_to, _Alloc_to> convert(_In_z_ const T_from* src)
    +
    335 {
    +
    336 return convert(src, SIZE_MAX);
    +
    337 }
    -
    332
    -
    338 template <class _Traits_to = std::char_traits<T_to>, class _Alloc_to = std::allocator<T_to>, class _Traits_from = std::char_traits<T_from>, class _Alloc_from = std::allocator<T_from>>
    -
    -
    339 inline std::basic_string<T_to, _Traits_to, _Alloc_to> convert(_In_ const std::basic_string<T_from, _Traits_from, _Alloc_from>& src)
    -
    340 {
    -
    341 return convert(src.data(), src.size());
    -
    342 }
    +
    338
    +
    344 template <class _Traits_to = std::char_traits<T_to>, class _Alloc_to = std::allocator<T_to>, class _Traits_from = std::char_traits<T_from>, class _Alloc_from = std::allocator<T_from>>
    +
    +
    345 inline std::basic_string<T_to, _Traits_to, _Alloc_to> convert(_In_ const std::basic_string<T_from, _Traits_from, _Alloc_from>& src)
    +
    346 {
    +
    347 return convert(src.data(), src.size());
    +
    348 }
    -
    343
    -
    344 inline void clear()
    -
    345 {
    -
    346#ifndef _WIN32
    -
    347 iconv(m_handle, NULL, NULL, NULL, NULL);
    -
    348#endif
    -
    349 }
    -
    350
    -
    351 static charset_id system_charset()
    -
    352 {
    -
    353#ifdef _WIN32
    -
    354 return static_cast<charset_id>(GetACP());
    -
    355#else
    -
    356 static const std::map<const char*, charset_id> charsets = {
    -
    357 { "UNICODE-1-1-UTF-7", charset_id::utf7 },
    -
    358 { "UTF-7", charset_id::utf7 },
    -
    359 { "CSUNICODE11UTF7", charset_id::utf7 },
    -
    360
    -
    361 { "UTF-8", charset_id::utf8 },
    -
    362 { "UTF8", charset_id::utf8 },
    -
    363
    -
    364 { "UTF-16", charset_id::utf16 },
    -
    365#if BYTE_ORDER == BIG_ENDIAN
    -
    366 { "UTF-16BE", charset_id::utf16 },
    -
    367#else
    -
    368 { "UTF-16LE", charset_id::utf16 },
    -
    369#endif
    -
    370
    -
    371 { "UTF-32", charset_id::utf32 },
    -
    372#if BYTE_ORDER == BIG_ENDIAN
    -
    373 { "UTF-32BE", charset_id::utf32 },
    -
    374#else
    -
    375 { "UTF-32LE", charset_id::utf32 },
    -
    376#endif
    -
    377
    -
    378 { "CP1250", charset_id::windows1250 },
    -
    379 { "MS-EE", charset_id::windows1250 },
    -
    380 { "WINDOWS-1250", charset_id::windows1250 },
    -
    381
    -
    382 { "CP1251", charset_id::windows1251 },
    -
    383 { "MS-CYRL", charset_id::windows1251 },
    -
    384 { "WINDOWS-1251", charset_id::windows1251 },
    -
    385
    -
    386 { "CP1252", charset_id::windows1252 },
    -
    387 { "MS-ANSI", charset_id::windows1252 },
    -
    388 { "WINDOWS-1252", charset_id::windows1252 },
    -
    389 };
    -
    390 const char* lctype = nl_langinfo(CODESET);
    -
    391 if (auto el = charsets.find(lctype); el != charsets.end())
    -
    392 return el->second;
    -
    393 return charset_id::system;
    -
    394#endif
    -
    395 }
    -
    396
    -
    397#ifdef _WIN32
    -
    398 protected:
    -
    399 static UINT to_encoding(_In_ charset_id charset)
    -
    400 {
    -
    401 return
    -
    402 charset == charset_id::system ? GetACP() :
    -
    403 charset == charset_id::oem ? GetOEMCP() :
    -
    404 static_cast<UINT>(charset);
    -
    405 }
    -
    406
    -
    407 protected:
    -
    408 UINT m_from_wincp, m_to_wincp;
    -
    409#else
    -
    410 protected:
    -
    411 static const char* to_encoding(_In_ charset_id charset)
    -
    412 {
    -
    413 static const char* const encodings[static_cast<std::underlying_type_t<charset_id>>(charset_id::_max)] = {
    -
    414 "", // system
    -
    415 "UTF-7", // utf7
    -
    416 "UTF-8", // utf8
    -
    417#if BYTE_ORDER == BIG_ENDIAN
    -
    418 "UTF-16BE", // utf16
    -
    419 "UTF-32BE", // utf32
    -
    420#else
    -
    421 "UTF-16LE", // utf16
    -
    422 "UTF-32LE", // utf32
    -
    423#endif
    -
    424 "CP1250", // windows1250
    -
    425 "CP1251", // windows1251
    -
    426 "CP1252", // windows1252
    -
    427 };
    -
    428 return
    -
    429 charset == charset_id::system ? nl_langinfo(CODESET) :
    -
    430 encodings[static_cast<std::underlying_type_t<charset_id>>(charset)];
    -
    431 }
    -
    432
    -
    433 protected:
    -
    434 iconv_t m_handle;
    -
    435#endif
    -
    436 };
    +
    349
    +
    350 inline void clear()
    +
    351 {
    +
    352#ifndef _WIN32
    +
    353 iconv(m_handle, NULL, NULL, NULL, NULL);
    +
    354#endif
    +
    355 }
    +
    356
    +
    357 static charset_id system_charset()
    +
    358 {
    +
    359#ifdef _WIN32
    +
    360 return static_cast<charset_id>(GetACP());
    +
    361#else
    +
    362 static const std::map<const char*, charset_id> charsets = {
    +
    363 { "UNICODE-1-1-UTF-7", charset_id::utf7 },
    +
    364 { "UTF-7", charset_id::utf7 },
    +
    365 { "CSUNICODE11UTF7", charset_id::utf7 },
    +
    366
    +
    367 { "UTF-8", charset_id::utf8 },
    +
    368 { "UTF8", charset_id::utf8 },
    +
    369
    +
    370 { "UTF-16", charset_id::utf16 },
    +
    371#if BYTE_ORDER == BIG_ENDIAN
    +
    372 { "UTF-16BE", charset_id::utf16 },
    +
    373#else
    +
    374 { "UTF-16LE", charset_id::utf16 },
    +
    375#endif
    +
    376
    +
    377 { "UTF-32", charset_id::utf32 },
    +
    378#if BYTE_ORDER == BIG_ENDIAN
    +
    379 { "UTF-32BE", charset_id::utf32 },
    +
    380#else
    +
    381 { "UTF-32LE", charset_id::utf32 },
    +
    382#endif
    +
    383
    +
    384 { "CP1250", charset_id::windows1250 },
    +
    385 { "MS-EE", charset_id::windows1250 },
    +
    386 { "WINDOWS-1250", charset_id::windows1250 },
    +
    387
    +
    388 { "CP1251", charset_id::windows1251 },
    +
    389 { "MS-CYRL", charset_id::windows1251 },
    +
    390 { "WINDOWS-1251", charset_id::windows1251 },
    +
    391
    +
    392 { "CP1252", charset_id::windows1252 },
    +
    393 { "MS-ANSI", charset_id::windows1252 },
    +
    394 { "WINDOWS-1252", charset_id::windows1252 },
    +
    395 };
    +
    396 const char* lctype = nl_langinfo(CODESET);
    +
    397 if (auto el = charsets.find(lctype); el != charsets.end())
    +
    398 return el->second;
    +
    399 return charset_id::system;
    +
    400#endif
    +
    401 }
    +
    402
    +
    403#ifdef _WIN32
    +
    404 protected:
    +
    405 static UINT to_encoding(_In_ charset_id charset)
    +
    406 {
    +
    407 return
    +
    408 charset == charset_id::system ? GetACP() :
    +
    409 charset == charset_id::oem ? GetOEMCP() :
    +
    410 static_cast<UINT>(charset);
    +
    411 }
    +
    412
    +
    413 protected:
    +
    414 UINT m_from_wincp, m_to_wincp;
    +
    415#else
    +
    416 protected:
    +
    417 static const char* to_encoding(_In_ charset_id charset)
    +
    418 {
    +
    419 static const char* const encodings[static_cast<std::underlying_type_t<charset_id>>(charset_id::_max)] = {
    +
    420 "", // system
    +
    421 "UTF-7", // utf7
    +
    422 "UTF-8", // utf8
    +
    423#if BYTE_ORDER == BIG_ENDIAN
    +
    424 "UTF-16BE", // utf16
    +
    425 "UTF-32BE", // utf32
    +
    426#else
    +
    427 "UTF-16LE", // utf16
    +
    428 "UTF-32LE", // utf32
    +
    429#endif
    +
    430 "CP1250", // windows1250
    +
    431 "CP1251", // windows1251
    +
    432 "CP1252", // windows1252
    +
    433 };
    +
    434 return
    +
    435 charset == charset_id::system ? nl_langinfo(CODESET) :
    +
    436 encodings[static_cast<std::underlying_type_t<charset_id>>(charset)];
    +
    437 }
    +
    438
    +
    439 protected:
    +
    440 iconv_t m_handle;
    +
    441#endif
    +
    442 };
    -
    437
    -
    448#ifndef _WIN32
    -
    449 _Deprecated_("For better performance, consider a reusable charset_encoder")
    -
    450#endif
    -
    451 inline void strcat(
    -
    452 _Inout_ std::wstring& dst,
    -
    453 _In_reads_or_z_opt_(count_src) const char* src, _In_ size_t count_src,
    -
    454 _In_ charset_id charset = charset_id::system)
    -
    455 {
    -
    456 charset_encoder<char, wchar_t>(charset, wchar_t_charset).strcat(dst, src, count_src);
    -
    457 }
    -
    458
    -
    459 _Deprecated_("Use stdex::strcat")
    -
    460 inline void str2wstr(
    -
    461 _Inout_ std::wstring& dst,
    -
    462 _In_reads_or_z_opt_(count_src) const char* src, _In_ size_t count_src,
    -
    463 _In_ charset_id charset = charset_id::system)
    -
    464 {
    -
    465 strcat(dst, src, count_src, charset);
    -
    466 }
    -
    467
    -
    477#ifndef _WIN32
    -
    478 _Deprecated_("For better performance, consider a reusable charset_encoder")
    -
    479#endif
    -
    480 inline void strcat(
    -
    481 _Inout_ std::wstring& dst,
    -
    482 _In_ const std::string& src,
    -
    483 _In_ charset_id charset = charset_id::system)
    -
    484 {
    -
    485 strcat(dst, src.data(), src.size(), charset);
    -
    486 }
    -
    487
    -
    488 _Deprecated_("Use stdex::strcat")
    -
    489 inline void str2wstr(
    -
    490 _Inout_ std::wstring& dst,
    -
    491 _In_ const std::string& src,
    -
    492 _In_ charset_id charset = charset_id::system)
    -
    493 {
    -
    494 strcat(dst, src, charset);
    -
    495 }
    -
    496
    -
    507#ifndef _WIN32
    -
    508 _Deprecated_("For better performance, consider a reusable charset_encoder")
    -
    509#endif
    -
    510 inline void strcpy(
    -
    511 _Inout_ std::wstring& dst,
    -
    512 _In_reads_or_z_opt_(count_src) const char* src, _In_ size_t count_src,
    -
    513 _In_ charset_id charset = charset_id::system)
    -
    514 {
    -
    515 dst.clear();
    -
    516 strcat(dst, src, count_src, charset);
    -
    517 }
    -
    518
    -
    528#ifndef _WIN32
    -
    529 _Deprecated_("For better performance, consider a reusable charset_encoder")
    -
    530#endif
    -
    531 inline void strcpy(
    -
    532 _Inout_ std::wstring& dst,
    -
    533 _In_ const std::string& src,
    -
    534 _In_ charset_id charset = charset_id::system)
    -
    535 {
    -
    536 strcpy(dst, src.data(), src.size(), charset);
    -
    537 }
    -
    538
    -
    549#ifndef _WIN32
    -
    550 _Deprecated_("For better performance, consider a reusable charset_encoder")
    -
    551#endif
    -
    552 inline std::wstring str2wstr(
    -
    553 _In_z_ const char* src,
    -
    554 _In_ charset_id charset = charset_id::system)
    -
    555 {
    -
    556 std::wstring dst;
    -
    557 strcat(dst, src, SIZE_MAX, charset);
    -
    558 return dst;
    -
    559 }
    -
    560
    -
    572#ifndef _WIN32
    -
    573 _Deprecated_("For better performance, consider a reusable charset_encoder")
    -
    574#endif
    -
    575 inline std::wstring str2wstr(
    -
    576 _In_reads_or_z_opt_(count_src) const char* src, _In_ size_t count_src,
    -
    577 _In_ charset_id charset = charset_id::system)
    -
    578 {
    -
    579 std::wstring dst;
    -
    580 strcat(dst, src, count_src, charset);
    -
    581 return dst;
    -
    582 }
    -
    583
    -
    594#ifndef _WIN32
    -
    595 _Deprecated_("For better performance, consider a reusable charset_encoder")
    -
    596#endif
    -
    597 inline std::wstring str2wstr(
    -
    598 _In_ const std::string& src,
    -
    599 _In_ charset_id charset = charset_id::system)
    -
    600 {
    -
    601 return str2wstr(src.c_str(), src.size(), charset);
    -
    602 }
    -
    603
    -
    614#ifndef _WIN32
    -
    615 _Deprecated_("For better performance, consider a reusable charset_encoder")
    -
    616#endif
    -
    617 inline void strcat(
    -
    618 _Inout_ std::string& dst,
    -
    619 _In_reads_or_z_opt_(count_src) const wchar_t* src, _In_ size_t count_src,
    -
    620 _In_ charset_id charset = charset_id::system)
    -
    621 {
    -
    622 charset_encoder<wchar_t, char>(wchar_t_charset, charset).strcat(dst, src, count_src);
    -
    623 }
    -
    624
    -
    625 _Deprecated_("Use stdex::strcat")
    -
    626 inline void wstr2str(
    -
    627 _Inout_ std::string& dst,
    -
    628 _In_reads_or_z_opt_(count_src) const wchar_t* src, _In_ size_t count_src,
    -
    629 _In_ charset_id charset = charset_id::system)
    -
    630 {
    -
    631 strcat(dst, src, count_src, charset);
    -
    632 }
    -
    633
    -
    643#ifndef _WIN32
    -
    644 _Deprecated_("For better performance, consider a reusable charset_encoder")
    -
    645#endif
    -
    646 inline void strcat(
    -
    647 _Inout_ std::string& dst,
    -
    648 _In_ const std::wstring& src,
    -
    649 _In_ charset_id charset = charset_id::system)
    -
    650 {
    -
    651 strcat(dst, src.c_str(), src.size(), charset);
    -
    652 }
    -
    653
    -
    654 _Deprecated_("Use stdex::strcat")
    -
    655 inline void wstr2str(
    -
    656 _Inout_ std::string& dst,
    -
    657 _In_ const std::wstring& src,
    -
    658 _In_ charset_id charset = charset_id::system)
    -
    659 {
    -
    660 strcat(dst, src, charset);
    -
    661 }
    -
    662
    -
    673#ifndef _WIN32
    -
    674 _Deprecated_("For better performance, consider a reusable charset_encoder")
    -
    675#endif
    -
    676 inline void strcpy(
    -
    677 _Inout_ std::string& dst,
    -
    678 _In_reads_or_z_opt_(count_src) const wchar_t* src, _In_ size_t count_src,
    -
    679 _In_ charset_id charset = charset_id::system)
    -
    680 {
    -
    681 dst.clear();
    -
    682 strcat(dst, src, count_src, charset);
    -
    683 }
    -
    684
    -
    694#ifndef _WIN32
    -
    695 _Deprecated_("For better performance, consider a reusable charset_encoder")
    -
    696#endif
    -
    697 inline void strcpy(
    -
    698 _Inout_ std::string& dst,
    -
    699 _In_ const std::wstring& src,
    -
    700 _In_ charset_id charset = charset_id::system)
    -
    701 {
    -
    702 strcpy(dst, src.data(), src.size(), charset);
    -
    703 }
    -
    704
    -
    715#ifndef _WIN32
    -
    716 _Deprecated_("For better performance, consider a reusable charset_encoder")
    -
    717#endif
    -
    718 inline std::string wstr2str(
    -
    719 _In_z_ const wchar_t* src,
    -
    720 _In_ charset_id charset = charset_id::system)
    -
    721 {
    -
    722 std::string dst;
    -
    723 strcat(dst, src, SIZE_MAX, charset);
    -
    724 return dst;
    -
    725 }
    -
    726
    -
    738#ifndef _WIN32
    -
    739 _Deprecated_("For better performance, consider a reusable charset_encoder")
    -
    740#endif
    -
    741 inline std::string wstr2str(
    -
    742 _In_reads_or_z_opt_(count_src) const wchar_t* src, _In_ size_t count_src,
    -
    743 _In_ charset_id charset = charset_id::system)
    -
    744 {
    -
    745 std::string dst;
    -
    746 strcat(dst, src, count_src, charset);
    -
    747 return dst;
    -
    748 }
    -
    749
    -
    760#ifndef _WIN32
    -
    761 _Deprecated_("For better performance, consider a reusable charset_encoder")
    -
    762#endif
    -
    763 inline std::string wstr2str(
    -
    764 _In_ const std::wstring& src,
    -
    765 _In_ charset_id charset = charset_id::system)
    -
    766 {
    -
    767 return wstr2str(src.c_str(), src.size(), charset);
    -
    768 }
    -
    769}
    -
    Encoding converter context.
    Definition unicode.hpp:64
    -
    void strcpy(std::basic_string< T_to, _Traits_to, _Alloc_to > &dst, const std::basic_string< T_from, _Traits_from, _Alloc_from > &src)
    Convert string.
    Definition unicode.hpp:301
    -
    std::basic_string< T_to, _Traits_to, _Alloc_to > convert(const std::basic_string< T_from, _Traits_from, _Alloc_from > &src)
    Return converted string.
    Definition unicode.hpp:339
    -
    std::basic_string< T_to, _Traits_to, _Alloc_to > convert(const T_from *src)
    Return converted string.
    Definition unicode.hpp:328
    -
    void strcat(std::basic_string< T_to, _Traits_to, _Alloc_to > &dst, const std::basic_string< T_from, _Traits_from, _Alloc_from > &src)
    Convert string and append to string.
    Definition unicode.hpp:257
    -
    void strcpy(std::basic_string< T_to, _Traits_to, _Alloc_to > &dst, const T_from *src)
    Convert string.
    Definition unicode.hpp:287
    -
    void strcat(std::basic_string< T_to, _Traits_to, _Alloc_to > &dst, _In_reads_or_z_opt_(count_src) const T_from *src, size_t count_src)
    Convert string and append to string.
    Definition unicode.hpp:101
    -
    void strcat(std::basic_string< T_to, _Traits_to, _Alloc_to > &dst, const T_from *src)
    Convert string and append to string.
    Definition unicode.hpp:243
    -
    void strcpy(std::basic_string< T_to, _Traits_to, _Alloc_to > &dst, _In_reads_or_z_opt_(count_src) const T_from *src, size_t count_src)
    Convert string.
    Definition unicode.hpp:272
    -
    std::basic_string< T_to, _Traits_to, _Alloc_to > convert(_In_reads_or_z_opt_(count_src) const T_from *src, size_t count_src)
    Return converted string.
    Definition unicode.hpp:315
    +
    443
    +
    454#ifndef _WIN32
    +
    455 _Deprecated_("For better performance, consider a reusable charset_encoder")
    +
    456#endif
    +
    457 inline void strcat(
    +
    458 _Inout_ std::wstring& dst,
    +
    459 _In_reads_or_z_opt_(count_src) const char* src, _In_ size_t count_src,
    +
    460 _In_ charset_id charset = charset_id::system)
    +
    461 {
    +
    462 charset_encoder<char, wchar_t>(charset, wchar_t_charset).strcat(dst, src, count_src);
    +
    463 }
    +
    464
    +
    465 _Deprecated_("Use stdex::strcat")
    +
    466 inline void str2wstr(
    +
    467 _Inout_ std::wstring& dst,
    +
    468 _In_reads_or_z_opt_(count_src) const char* src, _In_ size_t count_src,
    +
    469 _In_ charset_id charset = charset_id::system)
    +
    470 {
    +
    471 strcat(dst, src, count_src, charset);
    +
    472 }
    +
    473
    +
    483#ifndef _WIN32
    +
    484 _Deprecated_("For better performance, consider a reusable charset_encoder")
    +
    485#endif
    +
    486 inline void strcat(
    +
    487 _Inout_ std::wstring& dst,
    +
    488 _In_ const std::string& src,
    +
    489 _In_ charset_id charset = charset_id::system)
    +
    490 {
    +
    491 strcat(dst, src.data(), src.size(), charset);
    +
    492 }
    +
    493
    +
    494 _Deprecated_("Use stdex::strcat")
    +
    495 inline void str2wstr(
    +
    496 _Inout_ std::wstring& dst,
    +
    497 _In_ const std::string& src,
    +
    498 _In_ charset_id charset = charset_id::system)
    +
    499 {
    +
    500 strcat(dst, src, charset);
    +
    501 }
    +
    502
    +
    513#ifndef _WIN32
    +
    514 _Deprecated_("For better performance, consider a reusable charset_encoder")
    +
    515#endif
    +
    516 inline void strcpy(
    +
    517 _Inout_ std::wstring& dst,
    +
    518 _In_reads_or_z_opt_(count_src) const char* src, _In_ size_t count_src,
    +
    519 _In_ charset_id charset = charset_id::system)
    +
    520 {
    +
    521 dst.clear();
    +
    522 strcat(dst, src, count_src, charset);
    +
    523 }
    +
    524
    +
    534#ifndef _WIN32
    +
    535 _Deprecated_("For better performance, consider a reusable charset_encoder")
    +
    536#endif
    +
    537 inline void strcpy(
    +
    538 _Inout_ std::wstring& dst,
    +
    539 _In_ const std::string& src,
    +
    540 _In_ charset_id charset = charset_id::system)
    +
    541 {
    +
    542 strcpy(dst, src.data(), src.size(), charset);
    +
    543 }
    +
    544
    +
    555#ifndef _WIN32
    +
    556 _Deprecated_("For better performance, consider a reusable charset_encoder")
    +
    557#endif
    +
    558 inline std::wstring str2wstr(
    +
    559 _In_z_ const char* src,
    +
    560 _In_ charset_id charset = charset_id::system)
    +
    561 {
    +
    562 std::wstring dst;
    +
    563 strcat(dst, src, SIZE_MAX, charset);
    +
    564 return dst;
    +
    565 }
    +
    566
    +
    578#ifndef _WIN32
    +
    579 _Deprecated_("For better performance, consider a reusable charset_encoder")
    +
    580#endif
    +
    581 inline std::wstring str2wstr(
    +
    582 _In_reads_or_z_opt_(count_src) const char* src, _In_ size_t count_src,
    +
    583 _In_ charset_id charset = charset_id::system)
    +
    584 {
    +
    585 std::wstring dst;
    +
    586 strcat(dst, src, count_src, charset);
    +
    587 return dst;
    +
    588 }
    +
    589
    +
    600#ifndef _WIN32
    +
    601 _Deprecated_("For better performance, consider a reusable charset_encoder")
    +
    602#endif
    +
    603 inline std::wstring str2wstr(
    +
    604 _In_ const std::string& src,
    +
    605 _In_ charset_id charset = charset_id::system)
    +
    606 {
    +
    607 return str2wstr(src.c_str(), src.size(), charset);
    +
    608 }
    +
    609
    +
    620#ifndef _WIN32
    +
    621 _Deprecated_("For better performance, consider a reusable charset_encoder")
    +
    622#endif
    +
    623 inline void strcat(
    +
    624 _Inout_ std::string& dst,
    +
    625 _In_reads_or_z_opt_(count_src) const wchar_t* src, _In_ size_t count_src,
    +
    626 _In_ charset_id charset = charset_id::system)
    +
    627 {
    +
    628 charset_encoder<wchar_t, char>(wchar_t_charset, charset).strcat(dst, src, count_src);
    +
    629 }
    +
    630
    +
    631 _Deprecated_("Use stdex::strcat")
    +
    632 inline void wstr2str(
    +
    633 _Inout_ std::string& dst,
    +
    634 _In_reads_or_z_opt_(count_src) const wchar_t* src, _In_ size_t count_src,
    +
    635 _In_ charset_id charset = charset_id::system)
    +
    636 {
    +
    637 strcat(dst, src, count_src, charset);
    +
    638 }
    +
    639
    +
    649#ifndef _WIN32
    +
    650 _Deprecated_("For better performance, consider a reusable charset_encoder")
    +
    651#endif
    +
    652 inline void strcat(
    +
    653 _Inout_ std::string& dst,
    +
    654 _In_ const std::wstring& src,
    +
    655 _In_ charset_id charset = charset_id::system)
    +
    656 {
    +
    657 strcat(dst, src.c_str(), src.size(), charset);
    +
    658 }
    +
    659
    +
    660 _Deprecated_("Use stdex::strcat")
    +
    661 inline void wstr2str(
    +
    662 _Inout_ std::string& dst,
    +
    663 _In_ const std::wstring& src,
    +
    664 _In_ charset_id charset = charset_id::system)
    +
    665 {
    +
    666 strcat(dst, src, charset);
    +
    667 }
    +
    668
    +
    679#ifndef _WIN32
    +
    680 _Deprecated_("For better performance, consider a reusable charset_encoder")
    +
    681#endif
    +
    682 inline void strcpy(
    +
    683 _Inout_ std::string& dst,
    +
    684 _In_reads_or_z_opt_(count_src) const wchar_t* src, _In_ size_t count_src,
    +
    685 _In_ charset_id charset = charset_id::system)
    +
    686 {
    +
    687 dst.clear();
    +
    688 strcat(dst, src, count_src, charset);
    +
    689 }
    +
    690
    +
    700#ifndef _WIN32
    +
    701 _Deprecated_("For better performance, consider a reusable charset_encoder")
    +
    702#endif
    +
    703 inline void strcpy(
    +
    704 _Inout_ std::string& dst,
    +
    705 _In_ const std::wstring& src,
    +
    706 _In_ charset_id charset = charset_id::system)
    +
    707 {
    +
    708 strcpy(dst, src.data(), src.size(), charset);
    +
    709 }
    +
    710
    +
    721#ifndef _WIN32
    +
    722 _Deprecated_("For better performance, consider a reusable charset_encoder")
    +
    723#endif
    +
    724 inline std::string wstr2str(
    +
    725 _In_z_ const wchar_t* src,
    +
    726 _In_ charset_id charset = charset_id::system)
    +
    727 {
    +
    728 std::string dst;
    +
    729 strcat(dst, src, SIZE_MAX, charset);
    +
    730 return dst;
    +
    731 }
    +
    732
    +
    744#ifndef _WIN32
    +
    745 _Deprecated_("For better performance, consider a reusable charset_encoder")
    +
    746#endif
    +
    747 inline std::string wstr2str(
    +
    748 _In_reads_or_z_opt_(count_src) const wchar_t* src, _In_ size_t count_src,
    +
    749 _In_ charset_id charset = charset_id::system)
    +
    750 {
    +
    751 std::string dst;
    +
    752 strcat(dst, src, count_src, charset);
    +
    753 return dst;
    +
    754 }
    +
    755
    +
    766#ifndef _WIN32
    +
    767 _Deprecated_("For better performance, consider a reusable charset_encoder")
    +
    768#endif
    +
    769 inline std::string wstr2str(
    +
    770 _In_ const std::wstring& src,
    +
    771 _In_ charset_id charset = charset_id::system)
    +
    772 {
    +
    773 return wstr2str(src.c_str(), src.size(), charset);
    +
    774 }
    +
    775}
    +
    776
    +
    777#ifndef _WIN32
    +
    778#pragma GCC diagnostic pop
    +
    779#endif
    +
    Encoding converter context.
    Definition unicode.hpp:70
    +
    void strcpy(std::basic_string< T_to, _Traits_to, _Alloc_to > &dst, const std::basic_string< T_from, _Traits_from, _Alloc_from > &src)
    Convert string.
    Definition unicode.hpp:307
    +
    std::basic_string< T_to, _Traits_to, _Alloc_to > convert(const std::basic_string< T_from, _Traits_from, _Alloc_from > &src)
    Return converted string.
    Definition unicode.hpp:345
    +
    std::basic_string< T_to, _Traits_to, _Alloc_to > convert(const T_from *src)
    Return converted string.
    Definition unicode.hpp:334
    +
    void strcat(std::basic_string< T_to, _Traits_to, _Alloc_to > &dst, const std::basic_string< T_from, _Traits_from, _Alloc_from > &src)
    Convert string and append to string.
    Definition unicode.hpp:263
    +
    void strcpy(std::basic_string< T_to, _Traits_to, _Alloc_to > &dst, const T_from *src)
    Convert string.
    Definition unicode.hpp:293
    +
    void strcat(std::basic_string< T_to, _Traits_to, _Alloc_to > &dst, _In_reads_or_z_opt_(count_src) const T_from *src, size_t count_src)
    Convert string and append to string.
    Definition unicode.hpp:107
    +
    void strcat(std::basic_string< T_to, _Traits_to, _Alloc_to > &dst, const T_from *src)
    Convert string and append to string.
    Definition unicode.hpp:249
    +
    void strcpy(std::basic_string< T_to, _Traits_to, _Alloc_to > &dst, _In_reads_or_z_opt_(count_src) const T_from *src, size_t count_src)
    Convert string.
    Definition unicode.hpp:278
    +
    std::basic_string< T_to, _Traits_to, _Alloc_to > convert(_In_reads_or_z_opt_(count_src) const T_from *src, size_t count_src)
    Return converted string.
    Definition unicode.hpp:321
    diff --git a/unionstdex_1_1md2__t-members.html b/unionstdex_1_1md2__t-members.html index 53db6e32c..8b60415fb 100644 --- a/unionstdex_1_1md2__t-members.html +++ b/unionstdex_1_1md2__t-members.html @@ -89,7 +89,7 @@ $(function() {
    diff --git a/unionstdex_1_1md2__t.html b/unionstdex_1_1md2__t.html index ded8be1a1..2883f5cd5 100644 --- a/unionstdex_1_1md2__t.html +++ b/unionstdex_1_1md2__t.html @@ -123,7 +123,7 @@ Friends
    diff --git a/unionstdex_1_1sha256__t-members.html b/unionstdex_1_1sha256__t-members.html index d089cc1cd..30e89ac3c 100644 --- a/unionstdex_1_1sha256__t-members.html +++ b/unionstdex_1_1sha256__t-members.html @@ -89,7 +89,7 @@ $(function() {
    diff --git a/unionstdex_1_1sha256__t.html b/unionstdex_1_1sha256__t.html index 5032cd6e5..ea49917f9 100644 --- a/unionstdex_1_1sha256__t.html +++ b/unionstdex_1_1sha256__t.html @@ -123,7 +123,7 @@ Friends
    diff --git a/unionstdex_1_1sha__t-members.html b/unionstdex_1_1sha__t-members.html index 8b3aaf6e6..5d9c3467b 100644 --- a/unionstdex_1_1sha__t-members.html +++ b/unionstdex_1_1sha__t-members.html @@ -89,7 +89,7 @@ $(function() {
    diff --git a/unionstdex_1_1sha__t.html b/unionstdex_1_1sha__t.html index b0472ef6f..463c6a2ca 100644 --- a/unionstdex_1_1sha__t.html +++ b/unionstdex_1_1sha__t.html @@ -123,7 +123,7 @@ Friends
    diff --git a/uuid_8hpp_source.html b/uuid_8hpp_source.html new file mode 100644 index 000000000..4ff0586f0 --- /dev/null +++ b/uuid_8hpp_source.html @@ -0,0 +1,151 @@ + + + + + + + +stdex: include/stdex/uuid.hpp Source File + + + + + + + + + +
    +
    + + + + + + +
    +
    stdex +
    +
    Additional custom or not Standard C++ covered algorithms
    +
    +
    + + + + + + + + + +
    +
    + + +
    +
    +
    +
    +
    +
    Loading...
    +
    Searching...
    +
    No Matches
    +
    +
    +
    +
    + + +
    +
    +
    uuid.hpp
    +
    +
    +
    1/*
    +
    2 SPDX-License-Identifier: MIT
    +
    3 Copyright © 2016-2023 Amebis
    +
    4*/
    +
    5
    +
    6#pragma once
    +
    7
    +
    8#include "compat.hpp"
    +
    9#include <stdint.h>
    +
    10#include <stdio.h>
    +
    11#if defined(_WIN32)
    +
    12#include "windows.h"
    +
    13#include <rpc.h>
    +
    14#else
    +
    15#include <uuid/uuid.h>
    +
    16#include <wchar.h>
    +
    17#endif
    +
    18
    +
    19namespace stdex
    +
    20{
    +
    27 inline void uuidtostr(_Out_writes_z_(39) char str[39], _In_ const uuid_t& id)
    +
    28 {
    +
    29 _Assume_(str);
    +
    30#ifdef _WIN32
    +
    31 _snprintf_s_l(str, 39, _TRUNCATE, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", NULL,
    +
    32 id.Data1,
    +
    33 static_cast<unsigned int>(id.Data2),
    +
    34 static_cast<unsigned int>(id.Data3),
    +
    35 static_cast<unsigned int>(id.Data4[0]), static_cast<unsigned int>(id.Data4[1]),
    +
    36 static_cast<unsigned int>(id.Data4[2]), static_cast<unsigned int>(id.Data4[3]), static_cast<unsigned int>(id.Data4[4]), static_cast<unsigned int>(id.Data4[5]), static_cast<unsigned int>(id.Data4[6]), static_cast<unsigned int>(id.Data4[7]));
    +
    37#else
    +
    38 snprintf(str, 39, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", NULL,
    +
    39 *reinterpret_cast<const uint32_t*>(&id[0]),
    +
    40 static_cast<unsigned int>(*reinterpret_cast<const uint16_t*>(&id[4])),
    +
    41 static_cast<unsigned int>(*reinterpret_cast<const uint16_t*>(&id[6])),
    +
    42 static_cast<unsigned int>(id[8]), static_cast<unsigned int>(id[9]),
    +
    43 static_cast<unsigned int>(id[10]), static_cast<unsigned int>(id[11]), static_cast<unsigned int>(id[12]), static_cast<unsigned int>(id[13]), static_cast<unsigned int>(id[14]), static_cast<unsigned int>(id[15]));
    +
    44#endif
    +
    45 }
    +
    46
    +
    53 inline void uuidtostr(_Out_writes_z_(39) wchar_t str[39], _In_ const uuid_t& id)
    +
    54 {
    +
    55 _Assume_(str);
    +
    56#ifdef _WIN32
    +
    57 _snwprintf_s_l(str, 39, _TRUNCATE, L"{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", NULL,
    +
    58 id.Data1,
    +
    59 static_cast<unsigned int>(id.Data2),
    +
    60 static_cast<unsigned int>(id.Data3),
    +
    61 static_cast<unsigned int>(id.Data4[0]), static_cast<unsigned int>(id.Data4[1]),
    +
    62 static_cast<unsigned int>(id.Data4[2]), static_cast<unsigned int>(id.Data4[3]), static_cast<unsigned int>(id.Data4[4]), static_cast<unsigned int>(id.Data4[5]), static_cast<unsigned int>(id.Data4[6]), static_cast<unsigned int>(id.Data4[7]));
    +
    63#else
    +
    64 swprintf(str, 39, L"{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", NULL,
    +
    65 *reinterpret_cast<const uint32_t*>(&id[0]),
    +
    66 static_cast<unsigned int>(*reinterpret_cast<const uint16_t*>(&id[4])),
    +
    67 static_cast<unsigned int>(*reinterpret_cast<const uint16_t*>(&id[6])),
    +
    68 static_cast<unsigned int>(id[8]), static_cast<unsigned int>(id[9]),
    +
    69 static_cast<unsigned int>(id[10]), static_cast<unsigned int>(id[11]), static_cast<unsigned int>(id[12]), static_cast<unsigned int>(id[13]), static_cast<unsigned int>(id[14]), static_cast<unsigned int>(id[15]));
    +
    70#endif
    +
    71 }
    +
    72}
    +
    + + + + diff --git a/vector__queue_8hpp_source.html b/vector__queue_8hpp_source.html index fd7bb7c2a..437f32974 100644 --- a/vector__queue_8hpp_source.html +++ b/vector__queue_8hpp_source.html @@ -90,368 +90,370 @@ $(document).ready(function() { init_codefold(0); });
    6#pragma once
    7
    8#include "compat.hpp"
    -
    9
    -
    10namespace stdex
    -
    11{
    -
    15 template <class T>
    -
    - -
    17 {
    -
    18 public:
    -
    22 typedef size_t size_type;
    -
    23
    -
    27 typedef T value_type;
    -
    28
    -
    32 typedef T& reference;
    -
    33
    -
    37 typedef const T& const_reference;
    -
    38
    -
    42 typedef T* pointer;
    -
    43
    -
    47 typedef const T* const_pointer;
    -
    48
    -
    49 public:
    -
    -
    55 vector_queue(_In_ size_type size_max) :
    -
    56 m_data(new value_type[size_max]),
    -
    57 m_head(0),
    -
    58 m_count(0),
    -
    59 m_size_max(size_max)
    -
    60 {
    -
    61 }
    +
    9#include <stdexcept>
    +
    10#include <utility>
    +
    11
    +
    12namespace stdex
    +
    13{
    +
    17 template <class T>
    +
    + +
    19 {
    +
    20 public:
    +
    24 typedef size_t size_type;
    +
    25
    +
    29 typedef T value_type;
    +
    30
    +
    34 typedef T& reference;
    +
    35
    +
    39 typedef const T& const_reference;
    +
    40
    +
    44 typedef T* pointer;
    +
    45
    +
    49 typedef const T* const_pointer;
    +
    50
    +
    51 public:
    +
    +
    57 vector_queue(_In_ size_type size_max) :
    +
    58 m_data(new value_type[size_max]),
    +
    59 m_head(0),
    +
    60 m_count(0),
    +
    61 m_size_max(size_max)
    +
    62 {
    +
    63 }
    -
    62
    -
    - -
    69 m_data(new value_type[other.m_size_max]),
    -
    70 m_head(other.m_head),
    -
    71 m_count(other.m_count),
    - -
    73 {
    -
    74 // Copy elements.
    -
    75 for (size_type i = 0; i < m_count; i++) {
    -
    76 size_type i_l = abs(i);
    -
    77 m_data[i_l] = other.m_data[i_l];
    -
    78 }
    -
    79 }
    +
    64
    +
    + +
    71 m_data(new value_type[other.m_size_max]),
    +
    72 m_head(other.m_head),
    +
    73 m_count(other.m_count),
    + +
    75 {
    +
    76 // Copy elements.
    +
    77 for (size_type i = 0; i < m_count; i++) {
    +
    78 size_type i_l = abs(i);
    +
    79 m_data[i_l] = other.m_data[i_l];
    +
    80 }
    +
    81 }
    -
    80
    -
    -
    84 virtual ~vector_queue()
    -
    85 {
    -
    86 if (m_data) delete [] m_data;
    -
    87 }
    +
    82
    +
    +
    86 virtual ~vector_queue()
    +
    87 {
    +
    88 if (m_data) delete [] m_data;
    +
    89 }
    -
    88
    -
    - -
    95 m_data (std::move(other.m_data )),
    -
    96 m_head (std::move(other.m_head )),
    -
    97 m_count (std::move(other.m_count )),
    -
    98 m_size_max(std::move(other.m_size_max))
    -
    99 {
    -
    100 // Reset other to consistent state.
    -
    101 other.m_data = NULL;
    -
    102 other.m_head = 0;
    -
    103 other.m_count = 0;
    -
    104 other.m_size_max = 0;
    -
    105 }
    +
    90
    +
    + +
    97 m_data (std::move(other.m_data )),
    +
    98 m_head (std::move(other.m_head )),
    +
    99 m_count (std::move(other.m_count )),
    +
    100 m_size_max(std::move(other.m_size_max))
    +
    101 {
    +
    102 // Reset other to consistent state.
    +
    103 other.m_data = NULL;
    +
    104 other.m_head = 0;
    +
    105 other.m_count = 0;
    +
    106 other.m_size_max = 0;
    +
    107 }
    -
    106
    -
    - -
    113 {
    -
    114 if (this != std::addressof(other)) {
    -
    115 m_head = other.m_head;
    -
    116 m_count = other.m_count;
    -
    117 m_size_max = other.m_size_max;
    -
    118
    -
    119 // Copy elements.
    -
    120 if (m_data) delete [] m_data;
    -
    121 m_data = new value_type[other.m_size_max];
    -
    122 for (size_type i = 0; i < m_count; i++) {
    -
    123 size_type i_l = abs(i);
    -
    124 m_data[i_l] = other.m_data[i_l];
    -
    125 }
    -
    126 }
    -
    127
    -
    128 return *this;
    -
    129 }
    +
    108
    +
    + +
    115 {
    +
    116 if (this != std::addressof(other)) {
    +
    117 m_head = other.m_head;
    +
    118 m_count = other.m_count;
    +
    119 m_size_max = other.m_size_max;
    +
    120
    +
    121 // Copy elements.
    +
    122 if (m_data) delete [] m_data;
    +
    123 m_data = new value_type[other.m_size_max];
    +
    124 for (size_type i = 0; i < m_count; i++) {
    +
    125 size_type i_l = abs(i);
    +
    126 m_data[i_l] = other.m_data[i_l];
    +
    127 }
    +
    128 }
    +
    129
    +
    130 return *this;
    +
    131 }
    -
    130
    -
    - -
    137 {
    -
    138 if (this != std::addressof(other)) {
    -
    139 m_data = std::move(other.m_data );
    -
    140 m_head = std::move(other.m_head );
    -
    141 m_count = std::move(other.m_count );
    -
    142 m_size_max = std::move(other.m_size_max);
    -
    143
    -
    144 // Reset other to consistent state.
    -
    145 other.m_data = NULL;
    -
    146 other.m_head = 0;
    -
    147 other.m_count = 0;
    -
    148 other.m_size_max = 0;
    -
    149 }
    -
    150
    -
    151 return *this;
    -
    152 }
    +
    132
    +
    + +
    139 {
    +
    140 if (this != std::addressof(other)) {
    +
    141 m_data = std::move(other.m_data );
    +
    142 m_head = std::move(other.m_head );
    +
    143 m_count = std::move(other.m_count );
    +
    144 m_size_max = std::move(other.m_size_max);
    +
    145
    +
    146 // Reset other to consistent state.
    +
    147 other.m_data = NULL;
    +
    148 other.m_head = 0;
    +
    149 other.m_count = 0;
    +
    150 other.m_size_max = 0;
    +
    151 }
    +
    152
    +
    153 return *this;
    +
    154 }
    -
    153
    -
    - -
    158 {
    -
    159 return m_count;
    -
    160 }
    +
    155
    +
    + +
    160 {
    +
    161 return m_count;
    +
    162 }
    -
    161
    -
    - -
    166 {
    -
    167 return m_size_max;
    -
    168 }
    +
    163
    +
    + +
    168 {
    +
    169 return m_size_max;
    +
    170 }
    -
    169
    -
    -
    173 void clear()
    -
    174 {
    -
    175 m_count = 0;
    -
    176 }
    +
    171
    +
    +
    175 void clear()
    +
    176 {
    +
    177 m_count = 0;
    +
    178 }
    -
    177
    -
    -
    181 bool empty() const
    -
    182 {
    -
    183 return m_count == 0;
    -
    184 }
    +
    179
    +
    +
    183 bool empty() const
    +
    184 {
    +
    185 return m_count == 0;
    +
    186 }
    -
    185
    -
    - -
    192 {
    -
    193 if (pos >= m_count) throw std::invalid_argument("Invalid subscript");
    -
    194 return m_data[abs(pos)];
    -
    195 }
    +
    187
    +
    + +
    194 {
    +
    195 if (pos >= m_count) throw std::invalid_argument("Invalid subscript");
    +
    196 return m_data[abs(pos)];
    +
    197 }
    -
    196
    -
    - -
    203 {
    -
    204 if (pos >= m_count) throw std::invalid_argument("Invalid subscript");
    -
    205 return m_data[abs(pos)];
    -
    206 }
    +
    198
    +
    + +
    205 {
    +
    206 if (pos >= m_count) throw std::invalid_argument("Invalid subscript");
    +
    207 return m_data[abs(pos)];
    +
    208 }
    -
    207
    -
    - -
    214 {
    -
    215 if (pos >= m_count) throw std::invalid_argument("Invalid subscript");
    -
    216 return m_data[abs(pos)];
    -
    217 }
    +
    209
    +
    + +
    216 {
    +
    217 if (pos >= m_count) throw std::invalid_argument("Invalid subscript");
    +
    218 return m_data[abs(pos)];
    +
    219 }
    -
    218
    -
    - -
    225 {
    -
    226 if (pos >= m_count) throw std::invalid_argument("Invalid subscript");
    -
    227 return m_data[abs(pos)];
    -
    228 }
    +
    220
    +
    + +
    227 {
    +
    228 if (pos >= m_count) throw std::invalid_argument("Invalid subscript");
    +
    229 return m_data[abs(pos)];
    +
    230 }
    -
    229
    -
    - -
    238 {
    -
    239 if (pos >= m_size_max) throw std::invalid_argument("Invalid subscript");
    -
    240 return m_data[pos];
    -
    241 }
    +
    231
    +
    + +
    240 {
    +
    241 if (pos >= m_size_max) throw std::invalid_argument("Invalid subscript");
    +
    242 return m_data[pos];
    +
    243 }
    -
    242
    -
    - -
    251 {
    -
    252 if (pos >= m_size_max) throw std::invalid_argument("Invalid subscript");
    -
    253 return m_data[pos];
    -
    254 }
    +
    244
    +
    + +
    253 {
    +
    254 if (pos >= m_size_max) throw std::invalid_argument("Invalid subscript");
    +
    255 return m_data[pos];
    +
    256 }
    -
    255
    -
    - -
    264 {
    -
    265 if (m_count < m_size_max) {
    -
    266 size_type pos = abs(m_count);
    -
    267 m_data[pos] = v;
    -
    268 m_count++;
    -
    269 return pos;
    -
    270 } else {
    -
    271 size_type pos = m_head;
    -
    272 m_data[pos] = v;
    -
    273 m_head = abs(1);
    -
    274 return pos;
    -
    275 }
    -
    276 }
    +
    257
    +
    + +
    266 {
    +
    267 if (m_count < m_size_max) {
    +
    268 size_type pos = abs(m_count);
    +
    269 m_data[pos] = v;
    +
    270 m_count++;
    +
    271 return pos;
    +
    272 } else {
    +
    273 size_type pos = m_head;
    +
    274 m_data[pos] = v;
    +
    275 m_head = abs(1);
    +
    276 return pos;
    +
    277 }
    +
    278 }
    -
    277
    -
    - -
    286 {
    -
    287 if (m_count < m_size_max) {
    -
    288 size_type pos = abs(m_count);
    -
    289 m_data[pos] = std::move(v);
    -
    290 m_count++;
    -
    291 return pos;
    -
    292 } else {
    -
    293 size_type pos = m_head;
    -
    294 m_data[pos] = std::move(v);
    -
    295 m_head = abs(1);
    -
    296 return pos;
    -
    297 }
    -
    298 }
    +
    279
    +
    + +
    288 {
    +
    289 if (m_count < m_size_max) {
    +
    290 size_type pos = abs(m_count);
    +
    291 m_data[pos] = std::move(v);
    +
    292 m_count++;
    +
    293 return pos;
    +
    294 } else {
    +
    295 size_type pos = m_head;
    +
    296 m_data[pos] = std::move(v);
    +
    297 m_head = abs(1);
    +
    298 return pos;
    +
    299 }
    +
    300 }
    -
    299
    -
    -
    303 void pop_back()
    -
    304 {
    -
    305 if (!m_count) throw std::invalid_argument("Empty storage");
    -
    306 m_count--;
    -
    307 }
    +
    301
    +
    +
    305 void pop_back()
    +
    306 {
    +
    307 if (!m_count) throw std::invalid_argument("Empty storage");
    +
    308 m_count--;
    +
    309 }
    -
    308
    -
    - -
    317 {
    -
    318 m_head = abs(-1);
    -
    319 if (m_count < m_size_max)
    -
    320 m_count++;
    -
    321 m_data[m_head] = v;
    -
    322 return m_head;
    -
    323 }
    +
    310
    +
    + +
    319 {
    +
    320 m_head = abs(-1);
    +
    321 if (m_count < m_size_max)
    +
    322 m_count++;
    +
    323 m_data[m_head] = v;
    +
    324 return m_head;
    +
    325 }
    -
    324
    -
    - -
    333 {
    -
    334 m_head = abs(-1);
    -
    335 if (m_count < m_size_max)
    -
    336 m_count++;
    -
    337 m_data[m_head] = std::move(v);
    -
    338 return m_head;
    -
    339 }
    +
    326
    +
    + +
    335 {
    +
    336 m_head = abs(-1);
    +
    337 if (m_count < m_size_max)
    +
    338 m_count++;
    +
    339 m_data[m_head] = std::move(v);
    +
    340 return m_head;
    +
    341 }
    -
    340
    -
    - -
    345 {
    -
    346 if (!m_count) throw std::invalid_argument("Empty storage");
    -
    347 m_head = abs(1);
    -
    348 m_count--;
    -
    349 }
    +
    342
    +
    + +
    347 {
    +
    348 if (!m_count) throw std::invalid_argument("Empty storage");
    +
    349 m_head = abs(1);
    +
    350 m_count--;
    +
    351 }
    -
    350
    -
    - -
    355 {
    -
    356 if (!m_count) throw std::invalid_argument("Empty storage");
    -
    357 return m_data[m_head];
    -
    358 }
    +
    352
    +
    + +
    357 {
    +
    358 if (!m_count) throw std::invalid_argument("Empty storage");
    +
    359 return m_data[m_head];
    +
    360 }
    -
    359
    -
    - -
    364 {
    -
    365 if (!m_count) throw std::invalid_argument("Empty storage");
    -
    366 return m_data[m_head];
    -
    367 }
    +
    361
    +
    + +
    366 {
    +
    367 if (!m_count) throw std::invalid_argument("Empty storage");
    +
    368 return m_data[m_head];
    +
    369 }
    -
    368
    -
    - -
    373 {
    -
    374 return m_data[tail()];
    -
    375 }
    +
    370
    +
    + +
    375 {
    +
    376 return m_data[tail()];
    +
    377 }
    -
    376
    -
    - -
    381 {
    -
    382 return m_data[tail()];
    -
    383 }
    +
    378
    +
    + +
    383 {
    +
    384 return m_data[tail()];
    +
    385 }
    -
    384
    -
    - -
    389 {
    -
    390 return m_head;
    -
    391 }
    +
    386
    +
    + +
    391 {
    +
    392 return m_head;
    +
    393 }
    -
    392
    -
    - -
    397 {
    -
    398 if (!m_count) throw std::invalid_argument("Empty storage");
    -
    399 return abs(m_count - 1);
    -
    400 }
    +
    394
    +
    + +
    399 {
    +
    400 if (!m_count) throw std::invalid_argument("Empty storage");
    +
    401 return abs(m_count - 1);
    +
    402 }
    -
    401
    -
    -
    405 size_type abs(_In_ size_type pos) const
    -
    406 {
    -
    407 return (m_head + pos) % m_size_max;
    -
    408 }
    +
    403
    +
    +
    407 size_type abs(_In_ size_type pos) const
    +
    408 {
    +
    409 return (m_head + pos) % m_size_max;
    +
    410 }
    -
    409
    -
    410 protected:
    - - - - -
    415 };
    +
    411
    +
    412 protected:
    + + + + +
    417 };
    -
    416}
    -
    Helper class to allow limited size FIFO queues implemented as vector of elements.
    Definition vector_queue.hpp:17
    -
    vector_queue< value_type > & operator=(const vector_queue< value_type > &other)
    Copies existing queue.
    Definition vector_queue.hpp:112
    -
    const T * const_pointer
    Constant pointer to element.
    Definition vector_queue.hpp:47
    -
    bool empty() const
    Tests if the queue is empty.
    Definition vector_queue.hpp:181
    -
    size_type tail() const
    Returns absolute subscript or position number of the last element in the queue. The element must exis...
    Definition vector_queue.hpp:396
    -
    reference operator[](size_type pos)
    Returns a reference to the element at a specified location in the queue.
    Definition vector_queue.hpp:202
    -
    vector_queue(const vector_queue< value_type > &other)
    Copies existing queue.
    Definition vector_queue.hpp:68
    -
    value_type * m_data
    Underlying data container.
    Definition vector_queue.hpp:411
    -
    size_t size_type
    Type to measure element count and indices in.
    Definition vector_queue.hpp:22
    -
    T & reference
    Reference to element type.
    Definition vector_queue.hpp:32
    -
    const_reference back() const
    Returns a constant reference to the last element in the queue.
    Definition vector_queue.hpp:380
    -
    vector_queue(vector_queue< value_type > &&other)
    Moves existing queue.
    Definition vector_queue.hpp:94
    -
    reference back()
    Returns a reference to the last element in the queue.
    Definition vector_queue.hpp:372
    -
    size_type push_back(value_type &&v)
    Moves the element to the end of the queue, overriding the first one when queue is out of space.
    Definition vector_queue.hpp:285
    -
    size_type head() const
    Returns absolute subscript or position number of the head element in the queue. The element does not ...
    Definition vector_queue.hpp:388
    -
    size_type m_count
    Number of elements.
    Definition vector_queue.hpp:413
    -
    virtual ~vector_queue()
    Destroys the queue.
    Definition vector_queue.hpp:84
    -
    reference front()
    Returns a reference to the head element in the queue.
    Definition vector_queue.hpp:354
    -
    size_type m_size_max
    Maximum size.
    Definition vector_queue.hpp:414
    -
    vector_queue< value_type > & operator=(vector_queue< value_type > &&other)
    Moves existing queue.
    Definition vector_queue.hpp:136
    -
    reference at_abs(size_type pos)
    Returns a reference to the element at the absolute location in the queue.
    Definition vector_queue.hpp:237
    -
    void clear()
    Erases the elements of the queue.
    Definition vector_queue.hpp:173
    -
    const_reference front() const
    Returns a constant reference to the head element in the queue.
    Definition vector_queue.hpp:363
    -
    vector_queue(size_type size_max)
    Construct queue of fixed size.
    Definition vector_queue.hpp:55
    -
    T value_type
    Element type.
    Definition vector_queue.hpp:27
    -
    size_type push_back(const value_type &v)
    Copies an existing element to the end of the queue, overriding the first one when queue is out of spa...
    Definition vector_queue.hpp:263
    -
    void pop_back()
    Removes (dequeues) the last element of the queue.
    Definition vector_queue.hpp:303
    -
    size_type m_head
    Index of the first element.
    Definition vector_queue.hpp:412
    -
    T * pointer
    Pointer to element.
    Definition vector_queue.hpp:42
    -
    const_reference at(size_type pos) const
    Returns a constant reference to the element at a specified location in the queue.
    Definition vector_queue.hpp:213
    -
    const_reference operator[](size_type pos) const
    Returns a constant reference to the element at a specified location in the queue.
    Definition vector_queue.hpp:224
    -
    size_type size() const
    Returns the number of elements in the vector.
    Definition vector_queue.hpp:157
    -
    void pop_front()
    Removes (dequeues) the head element of the queue.
    Definition vector_queue.hpp:344
    -
    size_type capacity() const
    Returns the number of elements that the queue can contain before overwriting head ones.
    Definition vector_queue.hpp:165
    -
    size_type push_front(const value_type &v)
    Copies an existing element to the head of the queue, overriding the last one when queue is out of spa...
    Definition vector_queue.hpp:316
    -
    reference at(size_type pos)
    Returns a reference to the element at a specified location in the queue.
    Definition vector_queue.hpp:191
    -
    size_type abs(size_type pos) const
    Returns absolute subscript or position number of the given element in the queue.
    Definition vector_queue.hpp:405
    -
    size_type push_front(value_type &&v)
    Moves the element to the head of the queue, overriding the last one when queue is out of space and mo...
    Definition vector_queue.hpp:332
    -
    const T & const_reference
    Constant reference to element type.
    Definition vector_queue.hpp:37
    -
    const_reference at_abs(size_type pos) const
    Returns a constant reference to the element at the absolute location in the queue: measured from the ...
    Definition vector_queue.hpp:250
    +
    418}
    +
    Helper class to allow limited size FIFO queues implemented as vector of elements.
    Definition vector_queue.hpp:19
    +
    vector_queue< value_type > & operator=(const vector_queue< value_type > &other)
    Copies existing queue.
    Definition vector_queue.hpp:114
    +
    const T * const_pointer
    Constant pointer to element.
    Definition vector_queue.hpp:49
    +
    bool empty() const
    Tests if the queue is empty.
    Definition vector_queue.hpp:183
    +
    size_type tail() const
    Returns absolute subscript or position number of the last element in the queue. The element must exis...
    Definition vector_queue.hpp:398
    +
    reference operator[](size_type pos)
    Returns a reference to the element at a specified location in the queue.
    Definition vector_queue.hpp:204
    +
    vector_queue(const vector_queue< value_type > &other)
    Copies existing queue.
    Definition vector_queue.hpp:70
    +
    value_type * m_data
    Underlying data container.
    Definition vector_queue.hpp:413
    +
    size_t size_type
    Type to measure element count and indices in.
    Definition vector_queue.hpp:24
    +
    T & reference
    Reference to element type.
    Definition vector_queue.hpp:34
    +
    const_reference back() const
    Returns a constant reference to the last element in the queue.
    Definition vector_queue.hpp:382
    +
    vector_queue(vector_queue< value_type > &&other)
    Moves existing queue.
    Definition vector_queue.hpp:96
    +
    reference back()
    Returns a reference to the last element in the queue.
    Definition vector_queue.hpp:374
    +
    size_type push_back(value_type &&v)
    Moves the element to the end of the queue, overriding the first one when queue is out of space.
    Definition vector_queue.hpp:287
    +
    size_type head() const
    Returns absolute subscript or position number of the head element in the queue. The element does not ...
    Definition vector_queue.hpp:390
    +
    size_type m_count
    Number of elements.
    Definition vector_queue.hpp:415
    +
    virtual ~vector_queue()
    Destroys the queue.
    Definition vector_queue.hpp:86
    +
    reference front()
    Returns a reference to the head element in the queue.
    Definition vector_queue.hpp:356
    +
    size_type m_size_max
    Maximum size.
    Definition vector_queue.hpp:416
    +
    vector_queue< value_type > & operator=(vector_queue< value_type > &&other)
    Moves existing queue.
    Definition vector_queue.hpp:138
    +
    reference at_abs(size_type pos)
    Returns a reference to the element at the absolute location in the queue.
    Definition vector_queue.hpp:239
    +
    void clear()
    Erases the elements of the queue.
    Definition vector_queue.hpp:175
    +
    const_reference front() const
    Returns a constant reference to the head element in the queue.
    Definition vector_queue.hpp:365
    +
    vector_queue(size_type size_max)
    Construct queue of fixed size.
    Definition vector_queue.hpp:57
    +
    T value_type
    Element type.
    Definition vector_queue.hpp:29
    +
    size_type push_back(const value_type &v)
    Copies an existing element to the end of the queue, overriding the first one when queue is out of spa...
    Definition vector_queue.hpp:265
    +
    void pop_back()
    Removes (dequeues) the last element of the queue.
    Definition vector_queue.hpp:305
    +
    size_type m_head
    Index of the first element.
    Definition vector_queue.hpp:414
    +
    T * pointer
    Pointer to element.
    Definition vector_queue.hpp:44
    +
    const_reference at(size_type pos) const
    Returns a constant reference to the element at a specified location in the queue.
    Definition vector_queue.hpp:215
    +
    const_reference operator[](size_type pos) const
    Returns a constant reference to the element at a specified location in the queue.
    Definition vector_queue.hpp:226
    +
    size_type size() const
    Returns the number of elements in the vector.
    Definition vector_queue.hpp:159
    +
    void pop_front()
    Removes (dequeues) the head element of the queue.
    Definition vector_queue.hpp:346
    +
    size_type capacity() const
    Returns the number of elements that the queue can contain before overwriting head ones.
    Definition vector_queue.hpp:167
    +
    size_type push_front(const value_type &v)
    Copies an existing element to the head of the queue, overriding the last one when queue is out of spa...
    Definition vector_queue.hpp:318
    +
    reference at(size_type pos)
    Returns a reference to the element at a specified location in the queue.
    Definition vector_queue.hpp:193
    +
    size_type abs(size_type pos) const
    Returns absolute subscript or position number of the given element in the queue.
    Definition vector_queue.hpp:407
    +
    size_type push_front(value_type &&v)
    Moves the element to the head of the queue, overriding the last one when queue is out of space and mo...
    Definition vector_queue.hpp:334
    +
    const T & const_reference
    Constant reference to element type.
    Definition vector_queue.hpp:39
    +
    const_reference at_abs(size_type pos) const
    Returns a constant reference to the element at the absolute location in the queue: measured from the ...
    Definition vector_queue.hpp:252
    diff --git a/watchdog_8cpp_source.html b/watchdog_8cpp_source.html index b30325a09..7be305d57 100644 --- a/watchdog_8cpp_source.html +++ b/watchdog_8cpp_source.html @@ -118,7 +118,7 @@ $(document).ready(function() { init_codefold(0); });
    diff --git a/watchdog_8hpp_source.html b/watchdog_8hpp_source.html index 622fe9819..f910d4fb2 100644 --- a/watchdog_8hpp_source.html +++ b/watchdog_8hpp_source.html @@ -176,7 +176,7 @@ $(document).ready(function() { init_codefold(0); });
    diff --git a/windows_8h_source.html b/windows_8h_source.html index 8c6762eba..f473c9d3c 100644 --- a/windows_8h_source.html +++ b/windows_8h_source.html @@ -109,7 +109,7 @@ $(document).ready(function() { init_codefold(0); });