diff --git a/_unit_tests_2compat_8hpp_source.html b/_unit_tests_2compat_8hpp_source.html new file mode 100644 index 000000000..edb9f7cf8 --- /dev/null +++ b/_unit_tests_2compat_8hpp_source.html @@ -0,0 +1,168 @@ + + + + + + + +stdex: UnitTests/compat.hpp Source File + + + + + + + + + +
+
+ + + + + + +
+
stdex +
+
Additional custom or not Standard C++ covered algorithms
+
+
+ + + + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
compat.hpp
+
+
+
1/*
+
2 SPDX-License-Identifier: MIT
+
3 Copyright © 2023 Amebis
+
4*/
+
5
+
6#pragma once
+
7
+
8#if defined(_WIN32)
+
9#include <CppUnitTest.h>
+
10#elif defined(__APPLE__)
+
11#include <stdexcept>
+
12
+
13#define TEST_CLASS(name) class name
+
14#define TEST_METHOD(name) static void name()
+
15
+
16namespace Assert
+
17{
+
18 inline void IsTrue(bool c)
+
19 {
+
20 if (!c)
+
21 throw std::runtime_error("not true");
+
22 }
+
23
+
24 inline void IsFalse(bool c)
+
25 {
+
26 if (c)
+
27 throw std::runtime_error("not false");
+
28 }
+
29
+
30 template <class T>
+
31 inline void AreEqual(const T& a, const T& b)
+
32 {
+
33 if (!(a == b))
+
34 throw std::runtime_error("not equal");
+
35 }
+
36
+
37 inline void AreEqual(const char* a, const char* b)
+
38 {
+
39 if (strcmp(a, b) != 0)
+
40 throw std::runtime_error("not equal");
+
41 }
+
42
+
43 inline void AreEqual(const wchar_t* a, const wchar_t* b)
+
44 {
+
45 if (wcscmp(a, b) != 0)
+
46 throw std::runtime_error("not equal");
+
47 }
+
48
+
49 template <class T>
+
50 inline void AreNotEqual(const T& a, const T& b)
+
51 {
+
52 if (a == b)
+
53 throw std::runtime_error("equal");
+
54 }
+
55
+
56 inline void AreNotEqual(const char* a, const char* b)
+
57 {
+
58 if (strcmp(a, b) == 0)
+
59 throw std::runtime_error("equal");
+
60 }
+
61
+
62 inline void AreNotEqual(const wchar_t* a, const wchar_t* b)
+
63 {
+
64 if (wcscmp(a, b) == 0)
+
65 throw std::runtime_error("equal");
+
66 }
+
67
+
68 template <class E, typename F>
+
69 inline void ExpectException(F functor)
+
70 {
+
71 try { functor(); }
+
72 catch (const E&) { return; }
+
73 catch (...) { throw std::runtime_error("unexpected exception"); }
+
74 throw std::runtime_error("exception not thrown");
+
75 }
+
76}
+
77#endif
+
+ + + + diff --git a/annotated.html b/annotated.html index 8a0a3de50..303647ba1 100644 --- a/annotated.html +++ b/annotated.html @@ -202,25 +202,24 @@ $(function() {  Cglobal_progressGlobal progress indicator base class  Chex_decHexadecimal decoding session  Chex_encHexadecimal encoding session - CintervalNumerical interval - Clazy_progressLazy progress indicator base class - CmappingMaps index in source string to index in destination string - Cno_deleteNoop deleter - Cno_delete< T[]>Noop array deleter - CprogressProgress indicator base class - Cprogress_switcherProgress indicator switcher - CringRing buffer - Csys_objectOperating system object (file, pipe, anything with an OS handle etc.) - Cuser_cancelledUser cancelled exception - Cvector_queueHelper class to allow limited size FIFO queues implemented as vector of elements - NUnitTests - Cmath + CiconverterUnicode converter context + CintervalNumerical interval + Clazy_progressLazy progress indicator base class + CmappingMaps index in source string to index in destination string + Cno_deleteNoop deleter + Cno_delete< T[]>Noop array deleter + CprogressProgress indicator base class + Cprogress_switcherProgress indicator switcher + CringRing buffer + Csys_objectOperating system object (file, pipe, anything with an OS handle etc.) + Cuser_cancelledUser cancelled exception + Cvector_queueHelper class to allow limited size FIFO queues implemented as vector of elements diff --git a/base64_8hpp_source.html b/base64_8hpp_source.html index 7b491d1fe..bf60a095c 100644 --- a/base64_8hpp_source.html +++ b/base64_8hpp_source.html @@ -89,7 +89,7 @@ $(document).ready(function() { init_codefold(0); });
5
6#pragma once
7
-
8#include "sal.hpp"
+
8#include "compat.hpp"
9#include <assert.h>
10#include <cstdint>
11#include <string>
@@ -98,258 +98,255 @@ $(document).ready(function() { init_codefold(0); });
14
15namespace stdex
16{
-
-
20 class base64_enc
-
21 {
-
22 public:
-
-
26 base64_enc() noexcept : num(0)
-
27 {
-
28 buf[0] = 0;
-
29 buf[1] = 0;
-
30 buf[2] = 0;
-
31 }
+
18 static const char base64_enc_lookup[64] = {
+
19 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
+
20 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
+
21 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
+
22 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
+
23 };
+
24
+
25 static const uint8_t base64_dec_lookup[256] = {
+
26 /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
+
27 /* 0 */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+
28 /* 1 */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+
29 /* 2 */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63,
+
30 /* 3 */ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255, 255, 64, 255, 255,
+
31 /* 4 */ 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+
32 /* 5 */ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 255,
+
33 /* 6 */ 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+
34 /* 7 */ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 255, 255, 255, 255, 255,
+
35 /* 8 */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+
36 /* 9 */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+
37 /* A */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+
38 /* B */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+
39 /* C */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+
40 /* D */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+
41 /* E */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+
42 /* F */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255
+
43 };
+
45
+
+ +
50 {
+
51 public:
+
+
55 base64_enc() noexcept : num(0)
+
56 {
+
57 buf[0] = 0;
+
58 buf[1] = 0;
+
59 buf[2] = 0;
+
60 }
-
32
-
33
-
42 template<class _Elem, class _Traits, class _Ax>
-
-
43 void encode(_Inout_ std::basic_string<_Elem, _Traits, _Ax> &out, _In_bytecount_(size) const void *data, _In_ size_t size, _In_opt_ bool is_last = true)
-
44 {
-
45 assert(data || !size);
-
46
-
47 // Preallocate output
-
48 out.reserve(out.size() + enc_size(size));
-
49
-
50 // Convert data character by character.
-
51 for (size_t i = 0;; i++) {
-
52 if (num >= 3) {
-
53 encode(out);
-
54 num = 0;
-
55 }
-
56
-
57 if (i >= size)
-
58 break;
-
59
-
60 buf[num++] = reinterpret_cast<const uint8_t*>(data)[i];
-
61 }
+
61
62
-
63 // If this is the last block, flush the buffer.
-
64 if (is_last && num) {
-
65 encode(out, num);
-
66 num = 0;
-
67 }
-
68 }
-
-
69
-
70
-
-
74 void clear() noexcept
-
75 {
-
76 num = 0;
-
77 }
-
+
71 template<class _Elem, class _Traits, class _Ax>
+
+
72 void encode(_Inout_ std::basic_string<_Elem, _Traits, _Ax> &out, _In_bytecount_(size) const void *data, _In_ size_t size, _In_opt_ bool is_last = true)
+
73 {
+
74 assert(data || !size);
+
75
+
76 // Preallocate output
+
77 out.reserve(out.size() + enc_size(size));
78
-
79
-
-
87 size_t enc_size(_In_ size_t size) const noexcept
-
88 {
-
89 return ((num + size + 2)/3)*4;
-
90 }
-
+
79 // Convert data character by character.
+
80 for (size_t i = 0;; i++) {
+
81 if (num >= 3) {
+
82 encode(out);
+
83 num = 0;
+
84 }
+
85
+
86 if (i >= size)
+
87 break;
+
88
+
89 buf[num++] = reinterpret_cast<const uint8_t*>(data)[i];
+
90 }
91
-
92
-
93 protected:
-
97 template<class _Elem, class _Traits, class _Ax>
-
-
98 void encode(_Inout_ std::basic_string<_Elem, _Traits, _Ax> &out)
-
99 {
-
100 out += base64_enc_lookup[ buf[0] >> 2 ];
-
101 out += base64_enc_lookup[((buf[0] << 4) | (buf[1] >> 4)) & 0x3f];
-
102 out += base64_enc_lookup[((buf[1] << 2) | (buf[2] >> 6)) & 0x3f];
-
103 out += base64_enc_lookup[ buf[2] & 0x3f];
-
104 }
+
92 // If this is the last block, flush the buffer.
+
93 if (is_last && num) {
+
94 encode(out, num);
+
95 num = 0;
+
96 }
+
97 }
-
105
-
106
-
110 template<class _Elem, class _Traits, class _Ax>
-
-
111 void encode(_Inout_ std::basic_string<_Elem, _Traits, _Ax> &out, _In_ size_t size)
-
112 {
-
113 if (size > 0) {
-
114 out += base64_enc_lookup[buf[0] >> 2];
-
115 if (size > 1) {
-
116 out += base64_enc_lookup[((buf[0] << 4) | (buf[1] >> 4)) & 0x3f];
-
117 if (size > 2) {
-
118 out += base64_enc_lookup[((buf[1] << 2) | (buf[2] >> 6)) & 0x3f];
-
119 out += base64_enc_lookup[buf[2] & 0x3f];
-
120 } else {
-
121 out += base64_enc_lookup[(buf[1] << 2) & 0x3f];
-
122 out += '=';
-
123 }
-
124 } else {
-
125 out += base64_enc_lookup[(buf[0] << 4) & 0x3f];
-
126 out += '=';
-
127 out += '=';
-
128 }
-
129 } else {
-
130 out += '=';
-
131 out += '=';
-
132 out += '=';
-
133 out += '=';
-
134 }
-
135 }
+
98
+
99
+
+
103 void clear() noexcept
+
104 {
+
105 num = 0;
+
106 }
-
136
-
137
-
138 protected:
-
139 uint8_t buf[3];
-
140 size_t num;
-
141 };
+
107
+
108
+
+
116 size_t enc_size(_In_ size_t size) const noexcept
+
117 {
+
118 return ((num + size + 2)/3)*4;
+
119 }
-
142
-
143
-
145 static const char base64_enc_lookup[64] = {
-
146 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
-
147 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
-
148 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
-
149 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
-
150 };
-
152
-
153
-
- -
158 {
-
159 public:
-
-
163 base64_dec() noexcept : num(0)
-
164 {
-
165 buf[0] = 0;
-
166 buf[1] = 0;
-
167 buf[2] = 0;
-
168 buf[3] = 0;
-
169 }
+
120
+
121
+
122 protected:
+
126 template<class _Elem, class _Traits, class _Ax>
+
+
127 void encode(_Inout_ std::basic_string<_Elem, _Traits, _Ax> &out)
+
128 {
+
129 out += base64_enc_lookup[ buf[0] >> 2 ];
+
130 out += base64_enc_lookup[((buf[0] << 4) | (buf[1] >> 4)) & 0x3f];
+
131 out += base64_enc_lookup[((buf[1] << 2) | (buf[2] >> 6)) & 0x3f];
+
132 out += base64_enc_lookup[ buf[2] & 0x3f];
+
133 }
+
+
134
+
135
+
139 template<class _Elem, class _Traits, class _Ax>
+
+
140 void encode(_Inout_ std::basic_string<_Elem, _Traits, _Ax> &out, _In_ size_t size)
+
141 {
+
142 if (size > 0) {
+
143 out += base64_enc_lookup[buf[0] >> 2];
+
144 if (size > 1) {
+
145 out += base64_enc_lookup[((buf[0] << 4) | (buf[1] >> 4)) & 0x3f];
+
146 if (size > 2) {
+
147 out += base64_enc_lookup[((buf[1] << 2) | (buf[2] >> 6)) & 0x3f];
+
148 out += base64_enc_lookup[buf[2] & 0x3f];
+
149 } else {
+
150 out += base64_enc_lookup[(buf[1] << 2) & 0x3f];
+
151 out += '=';
+
152 }
+
153 } else {
+
154 out += base64_enc_lookup[(buf[0] << 4) & 0x3f];
+
155 out += '=';
+
156 out += '=';
+
157 }
+
158 } else {
+
159 out += '=';
+
160 out += '=';
+
161 out += '=';
+
162 out += '=';
+
163 }
+
164 }
+
+
165
+
166
+
167 protected:
+
168 uint8_t buf[3];
+
169 size_t num;
+
170 };
-
170
171
-
180 template<class _Ty, class _Ax, class _Tchr>
+
+ +
176 {
+
177 public:
-
181 void decode(_Inout_ std::vector<_Ty, _Ax> &out, _Out_ bool &is_last, _In_z_count_(size) const _Tchr *data, _In_ size_t size)
+
181 base64_dec() noexcept : num(0)
182 {
-
183 is_last = false;
-
184
-
185 // Trim data size to first terminator.
-
186 for (size_t k = 0; k < size; k++)
-
187 if (!data[k]) { size = k; break; }
+
183 buf[0] = 0;
+
184 buf[1] = 0;
+
185 buf[2] = 0;
+
186 buf[3] = 0;
+
187 }
+
188
-
189 // Preallocate output
-
190 out.reserve(out.size() + dec_size(size));
-
191
-
192 for (size_t i = 0;; i++) {
-
193 if (num >= 4) {
-
194 // Buffer full; decode it.
-
195 size_t nibbles = decode(out);
-
196 num = 0;
-
197 if (nibbles < 3) {
-
198 is_last = true;
-
199 break;
-
200 }
-
201 }
+
189
+
198 template<class _Ty, class _Ax, class _Tchr>
+
+
199 void decode(_Inout_ std::vector<_Ty, _Ax> &out, _Out_ bool &is_last, _In_z_count_(size) const _Tchr *data, _In_ size_t size)
+
200 {
+
201 is_last = false;
202
-
203 if (i >= size)
-
204 break;
-
205
-
206 int x = data[i];
-
207 if ((buf[num] = x < _countof(base64_dec_lookup) ? base64_dec_lookup[x] : 255) != 255)
-
208 num++;
-
209 }
-
210 }
-
-
211
-
212
-
-
216 void clear() noexcept
-
217 {
-
218 num = 0;
-
219 }
-
+
203 // Trim data size to first terminator.
+
204 for (size_t k = 0; k < size; k++)
+
205 if (!data[k]) { size = k; break; }
+
206
+
207 // Preallocate output
+
208 out.reserve(out.size() + dec_size(size));
+
209
+
210 for (size_t i = 0;; i++) {
+
211 if (num >= 4) {
+
212 // Buffer full; decode it.
+
213 size_t nibbles = decode(out);
+
214 num = 0;
+
215 if (nibbles < 3) {
+
216 is_last = true;
+
217 break;
+
218 }
+
219 }
220
-
221
-
-
229 size_t dec_size(_In_ size_t size) const noexcept
-
230 {
-
231 return ((num + size + 3)/4)*3;
-
232 }
+
221 if (i >= size)
+
222 break;
+
223
+
224 int x = data[i];
+
225 if ((buf[num] = x < _countof(base64_dec_lookup) ? base64_dec_lookup[x] : 255) != 255)
+
226 num++;
+
227 }
+
228 }
-
233
-
234
-
235 protected:
-
239 template<class _Ty, class _Ax>
-
-
240 size_t decode(_Inout_ std::vector<_Ty, _Ax> &out)
-
241 {
-
242 out.push_back((_Ty)(((buf[0] << 2) | (buf[1] >> 4)) & 0xff));
-
243 if (buf[2] < 64) {
-
244 out.push_back((_Ty)(((buf[1] << 4) | (buf[2] >> 2)) & 0xff));
-
245 if (buf[3] < 64) {
-
246 out.push_back((_Ty)(((buf[2] << 6) | buf[3]) & 0xff));
-
247 return 3;
-
248 } else
-
249 return 2;
-
250 } else
-
251 return 1;
-
252 }
+
229
+
230
+
+
234 void clear() noexcept
+
235 {
+
236 num = 0;
+
237 }
-
253
-
254
-
255 protected:
-
256 uint8_t buf[4];
-
257 size_t num;
-
258 };
+
238
+
239
+
+
247 size_t dec_size(_In_ size_t size) const noexcept
+
248 {
+
249 return ((num + size + 3)/4)*3;
+
250 }
-
259
-
260
-
262 static const uint8_t base64_dec_lookup[256] = {
-
263 /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
-
264 /* 0 */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
-
265 /* 1 */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
-
266 /* 2 */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63,
-
267 /* 3 */ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255, 255, 64, 255, 255,
-
268 /* 4 */ 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
-
269 /* 5 */ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 255,
-
270 /* 6 */ 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
-
271 /* 7 */ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 255, 255, 255, 255, 255,
-
272 /* 8 */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
-
273 /* 9 */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
-
274 /* A */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
-
275 /* B */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
-
276 /* C */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
-
277 /* D */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
-
278 /* E */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
-
279 /* F */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255
-
280 };
-
282}
-
Base64 decoding session.
Definition base64.hpp:158
-
size_t num
Number of bytes used in buf
Definition base64.hpp:257
-
base64_dec() noexcept
Constructs blank decoding session.
Definition base64.hpp:163
-
void decode(std::vector< _Ty, _Ax > &out, bool &is_last, const _Tchr *data, size_t size)
Decodes one block of information, and appends it to the output.
Definition base64.hpp:181
-
size_t dec_size(size_t size) const noexcept
Returns maximum decoded size.
Definition base64.hpp:229
-
uint8_t buf[4]
Internal buffer.
Definition base64.hpp:256
-
size_t decode(std::vector< _Ty, _Ax > &out)
Decodes one complete internal buffer of data.
Definition base64.hpp:240
-
void clear() noexcept
Resets decoding session.
Definition base64.hpp:216
-
Base64 encoding session.
Definition base64.hpp:21
-
void encode(std::basic_string< _Elem, _Traits, _Ax > &out, const void *data, size_t size, bool is_last=true)
Encodes one block of information, and appends it to the output.
Definition base64.hpp:43
-
void encode(std::basic_string< _Elem, _Traits, _Ax > &out)
Encodes one complete internal buffer of data.
Definition base64.hpp:98
-
size_t num
Number of bytes used in buf
Definition base64.hpp:140
-
void encode(std::basic_string< _Elem, _Traits, _Ax > &out, size_t size)
Encodes partial internal buffer of data.
Definition base64.hpp:111
-
base64_enc() noexcept
Constructs blank encoding session.
Definition base64.hpp:26
-
uint8_t buf[3]
Internal buffer.
Definition base64.hpp:139
-
void clear() noexcept
Resets encoding session.
Definition base64.hpp:74
-
size_t enc_size(size_t size) const noexcept
Returns maximum encoded size.
Definition base64.hpp:87
+
251
+
252
+
253 protected:
+
257 template<class _Ty, class _Ax>
+
+
258 size_t decode(_Inout_ std::vector<_Ty, _Ax> &out)
+
259 {
+
260 out.push_back((_Ty)(((buf[0] << 2) | (buf[1] >> 4)) & 0xff));
+
261 if (buf[2] < 64) {
+
262 out.push_back((_Ty)(((buf[1] << 4) | (buf[2] >> 2)) & 0xff));
+
263 if (buf[3] < 64) {
+
264 out.push_back((_Ty)(((buf[2] << 6) | buf[3]) & 0xff));
+
265 return 3;
+
266 } else
+
267 return 2;
+
268 } else
+
269 return 1;
+
270 }
+
+
271
+
272
+
273 protected:
+
274 uint8_t buf[4];
+
275 size_t num;
+
276 };
+
+
277}
+
Base64 decoding session.
Definition base64.hpp:176
+
size_t num
Number of bytes used in buf
Definition base64.hpp:275
+
base64_dec() noexcept
Constructs blank decoding session.
Definition base64.hpp:181
+
void decode(std::vector< _Ty, _Ax > &out, bool &is_last, const _Tchr *data, size_t size)
Decodes one block of information, and appends it to the output.
Definition base64.hpp:199
+
size_t dec_size(size_t size) const noexcept
Returns maximum decoded size.
Definition base64.hpp:247
+
uint8_t buf[4]
Internal buffer.
Definition base64.hpp:274
+
size_t decode(std::vector< _Ty, _Ax > &out)
Decodes one complete internal buffer of data.
Definition base64.hpp:258
+
void clear() noexcept
Resets decoding session.
Definition base64.hpp:234
+
Base64 encoding session.
Definition base64.hpp:50
+
void encode(std::basic_string< _Elem, _Traits, _Ax > &out, const void *data, size_t size, bool is_last=true)
Encodes one block of information, and appends it to the output.
Definition base64.hpp:72
+
void encode(std::basic_string< _Elem, _Traits, _Ax > &out)
Encodes one complete internal buffer of data.
Definition base64.hpp:127
+
size_t num
Number of bytes used in buf
Definition base64.hpp:169
+
void encode(std::basic_string< _Elem, _Traits, _Ax > &out, size_t size)
Encodes partial internal buffer of data.
Definition base64.hpp:140
+
base64_enc() noexcept
Constructs blank encoding session.
Definition base64.hpp:55
+
uint8_t buf[3]
Internal buffer.
Definition base64.hpp:168
+
void clear() noexcept
Resets encoding session.
Definition base64.hpp:103
+
size_t enc_size(size_t size) const noexcept
Returns maximum encoded size.
Definition base64.hpp:116
diff --git a/chrono_8hpp_source.html b/chrono_8hpp_source.html index 6968f03c1..e1c6eade0 100644 --- a/chrono_8hpp_source.html +++ b/chrono_8hpp_source.html @@ -89,7 +89,7 @@ $(document).ready(function() { init_codefold(0); });
5
6#pragma once
7
-
8#include "sal.hpp"
+
8#include "compat.hpp"
9#include "system.hpp"
10#include "string.hpp"
11#include <stdint.h>
@@ -464,7 +464,7 @@ $(document).ready(function() { init_codefold(0); });
diff --git a/class_unit_tests_1_1math.html b/class_unit_tests_1_1math.html deleted file mode 100644 index 2d3f4fd16..000000000 --- a/class_unit_tests_1_1math.html +++ /dev/null @@ -1,102 +0,0 @@ - - - - - - - -stdex: UnitTests::math Class Reference - - - - - - - - - -
-
- - - - - - -
-
stdex -
-
Additional custom or not Standard C++ covered algorithms
-
-
- - - - - - - - -
-
- - -
-
-
-
-
-
Loading...
-
Searching...
-
No Matches
-
-
-
-
- - -
-
- -
UnitTests::math Class Reference
-
-
- - - - - - -

-Static Public Member Functions

-static void mul ()
 
-static void add ()
 
-
The documentation for this class was generated from the following file: -
- - - - diff --git a/classes.html b/classes.html index 66b3cf8a5..91febea6d 100644 --- a/classes.html +++ b/classes.html @@ -101,13 +101,13 @@ $(function() {
hex_dec (stdex)
hex_enc (stdex)
http_agent (stdex::parser)
http_any_type (stdex::parser)
http_asterisk (stdex::parser)
http_cookie (stdex::parser)
http_cookie_parameter (stdex::parser)
http_factor_more (stdex::parser)
http_header (stdex::parser)
http_language (stdex::parser)
http_line_break (stdex::parser)
http_media_range (stdex::parser)
http_media_type (stdex::parser)
http_parameter (stdex::parser)
http_protocol (stdex::parser)
http_quoted_string (stdex::parser)
http_request (stdex::parser)
http_space (stdex::parser)
http_text_char (stdex::parser)
http_token (stdex::parser)
http_url (stdex::parser)
http_url_parameter (stdex::parser)
http_url_path (stdex::parser)
http_url_path_segment (stdex::parser)
http_url_port (stdex::parser)
http_url_server (stdex::parser)
http_value (stdex::parser)
http_value_collection (stdex::parser)
http_weight (stdex::parser)
http_weighted_value (stdex::parser)
I
-
interval (stdex)
+
iconverter (stdex)
interval (stdex)
L
lazy_progress (stdex)
limiter (stdex::stream)
M
-
mapping (stdex)
math (UnitTests)
memory_file (stdex::stream)
+
mapping (stdex)
memory_file (stdex::stream)
N
no_delete (stdex)
no_delete< T[]> (stdex)
fifo::node_t (stdex::stream)
@@ -133,7 +133,7 @@ $(function() {
diff --git a/classstdex_1_1base64__dec-members.html b/classstdex_1_1base64__dec-members.html index 17bd3bb63..499aa593a 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 6d0a04c89..70fe67212 100644 --- a/classstdex_1_1base64__dec.html +++ b/classstdex_1_1base64__dec.html @@ -230,7 +230,7 @@ template<class _Ty , class _Ax , class _Tchr >
diff --git a/classstdex_1_1base64__enc-members.html b/classstdex_1_1base64__enc-members.html index f02e76b14..f76186e04 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 e1dbf96e7..cfab8f707 100644 --- a/classstdex_1_1base64__enc.html +++ b/classstdex_1_1base64__enc.html @@ -235,7 +235,7 @@ template<class _Elem , class _Traits , class _Ax > diff --git a/classstdex_1_1errno__error-members.html b/classstdex_1_1errno__error-members.html index fe51a9fbf..3b4d17f7e 100644 --- a/classstdex_1_1errno__error-members.html +++ b/classstdex_1_1errno__error-members.html @@ -89,7 +89,7 @@ $(function() { diff --git a/classstdex_1_1errno__error.html b/classstdex_1_1errno__error.html index d4cb799ef..30993a130 100644 --- a/classstdex_1_1errno__error.html +++ b/classstdex_1_1errno__error.html @@ -286,7 +286,7 @@ errno_t m_num diff --git a/classstdex_1_1global__progress-members.html b/classstdex_1_1global__progress-members.html index f7adae658..cef7765b8 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 d83103cfd..49496b401 100644 --- a/classstdex_1_1global__progress.html +++ b/classstdex_1_1global__progress.html @@ -132,9 +132,9 @@ Public Member Functions - - + + @@ -547,7 +547,7 @@ template<class T > diff --git a/classstdex_1_1hex__dec-members.html b/classstdex_1_1hex__dec-members.html index 82bcace79..4740d1d4d 100644 --- a/classstdex_1_1hex__dec-members.html +++ b/classstdex_1_1hex__dec-members.html @@ -89,7 +89,7 @@ $(function() {

Protected Attributes

-progressm_host
 
+progress< T > * m_host
 
interval< T > m_local
 
diff --git a/classstdex_1_1hex__dec.html b/classstdex_1_1hex__dec.html index c013d849a..f92287074 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 3190fa674..4b85c2ecd 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 c198cb6d8..22c136285 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/class_unit_tests_1_1math-members.html b/classstdex_1_1iconverter-members.html similarity index 55% rename from class_unit_tests_1_1math-members.html rename to classstdex_1_1iconverter-members.html index 01a0dc928..68b72e72b 100644 --- a/class_unit_tests_1_1math-members.html +++ b/classstdex_1_1iconverter-members.html @@ -70,22 +70,25 @@ $(function() {
-
UnitTests::math Member List
+
stdex::iconverter< T_from, T_to > Member List
-

This is the complete list of members for UnitTests::math, including all inherited members.

+

This is the complete list of members for stdex::iconverter< T_from, T_to >, including all inherited members.

- - + + + + +
add() (defined in UnitTests::math)UnitTests::mathinlinestatic
mul() (defined in UnitTests::math)UnitTests::mathinlinestatic
convert(std::basic_string< T_to > &dst, _In_reads_or_z_opt_(count) const T_from *src, size_t count_src) const (defined in stdex::iconverter< T_from, T_to >)stdex::iconverter< T_from, T_to >inline
iconverter(charset_id from, charset_id to) (defined in stdex::iconverter< T_from, T_to >)stdex::iconverter< T_from, T_to >inline
m_handle (defined in stdex::iconverter< T_from, T_to >)stdex::iconverter< T_from, T_to >protected
to_encoding(charset_id charset) (defined in stdex::iconverter< T_from, T_to >)stdex::iconverter< T_from, T_to >inlineprotectedstatic
~iconverter() (defined in stdex::iconverter< T_from, T_to >)stdex::iconverter< T_from, T_to >inline
diff --git a/classstdex_1_1iconverter.html b/classstdex_1_1iconverter.html new file mode 100644 index 000000000..06938f8c8 --- /dev/null +++ b/classstdex_1_1iconverter.html @@ -0,0 +1,124 @@ + + + + + + + +stdex: stdex::iconverter< T_from, T_to > Class Template Reference + + + + + + + + + +
+
+ + + + + + +
+
stdex +
+
Additional custom or not Standard C++ covered algorithms
+
+
+ + + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
+Public Member Functions | +Static Protected Member Functions | +Protected Attributes | +List of all members
+
stdex::iconverter< T_from, T_to > Class Template Reference
+
+
+ +

Unicode converter context. + More...

+ +

#include <stdex/unicode.hpp>

+ + + + + + +

+Public Member Functions

iconverter (charset_id from, charset_id to)
 
+void convert (std::basic_string< T_to > &dst, _In_reads_or_z_opt_(count) const T_from *src, size_t count_src) const
 
+ + + +

+Static Protected Member Functions

+static const char * to_encoding (charset_id charset)
 
+ + + +

+Protected Attributes

+iconv_t m_handle
 
+

Detailed Description

+
template<typename T_from, typename T_to>
+class stdex::iconverter< T_from, T_to >

Unicode converter context.

+

The documentation for this class was generated from the following file: +
+ + + + diff --git a/classstdex_1_1idrec_1_1record-members.html b/classstdex_1_1idrec_1_1record-members.html index 3f888d2b5..518ec19b2 100644 --- a/classstdex_1_1idrec_1_1record-members.html +++ b/classstdex_1_1idrec_1_1record-members.html @@ -94,7 +94,7 @@ $(function() { diff --git a/classstdex_1_1idrec_1_1record.html b/classstdex_1_1idrec_1_1record.html index 79302ca6b..e40a77d1e 100644 --- a/classstdex_1_1idrec_1_1record.html +++ b/classstdex_1_1idrec_1_1record.html @@ -526,7 +526,7 @@ template<class T , class T_ID , const T_ID ID, class T_SIZE , unsigned int AL diff --git a/classstdex_1_1lazy__progress-members.html b/classstdex_1_1lazy__progress-members.html index e088b9ce7..9ec5f2330 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 2b8adf869..5ef83e1af 100644 --- a/classstdex_1_1lazy__progress.html +++ b/classstdex_1_1lazy__progress.html @@ -279,7 +279,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__angle-members.html b/classstdex_1_1parser_1_1basic__angle-members.html index 2f80f1f06..7fb7e9136 100644 --- a/classstdex_1_1parser_1_1basic__angle-members.html +++ b/classstdex_1_1parser_1_1basic__angle-members.html @@ -99,7 +99,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__angle.html b/classstdex_1_1parser_1_1basic__angle.html index 7a5cba5a5..72890b352 100644 --- a/classstdex_1_1parser_1_1basic__angle.html +++ b/classstdex_1_1parser_1_1basic__angle.html @@ -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 c62407e3a..430115a82 100644 --- a/classstdex_1_1parser_1_1basic__any__cu-members.html +++ b/classstdex_1_1parser_1_1basic__any__cu-members.html @@ -92,7 +92,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__any__cu.html b/classstdex_1_1parser_1_1basic__any__cu.html index e680bfb42..d3fd88479 100644 --- a/classstdex_1_1parser_1_1basic__any__cu.html +++ b/classstdex_1_1parser_1_1basic__any__cu.html @@ -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 b0faa3b6f..23e9c44d7 100644 --- a/classstdex_1_1parser_1_1basic__bol-members.html +++ b/classstdex_1_1parser_1_1basic__bol-members.html @@ -93,7 +93,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__bol.html b/classstdex_1_1parser_1_1basic__bol.html index d1ee9997b..b384fdbe6 100644 --- a/classstdex_1_1parser_1_1basic__bol.html +++ b/classstdex_1_1parser_1_1basic__bol.html @@ -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 e8a571ec3..608c13a75 100644 --- a/classstdex_1_1parser_1_1basic__branch-members.html +++ b/classstdex_1_1parser_1_1basic__branch-members.html @@ -99,7 +99,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__branch.html b/classstdex_1_1parser_1_1basic__branch.html index 55da18356..45ccd98c5 100644 --- a/classstdex_1_1parser_1_1basic__branch.html +++ b/classstdex_1_1parser_1_1basic__branch.html @@ -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 73cd122af..397191254 100644 --- a/classstdex_1_1parser_1_1basic__chemical__formula-members.html +++ b/classstdex_1_1parser_1_1basic__chemical__formula-members.html @@ -97,7 +97,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__chemical__formula.html b/classstdex_1_1parser_1_1basic__chemical__formula.html index cb533ddd8..40b828283 100644 --- a/classstdex_1_1parser_1_1basic__chemical__formula.html +++ b/classstdex_1_1parser_1_1basic__chemical__formula.html @@ -239,7 +239,7 @@ template<clas diff --git a/classstdex_1_1parser_1_1basic__cu-members.html b/classstdex_1_1parser_1_1basic__cu-members.html index aedf4c6c3..9bce8dcbe 100644 --- a/classstdex_1_1parser_1_1basic__cu-members.html +++ b/classstdex_1_1parser_1_1basic__cu-members.html @@ -94,7 +94,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__cu.html b/classstdex_1_1parser_1_1basic__cu.html index e27cacf06..9bd0db6fc 100644 --- a/classstdex_1_1parser_1_1basic__cu.html +++ b/classstdex_1_1parser_1_1basic__cu.html @@ -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 641261fa3..1eba121e8 100644 --- a/classstdex_1_1parser_1_1basic__cu__set-members.html +++ b/classstdex_1_1parser_1_1basic__cu__set-members.html @@ -96,7 +96,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__cu__set.html b/classstdex_1_1parser_1_1basic__cu__set.html index e40305847..582b06d57 100644 --- a/classstdex_1_1parser_1_1basic__cu__set.html +++ b/classstdex_1_1parser_1_1basic__cu__set.html @@ -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 08549ca79..2b022df36 100644 --- a/classstdex_1_1parser_1_1basic__date-members.html +++ b/classstdex_1_1parser_1_1basic__date-members.html @@ -100,7 +100,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__date.html b/classstdex_1_1parser_1_1basic__date.html index f2c942ef8..b4962e8ba 100644 --- a/classstdex_1_1parser_1_1basic__date.html +++ b/classstdex_1_1parser_1_1basic__date.html @@ -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 131e543ee..d387af5f6 100644 --- a/classstdex_1_1parser_1_1basic__dns__domain__char-members.html +++ b/classstdex_1_1parser_1_1basic__dns__domain__char-members.html @@ -94,7 +94,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__dns__domain__char.html b/classstdex_1_1parser_1_1basic__dns__domain__char.html index 32d905d3d..a78cc83ba 100644 --- a/classstdex_1_1parser_1_1basic__dns__domain__char.html +++ b/classstdex_1_1parser_1_1basic__dns__domain__char.html @@ -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 149a66aba..746068c19 100644 --- a/classstdex_1_1parser_1_1basic__dns__name-members.html +++ b/classstdex_1_1parser_1_1basic__dns__name-members.html @@ -95,7 +95,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__dns__name.html b/classstdex_1_1parser_1_1basic__dns__name.html index fe725a259..8cfd8dc28 100644 --- a/classstdex_1_1parser_1_1basic__dns__name.html +++ b/classstdex_1_1parser_1_1basic__dns__name.html @@ -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 6cc323364..cac61648d 100644 --- a/classstdex_1_1parser_1_1basic__email__address-members.html +++ b/classstdex_1_1parser_1_1basic__email__address-members.html @@ -99,7 +99,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__email__address.html b/classstdex_1_1parser_1_1basic__email__address.html index 2986fa3dd..76fc73f4f 100644 --- a/classstdex_1_1parser_1_1basic__email__address.html +++ b/classstdex_1_1parser_1_1basic__email__address.html @@ -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 1d0cd3b06..d8c252349 100644 --- a/classstdex_1_1parser_1_1basic__emoticon-members.html +++ b/classstdex_1_1parser_1_1basic__emoticon-members.html @@ -97,7 +97,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__emoticon.html b/classstdex_1_1parser_1_1basic__emoticon.html index 1bc9fad96..374c4651f 100644 --- a/classstdex_1_1parser_1_1basic__emoticon.html +++ b/classstdex_1_1parser_1_1basic__emoticon.html @@ -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 838fa78d2..670d9ee99 100644 --- a/classstdex_1_1parser_1_1basic__eol-members.html +++ b/classstdex_1_1parser_1_1basic__eol-members.html @@ -93,7 +93,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__eol.html b/classstdex_1_1parser_1_1basic__eol.html index 36ebca9a8..e6980c6ab 100644 --- a/classstdex_1_1parser_1_1basic__eol.html +++ b/classstdex_1_1parser_1_1basic__eol.html @@ -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 e6d8d5459..99d804d66 100644 --- a/classstdex_1_1parser_1_1basic__fraction-members.html +++ b/classstdex_1_1parser_1_1basic__fraction-members.html @@ -95,7 +95,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__fraction.html b/classstdex_1_1parser_1_1basic__fraction.html index ab8aba3b1..21b88c54b 100644 --- a/classstdex_1_1parser_1_1basic__fraction.html +++ b/classstdex_1_1parser_1_1basic__fraction.html @@ -232,7 +232,7 @@ template<clas diff --git a/classstdex_1_1parser_1_1basic__integer-members.html b/classstdex_1_1parser_1_1basic__integer-members.html index b8fb90930..e253aec04 100644 --- a/classstdex_1_1parser_1_1basic__integer-members.html +++ b/classstdex_1_1parser_1_1basic__integer-members.html @@ -93,7 +93,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__integer.html b/classstdex_1_1parser_1_1basic__integer.html index ad4ec72e1..471f39176 100644 --- a/classstdex_1_1parser_1_1basic__integer.html +++ b/classstdex_1_1parser_1_1basic__integer.html @@ -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 885c190eb..c01b39068 100644 --- a/classstdex_1_1parser_1_1basic__integer10-members.html +++ b/classstdex_1_1parser_1_1basic__integer10-members.html @@ -104,7 +104,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__integer10.html b/classstdex_1_1parser_1_1basic__integer10.html index 323ba95b2..624d585e7 100644 --- a/classstdex_1_1parser_1_1basic__integer10.html +++ b/classstdex_1_1parser_1_1basic__integer10.html @@ -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 46814ce22..5994797c3 100644 --- a/classstdex_1_1parser_1_1basic__integer10ts-members.html +++ b/classstdex_1_1parser_1_1basic__integer10ts-members.html @@ -98,7 +98,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__integer10ts.html b/classstdex_1_1parser_1_1basic__integer10ts.html index 74575d281..6db39c481 100644 --- a/classstdex_1_1parser_1_1basic__integer10ts.html +++ b/classstdex_1_1parser_1_1basic__integer10ts.html @@ -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 06f6be6b6..0cd2c5961 100644 --- a/classstdex_1_1parser_1_1basic__integer16-members.html +++ b/classstdex_1_1parser_1_1basic__integer16-members.html @@ -110,7 +110,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__integer16.html b/classstdex_1_1parser_1_1basic__integer16.html index a4980f7c7..365559569 100644 --- a/classstdex_1_1parser_1_1basic__integer16.html +++ b/classstdex_1_1parser_1_1basic__integer16.html @@ -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 391242ceb..c62f526f5 100644 --- a/classstdex_1_1parser_1_1basic__ipv4__address-members.html +++ b/classstdex_1_1parser_1_1basic__ipv4__address-members.html @@ -105,7 +105,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__ipv4__address.html b/classstdex_1_1parser_1_1basic__ipv4__address.html index 068b6ab84..c6ffb0365 100644 --- a/classstdex_1_1parser_1_1basic__ipv4__address.html +++ b/classstdex_1_1parser_1_1basic__ipv4__address.html @@ -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 91fee6ab0..5c28e260f 100644 --- a/classstdex_1_1parser_1_1basic__ipv6__address-members.html +++ b/classstdex_1_1parser_1_1basic__ipv6__address-members.html @@ -113,7 +113,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__ipv6__address.html b/classstdex_1_1parser_1_1basic__ipv6__address.html index bd84ea9d4..a17b14d3b 100644 --- a/classstdex_1_1parser_1_1basic__ipv6__address.html +++ b/classstdex_1_1parser_1_1basic__ipv6__address.html @@ -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 c0a315a9b..f79e5c9c6 100644 --- a/classstdex_1_1parser_1_1basic__ipv6__scope__id__char-members.html +++ b/classstdex_1_1parser_1_1basic__ipv6__scope__id__char-members.html @@ -92,7 +92,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__ipv6__scope__id__char.html b/classstdex_1_1parser_1_1basic__ipv6__scope__id__char.html index 9c0d903d1..9b0d6b34a 100644 --- a/classstdex_1_1parser_1_1basic__ipv6__scope__id__char.html +++ b/classstdex_1_1parser_1_1basic__ipv6__scope__id__char.html @@ -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 945b777b7..afc965d3a 100644 --- a/classstdex_1_1parser_1_1basic__iterations-members.html +++ b/classstdex_1_1parser_1_1basic__iterations-members.html @@ -96,7 +96,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__iterations.html b/classstdex_1_1parser_1_1basic__iterations.html index 4a074b2b0..0d62c6759 100644 --- a/classstdex_1_1parser_1_1basic__iterations.html +++ b/classstdex_1_1parser_1_1basic__iterations.html @@ -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 e4f123403..3889b50f0 100644 --- a/classstdex_1_1parser_1_1basic__json__string-members.html +++ b/classstdex_1_1parser_1_1basic__json__string-members.html @@ -104,7 +104,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__json__string.html b/classstdex_1_1parser_1_1basic__json__string.html index aa6ce86d5..df8c44bc8 100644 --- a/classstdex_1_1parser_1_1basic__json__string.html +++ b/classstdex_1_1parser_1_1basic__json__string.html @@ -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 9c9eaecf2..dc76e6419 100644 --- a/classstdex_1_1parser_1_1basic__mixed__numeral-members.html +++ b/classstdex_1_1parser_1_1basic__mixed__numeral-members.html @@ -98,7 +98,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__mixed__numeral.html b/classstdex_1_1parser_1_1basic__mixed__numeral.html index cb468d5cd..63d642600 100644 --- a/classstdex_1_1parser_1_1basic__mixed__numeral.html +++ b/classstdex_1_1parser_1_1basic__mixed__numeral.html @@ -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 8b7255d21..95f70a0fe 100644 --- a/classstdex_1_1parser_1_1basic__monetary__numeral-members.html +++ b/classstdex_1_1parser_1_1basic__monetary__numeral-members.html @@ -99,7 +99,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__monetary__numeral.html b/classstdex_1_1parser_1_1basic__monetary__numeral.html index dfb5f7ad1..d7365c1f7 100644 --- a/classstdex_1_1parser_1_1basic__monetary__numeral.html +++ b/classstdex_1_1parser_1_1basic__monetary__numeral.html @@ -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 660e1932e..61feb8a24 100644 --- a/classstdex_1_1parser_1_1basic__noop-members.html +++ b/classstdex_1_1parser_1_1basic__noop-members.html @@ -91,7 +91,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__noop.html b/classstdex_1_1parser_1_1basic__noop.html index 46962bda1..9dea005d4 100644 --- a/classstdex_1_1parser_1_1basic__noop.html +++ b/classstdex_1_1parser_1_1basic__noop.html @@ -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 5f84aa6f4..bfcfd1460 100644 --- a/classstdex_1_1parser_1_1basic__parser-members.html +++ b/classstdex_1_1parser_1_1basic__parser-members.html @@ -91,7 +91,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__parser.html b/classstdex_1_1parser_1_1basic__parser.html index 9f0d3ae1e..a9d401bc4 100644 --- a/classstdex_1_1parser_1_1basic__parser.html +++ b/classstdex_1_1parser_1_1basic__parser.html @@ -183,7 +183,7 @@ class stdex::parser::basic_parser< T >

Base template for all parse

diff --git a/classstdex_1_1parser_1_1basic__permutation-members.html b/classstdex_1_1parser_1_1basic__permutation-members.html index 174576b7c..8eb401ad1 100644 --- a/classstdex_1_1parser_1_1basic__permutation-members.html +++ b/classstdex_1_1parser_1_1basic__permutation-members.html @@ -98,7 +98,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__permutation.html b/classstdex_1_1parser_1_1basic__permutation.html index 06335f31e..40697a462 100644 --- a/classstdex_1_1parser_1_1basic__permutation.html +++ b/classstdex_1_1parser_1_1basic__permutation.html @@ -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 7a74454d2..27a6de76b 100644 --- a/classstdex_1_1parser_1_1basic__phone__number-members.html +++ b/classstdex_1_1parser_1_1basic__phone__number-members.html @@ -99,7 +99,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__phone__number.html b/classstdex_1_1parser_1_1basic__phone__number.html index 8aaa236bb..90a9155a1 100644 --- a/classstdex_1_1parser_1_1basic__phone__number.html +++ b/classstdex_1_1parser_1_1basic__phone__number.html @@ -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 4784e0eda..bd407210f 100644 --- a/classstdex_1_1parser_1_1basic__punct__cu-members.html +++ b/classstdex_1_1parser_1_1basic__punct__cu-members.html @@ -93,7 +93,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__punct__cu.html b/classstdex_1_1parser_1_1basic__punct__cu.html index bb8fa42b4..8927c78c5 100644 --- a/classstdex_1_1parser_1_1basic__punct__cu.html +++ b/classstdex_1_1parser_1_1basic__punct__cu.html @@ -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 c7890e737..6301d2033 100644 --- a/classstdex_1_1parser_1_1basic__roman__numeral-members.html +++ b/classstdex_1_1parser_1_1basic__roman__numeral-members.html @@ -103,7 +103,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__roman__numeral.html b/classstdex_1_1parser_1_1basic__roman__numeral.html index 447c4e6bb..a2fd01677 100644 --- a/classstdex_1_1parser_1_1basic__roman__numeral.html +++ b/classstdex_1_1parser_1_1basic__roman__numeral.html @@ -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 a8fc84b00..d6a93f7a7 100644 --- a/classstdex_1_1parser_1_1basic__scientific__numeral-members.html +++ b/classstdex_1_1parser_1_1basic__scientific__numeral-members.html @@ -103,7 +103,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__scientific__numeral.html b/classstdex_1_1parser_1_1basic__scientific__numeral.html index c0f163e65..f81a07f2b 100644 --- a/classstdex_1_1parser_1_1basic__scientific__numeral.html +++ b/classstdex_1_1parser_1_1basic__scientific__numeral.html @@ -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 d85c67efb..7e9038494 100644 --- a/classstdex_1_1parser_1_1basic__score-members.html +++ b/classstdex_1_1parser_1_1basic__score-members.html @@ -96,7 +96,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__score.html b/classstdex_1_1parser_1_1basic__score.html index c92842270..70e3b9e09 100644 --- a/classstdex_1_1parser_1_1basic__score.html +++ b/classstdex_1_1parser_1_1basic__score.html @@ -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 26edc4331..8772090a8 100644 --- a/classstdex_1_1parser_1_1basic__sequence-members.html +++ b/classstdex_1_1parser_1_1basic__sequence-members.html @@ -97,7 +97,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__sequence.html b/classstdex_1_1parser_1_1basic__sequence.html index 7b80381f9..bfcae405b 100644 --- a/classstdex_1_1parser_1_1basic__sequence.html +++ b/classstdex_1_1parser_1_1basic__sequence.html @@ -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 9afccc9cf..490684d01 100644 --- a/classstdex_1_1parser_1_1basic__set-members.html +++ b/classstdex_1_1parser_1_1basic__set-members.html @@ -94,7 +94,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__set.html b/classstdex_1_1parser_1_1basic__set.html index 0147c2280..b565d0129 100644 --- a/classstdex_1_1parser_1_1basic__set.html +++ b/classstdex_1_1parser_1_1basic__set.html @@ -223,7 +223,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 04d2b4aea..866cd004a 100644 --- a/classstdex_1_1parser_1_1basic__signed__numeral-members.html +++ b/classstdex_1_1parser_1_1basic__signed__numeral-members.html @@ -96,7 +96,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__signed__numeral.html b/classstdex_1_1parser_1_1basic__signed__numeral.html index abb815b6a..e826444a4 100644 --- a/classstdex_1_1parser_1_1basic__signed__numeral.html +++ b/classstdex_1_1parser_1_1basic__signed__numeral.html @@ -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 c8d1da77a..05516ccc7 100644 --- a/classstdex_1_1parser_1_1basic__space__cu-members.html +++ b/classstdex_1_1parser_1_1basic__space__cu-members.html @@ -93,7 +93,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__space__cu.html b/classstdex_1_1parser_1_1basic__space__cu.html index 1556c4b9a..b58dec1bb 100644 --- a/classstdex_1_1parser_1_1basic__space__cu.html +++ b/classstdex_1_1parser_1_1basic__space__cu.html @@ -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 1dc79731c..31f215401 100644 --- a/classstdex_1_1parser_1_1basic__space__or__punct__cu-members.html +++ b/classstdex_1_1parser_1_1basic__space__or__punct__cu-members.html @@ -93,7 +93,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__space__or__punct__cu.html b/classstdex_1_1parser_1_1basic__space__or__punct__cu.html index adbfe0647..075366cec 100644 --- a/classstdex_1_1parser_1_1basic__space__or__punct__cu.html +++ b/classstdex_1_1parser_1_1basic__space__or__punct__cu.html @@ -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 5a4d74d3d..35a023766 100644 --- a/classstdex_1_1parser_1_1basic__string-members.html +++ b/classstdex_1_1parser_1_1basic__string-members.html @@ -93,7 +93,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__string.html b/classstdex_1_1parser_1_1basic__string.html index 182ab2a3d..b83d60c7f 100644 --- a/classstdex_1_1parser_1_1basic__string.html +++ b/classstdex_1_1parser_1_1basic__string.html @@ -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 68854e376..b8ff49c9b 100644 --- a/classstdex_1_1parser_1_1basic__string__branch-members.html +++ b/classstdex_1_1parser_1_1basic__string__branch-members.html @@ -104,7 +104,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__string__branch.html b/classstdex_1_1parser_1_1basic__string__branch.html index d10cd5ef4..ca4252d7c 100644 --- a/classstdex_1_1parser_1_1basic__string__branch.html +++ b/classstdex_1_1parser_1_1basic__string__branch.html @@ -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 88303e0a3..787201ea2 100644 --- a/classstdex_1_1parser_1_1basic__time-members.html +++ b/classstdex_1_1parser_1_1basic__time-members.html @@ -98,7 +98,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__time.html b/classstdex_1_1parser_1_1basic__time.html index 2a65c6748..2a2049171 100644 --- a/classstdex_1_1parser_1_1basic__time.html +++ b/classstdex_1_1parser_1_1basic__time.html @@ -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 779e26548..d8b4db4cb 100644 --- a/classstdex_1_1parser_1_1basic__url-members.html +++ b/classstdex_1_1parser_1_1basic__url-members.html @@ -108,7 +108,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__url.html b/classstdex_1_1parser_1_1basic__url.html index 0eebb27ba..45727a13c 100644 --- a/classstdex_1_1parser_1_1basic__url.html +++ b/classstdex_1_1parser_1_1basic__url.html @@ -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 1c4554916..42d87e969 100644 --- a/classstdex_1_1parser_1_1basic__url__password__char-members.html +++ b/classstdex_1_1parser_1_1basic__url__password__char-members.html @@ -92,7 +92,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__url__password__char.html b/classstdex_1_1parser_1_1basic__url__password__char.html index b65b20467..132fb1e7c 100644 --- a/classstdex_1_1parser_1_1basic__url__password__char.html +++ b/classstdex_1_1parser_1_1basic__url__password__char.html @@ -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 726740867..1ae692672 100644 --- a/classstdex_1_1parser_1_1basic__url__path-members.html +++ b/classstdex_1_1parser_1_1basic__url__path-members.html @@ -98,7 +98,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__url__path.html b/classstdex_1_1parser_1_1basic__url__path.html index 67e1aab25..146bfd317 100644 --- a/classstdex_1_1parser_1_1basic__url__path.html +++ b/classstdex_1_1parser_1_1basic__url__path.html @@ -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 c9ac61379..da2e9417d 100644 --- a/classstdex_1_1parser_1_1basic__url__path__char-members.html +++ b/classstdex_1_1parser_1_1basic__url__path__char-members.html @@ -92,7 +92,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__url__path__char.html b/classstdex_1_1parser_1_1basic__url__path__char.html index 07ed07455..4998b942c 100644 --- a/classstdex_1_1parser_1_1basic__url__path__char.html +++ b/classstdex_1_1parser_1_1basic__url__path__char.html @@ -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 ded2b8311..beb546c33 100644 --- a/classstdex_1_1parser_1_1basic__url__username__char-members.html +++ b/classstdex_1_1parser_1_1basic__url__username__char-members.html @@ -92,7 +92,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__url__username__char.html b/classstdex_1_1parser_1_1basic__url__username__char.html index e4a7f79c5..722ecf5f8 100644 --- a/classstdex_1_1parser_1_1basic__url__username__char.html +++ b/classstdex_1_1parser_1_1basic__url__username__char.html @@ -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 03ab2cca6..323bae245 100644 --- a/classstdex_1_1parser_1_1http__agent-members.html +++ b/classstdex_1_1parser_1_1http__agent-members.html @@ -88,7 +88,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__agent.html b/classstdex_1_1parser_1_1http__agent.html index 7350b02e1..7cf7a312d 100644 --- a/classstdex_1_1parser_1_1http__agent.html +++ b/classstdex_1_1parser_1_1http__agent.html @@ -220,7 +220,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1http__any__type-members.html b/classstdex_1_1parser_1_1http__any__type-members.html index b7ac84f56..b9567278a 100644 --- a/classstdex_1_1parser_1_1http__any__type-members.html +++ b/classstdex_1_1parser_1_1http__any__type-members.html @@ -85,7 +85,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__any__type.html b/classstdex_1_1parser_1_1http__any__type.html index b920dfb95..6a00e609b 100644 --- a/classstdex_1_1parser_1_1http__any__type.html +++ b/classstdex_1_1parser_1_1http__any__type.html @@ -184,7 +184,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1http__asterisk-members.html b/classstdex_1_1parser_1_1http__asterisk-members.html index 75fae1497..d2ce8bb2e 100644 --- a/classstdex_1_1parser_1_1http__asterisk-members.html +++ b/classstdex_1_1parser_1_1http__asterisk-members.html @@ -85,7 +85,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__asterisk.html b/classstdex_1_1parser_1_1http__asterisk.html index 474081ec3..1c2d578c1 100644 --- a/classstdex_1_1parser_1_1http__asterisk.html +++ b/classstdex_1_1parser_1_1http__asterisk.html @@ -184,7 +184,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1http__cookie-members.html b/classstdex_1_1parser_1_1http__cookie-members.html index 8bda9040e..9962b6837 100644 --- a/classstdex_1_1parser_1_1http__cookie-members.html +++ b/classstdex_1_1parser_1_1http__cookie-members.html @@ -90,7 +90,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__cookie.html b/classstdex_1_1parser_1_1http__cookie.html index 363f8d92d..48b7bdee4 100644 --- a/classstdex_1_1parser_1_1http__cookie.html +++ b/classstdex_1_1parser_1_1http__cookie.html @@ -230,7 +230,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1http__cookie__parameter-members.html b/classstdex_1_1parser_1_1http__cookie__parameter-members.html index b46e76983..6961dfcc6 100644 --- a/classstdex_1_1parser_1_1http__cookie__parameter-members.html +++ b/classstdex_1_1parser_1_1http__cookie__parameter-members.html @@ -89,7 +89,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__cookie__parameter.html b/classstdex_1_1parser_1_1http__cookie__parameter.html index c6d832082..ff163ae24 100644 --- a/classstdex_1_1parser_1_1http__cookie__parameter.html +++ b/classstdex_1_1parser_1_1http__cookie__parameter.html @@ -224,7 +224,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1http__header-members.html b/classstdex_1_1parser_1_1http__header-members.html index fcde6f2d0..ffd768ddb 100644 --- a/classstdex_1_1parser_1_1http__header-members.html +++ b/classstdex_1_1parser_1_1http__header-members.html @@ -89,7 +89,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__header.html b/classstdex_1_1parser_1_1http__header.html index 21110b589..2f391adee 100644 --- a/classstdex_1_1parser_1_1http__header.html +++ b/classstdex_1_1parser_1_1http__header.html @@ -224,7 +224,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1http__language-members.html b/classstdex_1_1parser_1_1http__language-members.html index 19bf7a4e8..41d875512 100644 --- a/classstdex_1_1parser_1_1http__language-members.html +++ b/classstdex_1_1parser_1_1http__language-members.html @@ -87,7 +87,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__language.html b/classstdex_1_1parser_1_1http__language.html index f8e864a8f..baa28c144 100644 --- a/classstdex_1_1parser_1_1http__language.html +++ b/classstdex_1_1parser_1_1http__language.html @@ -217,7 +217,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1http__line__break-members.html b/classstdex_1_1parser_1_1http__line__break-members.html index d1c64f743..ab7784dfa 100644 --- a/classstdex_1_1parser_1_1http__line__break-members.html +++ b/classstdex_1_1parser_1_1http__line__break-members.html @@ -85,7 +85,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__line__break.html b/classstdex_1_1parser_1_1http__line__break.html index c7cd36e17..e96986294 100644 --- a/classstdex_1_1parser_1_1http__line__break.html +++ b/classstdex_1_1parser_1_1http__line__break.html @@ -184,7 +184,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1http__media__range-members.html b/classstdex_1_1parser_1_1http__media__range-members.html index 391e0c269..e2cd8e22e 100644 --- a/classstdex_1_1parser_1_1http__media__range-members.html +++ b/classstdex_1_1parser_1_1http__media__range-members.html @@ -89,7 +89,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__media__range.html b/classstdex_1_1parser_1_1http__media__range.html index 292fe45d2..d943b6e77 100644 --- a/classstdex_1_1parser_1_1http__media__range.html +++ b/classstdex_1_1parser_1_1http__media__range.html @@ -225,7 +225,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1http__media__type-members.html b/classstdex_1_1parser_1_1http__media__type-members.html index 34e16b347..671066d10 100644 --- a/classstdex_1_1parser_1_1http__media__type-members.html +++ b/classstdex_1_1parser_1_1http__media__type-members.html @@ -90,7 +90,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__media__type.html b/classstdex_1_1parser_1_1http__media__type.html index e627230ed..00d415ff8 100644 --- a/classstdex_1_1parser_1_1http__media__type.html +++ b/classstdex_1_1parser_1_1http__media__type.html @@ -229,7 +229,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1http__parameter-members.html b/classstdex_1_1parser_1_1http__parameter-members.html index 8dedcf8ab..a3ac0a81e 100644 --- a/classstdex_1_1parser_1_1http__parameter-members.html +++ b/classstdex_1_1parser_1_1http__parameter-members.html @@ -89,7 +89,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__parameter.html b/classstdex_1_1parser_1_1http__parameter.html index 236b01833..fbb691b1e 100644 --- a/classstdex_1_1parser_1_1http__parameter.html +++ b/classstdex_1_1parser_1_1http__parameter.html @@ -226,7 +226,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1http__protocol-members.html b/classstdex_1_1parser_1_1http__protocol-members.html index 1112180e8..f750c420a 100644 --- a/classstdex_1_1parser_1_1http__protocol-members.html +++ b/classstdex_1_1parser_1_1http__protocol-members.html @@ -91,7 +91,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__protocol.html b/classstdex_1_1parser_1_1http__protocol.html index 904ada391..eb105df90 100644 --- a/classstdex_1_1parser_1_1http__protocol.html +++ b/classstdex_1_1parser_1_1http__protocol.html @@ -230,7 +230,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1http__quoted__string-members.html b/classstdex_1_1parser_1_1http__quoted__string-members.html index fde8e062e..5b50e1d16 100644 --- a/classstdex_1_1parser_1_1http__quoted__string-members.html +++ b/classstdex_1_1parser_1_1http__quoted__string-members.html @@ -88,7 +88,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__quoted__string.html b/classstdex_1_1parser_1_1http__quoted__string.html index 14854ef67..39bb1f4c5 100644 --- a/classstdex_1_1parser_1_1http__quoted__string.html +++ b/classstdex_1_1parser_1_1http__quoted__string.html @@ -222,7 +222,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1http__request-members.html b/classstdex_1_1parser_1_1http__request-members.html index 00870ad41..d2ff7c1aa 100644 --- a/classstdex_1_1parser_1_1http__request-members.html +++ b/classstdex_1_1parser_1_1http__request-members.html @@ -91,7 +91,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__request.html b/classstdex_1_1parser_1_1http__request.html index 659889962..5e1660310 100644 --- a/classstdex_1_1parser_1_1http__request.html +++ b/classstdex_1_1parser_1_1http__request.html @@ -230,7 +230,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1http__space-members.html b/classstdex_1_1parser_1_1http__space-members.html index 54edbf18b..53b02ae91 100644 --- a/classstdex_1_1parser_1_1http__space-members.html +++ b/classstdex_1_1parser_1_1http__space-members.html @@ -86,7 +86,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__space.html b/classstdex_1_1parser_1_1http__space.html index 3fcdf27a4..9f0b87ea6 100644 --- a/classstdex_1_1parser_1_1http__space.html +++ b/classstdex_1_1parser_1_1http__space.html @@ -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 3f114fccf..b789ac5d3 100644 --- a/classstdex_1_1parser_1_1http__text__char-members.html +++ b/classstdex_1_1parser_1_1http__text__char-members.html @@ -86,7 +86,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__text__char.html b/classstdex_1_1parser_1_1http__text__char.html index da25fccae..3e84df5e7 100644 --- a/classstdex_1_1parser_1_1http__text__char.html +++ b/classstdex_1_1parser_1_1http__text__char.html @@ -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 f4c2532b6..4aa67f89f 100644 --- a/classstdex_1_1parser_1_1http__token-members.html +++ b/classstdex_1_1parser_1_1http__token-members.html @@ -85,7 +85,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__token.html b/classstdex_1_1parser_1_1http__token.html index 7bdb3d995..8c91bc419 100644 --- a/classstdex_1_1parser_1_1http__token.html +++ b/classstdex_1_1parser_1_1http__token.html @@ -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 d0de70588..bb82e1e80 100644 --- a/classstdex_1_1parser_1_1http__url-members.html +++ b/classstdex_1_1parser_1_1http__url-members.html @@ -91,7 +91,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__url.html b/classstdex_1_1parser_1_1http__url.html index bc9de84ba..ca8495642 100644 --- a/classstdex_1_1parser_1_1http__url.html +++ b/classstdex_1_1parser_1_1http__url.html @@ -229,7 +229,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1http__url__parameter-members.html b/classstdex_1_1parser_1_1http__url__parameter-members.html index 1ca2176dd..327923b9f 100644 --- a/classstdex_1_1parser_1_1http__url__parameter-members.html +++ b/classstdex_1_1parser_1_1http__url__parameter-members.html @@ -88,7 +88,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__url__parameter.html b/classstdex_1_1parser_1_1http__url__parameter.html index 6123d4910..aeab08059 100644 --- a/classstdex_1_1parser_1_1http__url__parameter.html +++ b/classstdex_1_1parser_1_1http__url__parameter.html @@ -220,7 +220,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1http__url__path-members.html b/classstdex_1_1parser_1_1http__url__path-members.html index 3bca64aa1..63d77511d 100644 --- a/classstdex_1_1parser_1_1http__url__path-members.html +++ b/classstdex_1_1parser_1_1http__url__path-members.html @@ -87,7 +87,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__url__path.html b/classstdex_1_1parser_1_1http__url__path.html index e4fc78fe7..5ee9baa50 100644 --- a/classstdex_1_1parser_1_1http__url__path.html +++ b/classstdex_1_1parser_1_1http__url__path.html @@ -218,7 +218,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1http__url__path__segment-members.html b/classstdex_1_1parser_1_1http__url__path__segment-members.html index e5a6258dc..c113bf7e0 100644 --- a/classstdex_1_1parser_1_1http__url__path__segment-members.html +++ b/classstdex_1_1parser_1_1http__url__path__segment-members.html @@ -85,7 +85,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__url__path__segment.html b/classstdex_1_1parser_1_1http__url__path__segment.html index 3d86adfd3..ec5c78bcc 100644 --- a/classstdex_1_1parser_1_1http__url__path__segment.html +++ b/classstdex_1_1parser_1_1http__url__path__segment.html @@ -184,7 +184,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1http__url__port-members.html b/classstdex_1_1parser_1_1http__url__port-members.html index c3576e2f7..d941c010e 100644 --- a/classstdex_1_1parser_1_1http__url__port-members.html +++ b/classstdex_1_1parser_1_1http__url__port-members.html @@ -88,7 +88,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__url__port.html b/classstdex_1_1parser_1_1http__url__port.html index afc842704..c872fee6e 100644 --- a/classstdex_1_1parser_1_1http__url__port.html +++ b/classstdex_1_1parser_1_1http__url__port.html @@ -220,7 +220,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1http__url__server-members.html b/classstdex_1_1parser_1_1http__url__server-members.html index e37f41646..7327031db 100644 --- a/classstdex_1_1parser_1_1http__url__server-members.html +++ b/classstdex_1_1parser_1_1http__url__server-members.html @@ -85,7 +85,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__url__server.html b/classstdex_1_1parser_1_1http__url__server.html index 2efd4edc0..9cdce5725 100644 --- a/classstdex_1_1parser_1_1http__url__server.html +++ b/classstdex_1_1parser_1_1http__url__server.html @@ -184,7 +184,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1http__value-members.html b/classstdex_1_1parser_1_1http__value-members.html index a195daa3a..dbd711f15 100644 --- a/classstdex_1_1parser_1_1http__value-members.html +++ b/classstdex_1_1parser_1_1http__value-members.html @@ -88,7 +88,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__value.html b/classstdex_1_1parser_1_1http__value.html index e6f9ad5c0..4aaad3976 100644 --- a/classstdex_1_1parser_1_1http__value.html +++ b/classstdex_1_1parser_1_1http__value.html @@ -222,7 +222,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1http__value__collection-members.html b/classstdex_1_1parser_1_1http__value__collection-members.html index 398aa1082..027ff3ad5 100644 --- a/classstdex_1_1parser_1_1http__value__collection-members.html +++ b/classstdex_1_1parser_1_1http__value__collection-members.html @@ -74,17 +74,17 @@ $(function() {
-
stdex::parser::http_value_collection< T > Member List
+
stdex::parser::http_value_collection< _Key, T > Member List
-

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

+

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

- +
insert(_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_collection< T >)stdex::parser::http_value_collection< T >inline
insert(_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_collection< _Key, T >)stdex::parser::http_value_collection< _Key, T >inline
diff --git a/classstdex_1_1parser_1_1http__value__collection.html b/classstdex_1_1parser_1_1http__value__collection.html index b5459379a..c87d61ba9 100644 --- a/classstdex_1_1parser_1_1http__value__collection.html +++ b/classstdex_1_1parser_1_1http__value__collection.html @@ -5,7 +5,7 @@ -stdex: stdex::parser::http_value_collection< T > Class Template Reference +stdex: stdex::parser::http_value_collection< _Key, T > Class Template Reference @@ -77,7 +77,7 @@ $(function() {
Public Member Functions | List of all members
-
stdex::parser::http_value_collection< T > Class Template Reference
+
stdex::parser::http_value_collection< _Key, T > Class Template Reference
@@ -86,7 +86,7 @@ $(function() {

#include <stdex/parser.hpp>

-Inheritance diagram for stdex::parser::http_value_collection< T >:
+Inheritance diagram for stdex::parser::http_value_collection< _Key, T >:
@@ -94,20 +94,20 @@ Inheritance diagram for stdex::parser::http_value_collection< T >:
- - +

Public Member Functions

+
void insert (_In_reads_or_z_(end) const char *text, size_t start=0, size_t end=(size_t) -1, int flags=match_default)
 
 

Detailed Description

-
template<class T>
-class stdex::parser::http_value_collection< T >

Collection of HTTP values.

+
template<class _Key, class T>
+class stdex::parser::http_value_collection< _Key, T >

Collection of HTTP values.


The documentation for this class was generated from the following file:
diff --git a/classstdex_1_1parser_1_1http__value__collection.png b/classstdex_1_1parser_1_1http__value__collection.png index e76f9bedc..4a75a9fb2 100644 Binary files a/classstdex_1_1parser_1_1http__value__collection.png and b/classstdex_1_1parser_1_1http__value__collection.png differ diff --git a/classstdex_1_1parser_1_1http__weight-members.html b/classstdex_1_1parser_1_1http__weight-members.html index 59f4c9384..c49c8598d 100644 --- a/classstdex_1_1parser_1_1http__weight-members.html +++ b/classstdex_1_1parser_1_1http__weight-members.html @@ -88,7 +88,7 @@ $(function() {
diff --git a/classstdex_1_1parser_1_1http__weight.html b/classstdex_1_1parser_1_1http__weight.html index f9ce2e2f9..4ae1fdcaf 100644 --- a/classstdex_1_1parser_1_1http__weight.html +++ b/classstdex_1_1parser_1_1http__weight.html @@ -221,7 +221,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1http__weighted__value-members.html b/classstdex_1_1parser_1_1http__weighted__value-members.html index 24c49512d..c9dc77799 100644 --- a/classstdex_1_1parser_1_1http__weighted__value-members.html +++ b/classstdex_1_1parser_1_1http__weighted__value-members.html @@ -90,7 +90,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__weighted__value.html b/classstdex_1_1parser_1_1http__weighted__value.html index 8b9341a7f..365469f8c 100644 --- a/classstdex_1_1parser_1_1http__weighted__value.html +++ b/classstdex_1_1parser_1_1http__weighted__value.html @@ -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 210860798..f2bda46a8 100644 --- a/classstdex_1_1parser_1_1parser__collection-members.html +++ b/classstdex_1_1parser_1_1parser__collection-members.html @@ -95,7 +95,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1parser__collection.html b/classstdex_1_1parser_1_1parser__collection.html index 67db442c9..6fb011a25 100644 --- a/classstdex_1_1parser_1_1parser__collection.html +++ b/classstdex_1_1parser_1_1parser__collection.html @@ -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 4f674a247..b5480b819 100644 --- a/classstdex_1_1parser_1_1sgml__any__cp-members.html +++ b/classstdex_1_1parser_1_1sgml__any__cp-members.html @@ -93,7 +93,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1sgml__any__cp.html b/classstdex_1_1parser_1_1sgml__any__cp.html index 5ecacea1f..40cb60fe0 100644 --- a/classstdex_1_1parser_1_1sgml__any__cp.html +++ b/classstdex_1_1parser_1_1sgml__any__cp.html @@ -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 f6b5e45e4..9913ac391 100644 --- a/classstdex_1_1parser_1_1sgml__cp-members.html +++ b/classstdex_1_1parser_1_1sgml__cp-members.html @@ -88,7 +88,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1sgml__cp.html b/classstdex_1_1parser_1_1sgml__cp.html index e14ff3da7..dc71900f9 100644 --- a/classstdex_1_1parser_1_1sgml__cp.html +++ b/classstdex_1_1parser_1_1sgml__cp.html @@ -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 eeecfe088..7c68ec069 100644 --- a/classstdex_1_1parser_1_1sgml__cp__set-members.html +++ b/classstdex_1_1parser_1_1sgml__cp__set-members.html @@ -93,7 +93,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1sgml__cp__set.html b/classstdex_1_1parser_1_1sgml__cp__set.html index 084a91577..798940abf 100644 --- a/classstdex_1_1parser_1_1sgml__cp__set.html +++ b/classstdex_1_1parser_1_1sgml__cp__set.html @@ -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 55bb092cc..98846103a 100644 --- a/classstdex_1_1parser_1_1sgml__dns__domain__char-members.html +++ b/classstdex_1_1parser_1_1sgml__dns__domain__char-members.html @@ -94,7 +94,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1sgml__dns__domain__char.html b/classstdex_1_1parser_1_1sgml__dns__domain__char.html index 265a45a3b..909e7d83e 100644 --- a/classstdex_1_1parser_1_1sgml__dns__domain__char.html +++ b/classstdex_1_1parser_1_1sgml__dns__domain__char.html @@ -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 50233c181..4a95757e3 100644 --- a/classstdex_1_1parser_1_1sgml__ipv6__scope__id__char-members.html +++ b/classstdex_1_1parser_1_1sgml__ipv6__scope__id__char-members.html @@ -86,7 +86,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1sgml__ipv6__scope__id__char.html b/classstdex_1_1parser_1_1sgml__ipv6__scope__id__char.html index ddac5261a..4c98c3840 100644 --- a/classstdex_1_1parser_1_1sgml__ipv6__scope__id__char.html +++ b/classstdex_1_1parser_1_1sgml__ipv6__scope__id__char.html @@ -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 92057bbf9..5a6c0e06e 100644 --- a/classstdex_1_1parser_1_1sgml__punct__cp-members.html +++ b/classstdex_1_1parser_1_1sgml__punct__cp-members.html @@ -93,7 +93,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1sgml__punct__cp.html b/classstdex_1_1parser_1_1sgml__punct__cp.html index 1b576191f..3fc32ac96 100644 --- a/classstdex_1_1parser_1_1sgml__punct__cp.html +++ b/classstdex_1_1parser_1_1sgml__punct__cp.html @@ -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 a9458169a..7a5cad99a 100644 --- a/classstdex_1_1parser_1_1sgml__space__cp-members.html +++ b/classstdex_1_1parser_1_1sgml__space__cp-members.html @@ -93,7 +93,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1sgml__space__cp.html b/classstdex_1_1parser_1_1sgml__space__cp.html index e3702ee36..9565660f7 100644 --- a/classstdex_1_1parser_1_1sgml__space__cp.html +++ b/classstdex_1_1parser_1_1sgml__space__cp.html @@ -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 3aef53f68..b7e2539a8 100644 --- a/classstdex_1_1parser_1_1sgml__space__or__punct__cp-members.html +++ b/classstdex_1_1parser_1_1sgml__space__or__punct__cp-members.html @@ -93,7 +93,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1sgml__space__or__punct__cp.html b/classstdex_1_1parser_1_1sgml__space__or__punct__cp.html index d719707e8..593f2a3a5 100644 --- a/classstdex_1_1parser_1_1sgml__space__or__punct__cp.html +++ b/classstdex_1_1parser_1_1sgml__space__or__punct__cp.html @@ -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 eb79291ff..a0b3e1964 100644 --- a/classstdex_1_1parser_1_1sgml__string-members.html +++ b/classstdex_1_1parser_1_1sgml__string-members.html @@ -87,7 +87,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1sgml__string.html b/classstdex_1_1parser_1_1sgml__string.html index d0982d9db..43b192e12 100644 --- a/classstdex_1_1parser_1_1sgml__string.html +++ b/classstdex_1_1parser_1_1sgml__string.html @@ -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 2eb6c35f7..c26640443 100644 --- a/classstdex_1_1parser_1_1sgml__url__password__char-members.html +++ b/classstdex_1_1parser_1_1sgml__url__password__char-members.html @@ -93,7 +93,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1sgml__url__password__char.html b/classstdex_1_1parser_1_1sgml__url__password__char.html index 565709422..a682e08b7 100644 --- a/classstdex_1_1parser_1_1sgml__url__password__char.html +++ b/classstdex_1_1parser_1_1sgml__url__password__char.html @@ -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 47e46788a..346a6c858 100644 --- a/classstdex_1_1parser_1_1sgml__url__path__char-members.html +++ b/classstdex_1_1parser_1_1sgml__url__path__char-members.html @@ -93,7 +93,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1sgml__url__path__char.html b/classstdex_1_1parser_1_1sgml__url__path__char.html index 005fef29f..52403d2de 100644 --- a/classstdex_1_1parser_1_1sgml__url__path__char.html +++ b/classstdex_1_1parser_1_1sgml__url__path__char.html @@ -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 4b01495fa..4ffbc39b6 100644 --- a/classstdex_1_1parser_1_1sgml__url__username__char-members.html +++ b/classstdex_1_1parser_1_1sgml__url__username__char-members.html @@ -93,7 +93,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1sgml__url__username__char.html b/classstdex_1_1parser_1_1sgml__url__username__char.html index b6753cb93..5e9de689e 100644 --- a/classstdex_1_1parser_1_1sgml__url__username__char.html +++ b/classstdex_1_1parser_1_1sgml__url__username__char.html @@ -196,7 +196,7 @@ std::locale m_locale diff --git a/classstdex_1_1progress-members.html b/classstdex_1_1progress-members.html index b86f72c6f..b5e332548 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 a77458c47..e55b91ebe 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 2799057dc..65114d874 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 2a2398585..30f0b260e 100644 --- a/classstdex_1_1progress__switcher.html +++ b/classstdex_1_1progress__switcher.html @@ -140,9 +140,9 @@ Protected Attributes progress< T > *& m_host_ref   - Protected Attributes inherited from stdex::global_progress< T > - -progressm_host -  + +progress< T > * m_hostinterval< T > m_local   @@ -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 33533546b..226c28b14 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 45a34bf9f..3b0203251 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_1stream_1_1async__reader-members.html b/classstdex_1_1stream_1_1async__reader-members.html index 0e22b8321..e92b4d371 100644 --- a/classstdex_1_1stream_1_1async__reader-members.html +++ b/classstdex_1_1stream_1_1async__reader-members.html @@ -149,7 +149,7 @@ $(function() { diff --git a/classstdex_1_1stream_1_1async__reader.html b/classstdex_1_1stream_1_1async__reader.html index fe700120d..0251a330d 100644 --- a/classstdex_1_1stream_1_1async__reader.html +++ b/classstdex_1_1stream_1_1async__reader.html @@ -390,7 +390,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 ba999ef03..d2304d4fa 100644 --- a/classstdex_1_1stream_1_1async__writer-members.html +++ b/classstdex_1_1stream_1_1async__writer-members.html @@ -149,7 +149,7 @@ $(function() { diff --git a/classstdex_1_1stream_1_1async__writer.html b/classstdex_1_1stream_1_1async__writer.html index 065ec2e7d..68728c309 100644 --- a/classstdex_1_1stream_1_1async__writer.html +++ b/classstdex_1_1stream_1_1async__writer.html @@ -421,7 +421,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 c516ec9ce..f716df1c9 100644 --- a/classstdex_1_1stream_1_1basic-members.html +++ b/classstdex_1_1stream_1_1basic-members.html @@ -139,7 +139,7 @@ $(function() { diff --git a/classstdex_1_1stream_1_1basic.html b/classstdex_1_1stream_1_1basic.html index fcf43c89f..6a44188a7 100644 --- a/classstdex_1_1stream_1_1basic.html +++ b/classstdex_1_1stream_1_1basic.html @@ -1320,7 +1320,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 9d56a970e..66f7ba43e 100644 --- a/classstdex_1_1stream_1_1basic__file-members.html +++ b/classstdex_1_1stream_1_1basic__file-members.html @@ -116,7 +116,7 @@ $(function() { read(_Out_writes_bytes_to_opt_(length, return) void *data, size_t length)stdex::stream::basicinlinevirtual read_array(_Out_writes_bytes_(size *count) void *array, size_t size, size_t count)stdex::stream::basicinline read_byte()stdex::stream::basicinline - read_charset(charset_id default_charset=charset_id::default)stdex::stream::basic_fileinline + read_charset(charset_id default_charset=charset_id::system)stdex::stream::basic_fileinline read_data(T &data)stdex::stream::basicinline read_remainder(size_t max_length=SIZE_MAX)stdex::stream::basic_fileinlinevirtual read_str(std::basic_string< _Elem, _Traits, _Ax > &data)stdex::stream::basicinline @@ -155,7 +155,7 @@ $(function() { diff --git a/classstdex_1_1stream_1_1basic__file.html b/classstdex_1_1stream_1_1basic__file.html index ecc1f824e..22d44e31b 100644 --- a/classstdex_1_1stream_1_1basic__file.html +++ b/classstdex_1_1stream_1_1basic__file.html @@ -154,9 +154,9 @@ Public Member Functions virtual void set_mtime (time_point date)  Sets file modification time.
  -charset_id read_charset (charset_id default_charset=charset_id::default) - Attempts to detect textfile charset based on UTF16 or UTF8 BOM.
-  +charset_id read_charset (charset_id default_charset=charset_id::system) + Attempts to detect textfile charset based on UTF16 or UTF8 BOM.
- Public Member Functions inherited from stdex::stream::basic  basic (state_t state=state_t::ok) @@ -472,8 +472,8 @@ state_t m_state - -

◆ read_charset()

+ +

◆ read_charset()

@@ -485,7 +485,7 @@ state_t m_statecharset_id stdex::stream::basic_file::read_charset ( charset_id  - default_charset = charset_id::default) + default_charset = charset_id::system) @@ -927,7 +927,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 222d1177c..f7d79f999 100644 --- a/classstdex_1_1stream_1_1basic__sys-members.html +++ b/classstdex_1_1stream_1_1basic__sys-members.html @@ -151,7 +151,7 @@ $(function() {
diff --git a/classstdex_1_1stream_1_1basic__sys.html b/classstdex_1_1stream_1_1basic__sys.html index dd73d287e..f611f2ab7 100644 --- a/classstdex_1_1stream_1_1basic__sys.html +++ b/classstdex_1_1stream_1_1basic__sys.html @@ -493,7 +493,7 @@ sys_handle m_h diff --git a/classstdex_1_1stream_1_1buffer-members.html b/classstdex_1_1stream_1_1buffer-members.html index 0eb609a76..e4905022b 100644 --- a/classstdex_1_1stream_1_1buffer-members.html +++ b/classstdex_1_1stream_1_1buffer-members.html @@ -150,7 +150,7 @@ $(function() {
diff --git a/classstdex_1_1stream_1_1buffer.html b/classstdex_1_1stream_1_1buffer.html index 8faadbe0a..e4164b6ed 100644 --- a/classstdex_1_1stream_1_1buffer.html +++ b/classstdex_1_1stream_1_1buffer.html @@ -468,7 +468,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 37cbf88ce..9fcdf691a 100644 --- a/classstdex_1_1stream_1_1buffered__sys-members.html +++ b/classstdex_1_1stream_1_1buffered__sys-members.html @@ -152,7 +152,7 @@ $(function() { diff --git a/classstdex_1_1stream_1_1buffered__sys.html b/classstdex_1_1stream_1_1buffered__sys.html index fa4579889..44790a440 100644 --- a/classstdex_1_1stream_1_1buffered__sys.html +++ b/classstdex_1_1stream_1_1buffered__sys.html @@ -344,7 +344,7 @@ void done () diff --git a/classstdex_1_1stream_1_1cache-members.html b/classstdex_1_1stream_1_1cache-members.html index 4f966c660..e023b8338 100644 --- a/classstdex_1_1stream_1_1cache-members.html +++ b/classstdex_1_1stream_1_1cache-members.html @@ -126,7 +126,7 @@ $(function() { read(_Out_writes_bytes_to_opt_(length, return) void *data, size_t length)stdex::stream::cacheinlinevirtual read_array(_Out_writes_bytes_(size *count) void *array, size_t size, size_t count)stdex::stream::basicinline read_byte()stdex::stream::basicinline - read_charset(charset_id default_charset=charset_id::default)stdex::stream::basic_fileinline + read_charset(charset_id default_charset=charset_id::system)stdex::stream::basic_fileinline read_data(T &data)stdex::stream::basicinline read_remainder(size_t max_length=SIZE_MAX)stdex::stream::basic_fileinlinevirtual read_str(std::basic_string< _Elem, _Traits, _Ax > &data)stdex::stream::basicinline @@ -167,7 +167,7 @@ $(function() { diff --git a/classstdex_1_1stream_1_1cache.html b/classstdex_1_1stream_1_1cache.html index 1e0100335..b4d635178 100644 --- a/classstdex_1_1stream_1_1cache.html +++ b/classstdex_1_1stream_1_1cache.html @@ -174,9 +174,9 @@ Public Member Functions virtual void skip (fsize_t amount)  Skips given amount of bytes of data on the stream.
  -charset_id read_charset (charset_id default_charset=charset_id::default) - Attempts to detect textfile charset based on UTF16 or UTF8 BOM.
-  +charset_id read_charset (charset_id default_charset=charset_id::system) + Attempts to detect textfile charset based on UTF16 or UTF8 BOM.
- Public Member Functions inherited from stdex::stream::basic  basic (state_t state=state_t::ok) @@ -933,7 +933,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 cabb83e25..f5021229f 100644 --- a/classstdex_1_1stream_1_1cached__file-members.html +++ b/classstdex_1_1stream_1_1cached__file-members.html @@ -129,7 +129,7 @@ $(function() { read(_Out_writes_bytes_to_opt_(length, return) void *data, size_t length)stdex::stream::cacheinlinevirtual read_array(_Out_writes_bytes_(size *count) void *array, size_t size, size_t count)stdex::stream::basicinline read_byte()stdex::stream::basicinline - read_charset(charset_id default_charset=charset_id::default)stdex::stream::basic_fileinline + read_charset(charset_id default_charset=charset_id::system)stdex::stream::basic_fileinline read_data(T &data)stdex::stream::basicinline read_remainder(size_t max_length=SIZE_MAX)stdex::stream::basic_fileinlinevirtual read_str(std::basic_string< _Elem, _Traits, _Ax > &data)stdex::stream::basicinline @@ -171,7 +171,7 @@ $(function() { diff --git a/classstdex_1_1stream_1_1cached__file.html b/classstdex_1_1stream_1_1cached__file.html index bb3d9cec9..6f1775a7d 100644 --- a/classstdex_1_1stream_1_1cached__file.html +++ b/classstdex_1_1stream_1_1cached__file.html @@ -177,9 +177,9 @@ Public Member Functions virtual void skip (fsize_t amount)  Skips given amount of bytes of data on the stream.
  -charset_id read_charset (charset_id default_charset=charset_id::default) - Attempts to detect textfile charset based on UTF16 or UTF8 BOM.
-  +charset_id read_charset (charset_id default_charset=charset_id::system) + Attempts to detect textfile charset based on UTF16 or UTF8 BOM.
- Public Member Functions inherited from stdex::stream::basic  basic (state_t state=state_t::ok) @@ -487,7 +487,6 @@ void write_cache () [in]filenameFilename [in]modeBitwise combination of mode_t flags - [in]cache_sizeSize of the cache block @@ -500,7 +499,7 @@ void write_cache () diff --git a/classstdex_1_1stream_1_1converter-members.html b/classstdex_1_1stream_1_1converter-members.html index d24f32441..dccd97c38 100644 --- a/classstdex_1_1stream_1_1converter-members.html +++ b/classstdex_1_1stream_1_1converter-members.html @@ -144,7 +144,7 @@ $(function() { diff --git a/classstdex_1_1stream_1_1converter.html b/classstdex_1_1stream_1_1converter.html index bb706e2fd..84e0d7cad 100644 --- a/classstdex_1_1stream_1_1converter.html +++ b/classstdex_1_1stream_1_1converter.html @@ -480,7 +480,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 2161af017..bb2920b96 100644 --- a/classstdex_1_1stream_1_1diag__file-members.html +++ b/classstdex_1_1stream_1_1diag__file-members.html @@ -119,7 +119,7 @@ $(function() { read(_Out_writes_bytes_to_opt_(length, return) void *data, size_t length)stdex::stream::diag_fileinlinevirtual read_array(_Out_writes_bytes_(size *count) void *array, size_t size, size_t count)stdex::stream::basicinline read_byte()stdex::stream::basicinline - read_charset(charset_id default_charset=charset_id::default)stdex::stream::basic_fileinline + read_charset(charset_id default_charset=charset_id::system)stdex::stream::basic_fileinline read_data(T &data)stdex::stream::basicinline read_remainder(size_t max_length=SIZE_MAX)stdex::stream::basic_fileinlinevirtual read_str(std::basic_string< _Elem, _Traits, _Ax > &data)stdex::stream::basicinline @@ -158,7 +158,7 @@ $(function() { diff --git a/classstdex_1_1stream_1_1diag__file.html b/classstdex_1_1stream_1_1diag__file.html index 3b5d56b55..d465f5698 100644 --- a/classstdex_1_1stream_1_1diag__file.html +++ b/classstdex_1_1stream_1_1diag__file.html @@ -166,9 +166,9 @@ Public Member Functions virtual void set_mtime (time_point date)  Sets file modification time.
  -charset_id read_charset (charset_id default_charset=charset_id::default) - Attempts to detect textfile charset based on UTF16 or UTF8 BOM.
-  +charset_id read_charset (charset_id default_charset=charset_id::system) + Attempts to detect textfile charset based on UTF16 or UTF8 BOM.
- Public Member Functions inherited from stdex::stream::basic  basic (state_t state=state_t::ok) @@ -720,7 +720,7 @@ state_t m_state diff --git a/classstdex_1_1stream_1_1fifo-members.html b/classstdex_1_1stream_1_1fifo-members.html index 20765eaab..0a6a039ff 100644 --- a/classstdex_1_1stream_1_1fifo-members.html +++ b/classstdex_1_1stream_1_1fifo-members.html @@ -146,7 +146,7 @@ $(function() { diff --git a/classstdex_1_1stream_1_1fifo.html b/classstdex_1_1stream_1_1fifo.html index 3f45e3dd7..dc0c0df5c 100644 --- a/classstdex_1_1stream_1_1fifo.html +++ b/classstdex_1_1stream_1_1fifo.html @@ -445,7 +445,7 @@ state_t m_state diff --git a/classstdex_1_1stream_1_1file-members.html b/classstdex_1_1stream_1_1file-members.html index 8eb574a01..6c0fec0da 100644 --- a/classstdex_1_1stream_1_1file-members.html +++ b/classstdex_1_1stream_1_1file-members.html @@ -130,7 +130,7 @@ $(function() { stdex::stream::basic_sys::read(_Out_writes_bytes_to_opt_(length, return) void *data, size_t length)stdex::stream::basic_sysinlinevirtual read_array(_Out_writes_bytes_(size *count) void *array, size_t size, size_t count)stdex::stream::basicinline read_byte()stdex::stream::basicinline - read_charset(charset_id default_charset=charset_id::default)stdex::stream::basic_fileinline + read_charset(charset_id default_charset=charset_id::system)stdex::stream::basic_fileinline read_data(T &data)stdex::stream::basicinline read_remainder(size_t max_length=SIZE_MAX)stdex::stream::basic_fileinlinevirtual read_str(std::basic_string< _Elem, _Traits, _Ax > &data)stdex::stream::basicinline @@ -174,7 +174,7 @@ $(function() { diff --git a/classstdex_1_1stream_1_1file.html b/classstdex_1_1stream_1_1file.html index 45f06a063..aaa6af4d1 100644 --- a/classstdex_1_1stream_1_1file.html +++ b/classstdex_1_1stream_1_1file.html @@ -162,9 +162,9 @@ Public Member Functions virtual void skip (fsize_t amount)  Skips given amount of bytes of data on the stream.
  -charset_id read_charset (charset_id default_charset=charset_id::default) - Attempts to detect textfile charset based on UTF16 or UTF8 BOM.
-  +charset_id read_charset (charset_id default_charset=charset_id::system) + Attempts to detect textfile charset based on UTF16 or UTF8 BOM.
- Public Member Functions inherited from stdex::stream::basic  basic (state_t state=state_t::ok) @@ -877,7 +877,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 e77e66a3b..3a7aedfcb 100644 --- a/classstdex_1_1stream_1_1file__window-members.html +++ b/classstdex_1_1stream_1_1file__window-members.html @@ -120,7 +120,7 @@ $(function() { read(_Out_writes_bytes_to_opt_(length, return) void *data, size_t length)stdex::stream::file_windowinlinevirtual read_array(_Out_writes_bytes_(size *count) void *array, size_t size, size_t count)stdex::stream::basicinline read_byte()stdex::stream::basicinline - read_charset(charset_id default_charset=charset_id::default)stdex::stream::basic_fileinline + read_charset(charset_id default_charset=charset_id::system)stdex::stream::basic_fileinline read_data(T &data)stdex::stream::basicinline read_remainder(size_t max_length=SIZE_MAX)stdex::stream::basic_fileinlinevirtual read_str(std::basic_string< _Elem, _Traits, _Ax > &data)stdex::stream::basicinline @@ -159,7 +159,7 @@ $(function() { diff --git a/classstdex_1_1stream_1_1file__window.html b/classstdex_1_1stream_1_1file__window.html index c3a15bc90..0a7a6dee6 100644 --- a/classstdex_1_1stream_1_1file__window.html +++ b/classstdex_1_1stream_1_1file__window.html @@ -166,9 +166,9 @@ Public Member Functions virtual void set_mtime (time_point date)  Sets file modification time.
  -charset_id read_charset (charset_id default_charset=charset_id::default) - Attempts to detect textfile charset based on UTF16 or UTF8 BOM.
-  +charset_id read_charset (charset_id default_charset=charset_id::system) + Attempts to detect textfile charset based on UTF16 or UTF8 BOM.
- Public Member Functions inherited from stdex::stream::basic  basic (state_t state=state_t::ok) @@ -753,7 +753,7 @@ state_t m_state diff --git a/classstdex_1_1stream_1_1limiter-members.html b/classstdex_1_1stream_1_1limiter-members.html index 8df3f0646..42471a1a6 100644 --- a/classstdex_1_1stream_1_1limiter-members.html +++ b/classstdex_1_1stream_1_1limiter-members.html @@ -147,7 +147,7 @@ $(function() { diff --git a/classstdex_1_1stream_1_1limiter.html b/classstdex_1_1stream_1_1limiter.html index 7399e7d73..19500f7d1 100644 --- a/classstdex_1_1stream_1_1limiter.html +++ b/classstdex_1_1stream_1_1limiter.html @@ -429,7 +429,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 424ed1a57..c30118b8f 100644 --- a/classstdex_1_1stream_1_1memory__file-members.html +++ b/classstdex_1_1stream_1_1memory__file-members.html @@ -140,7 +140,7 @@ $(function() { read(_Out_writes_bytes_to_opt_(length, return) void *data, size_t length)stdex::stream::memory_fileinlinevirtual read_array(_Out_writes_bytes_(size *count) void *array, size_t size, size_t count)stdex::stream::basicinline read_byte()stdex::stream::basicinline - read_charset(charset_id default_charset=charset_id::default)stdex::stream::basic_fileinline + read_charset(charset_id default_charset=charset_id::system)stdex::stream::basic_fileinline read_data(T &data)stdex::stream::memory_fileinline read_remainder(size_t max_length=SIZE_MAX)stdex::stream::basic_fileinlinevirtual read_str(std::basic_string< _Elem, _Traits, _Ax > &data)stdex::stream::memory_fileinline @@ -196,7 +196,7 @@ $(function() { diff --git a/classstdex_1_1stream_1_1memory__file.html b/classstdex_1_1stream_1_1memory__file.html index 9be0f2881..9125912c0 100644 --- a/classstdex_1_1stream_1_1memory__file.html +++ b/classstdex_1_1stream_1_1memory__file.html @@ -352,9 +352,9 @@ template<class _Elem , class _Traits = std::char_traits<_Elem>, class virtual void set_mtime (time_point date)  Sets file modification time.
  -charset_id read_charset (charset_id default_charset=charset_id::default) - Attempts to detect textfile charset based on UTF16 or UTF8 BOM.
-  +charset_id read_charset (charset_id default_charset=charset_id::system) + Attempts to detect textfile charset based on UTF16 or UTF8 BOM.
- Public Member Functions inherited from stdex::stream::basic  basic (state_t state=state_t::ok) @@ -1465,7 +1465,7 @@ template<class T > diff --git a/classstdex_1_1stream_1_1replicator-members.html b/classstdex_1_1stream_1_1replicator-members.html index a13d7bcdd..ce7fe3dca 100644 --- a/classstdex_1_1stream_1_1replicator-members.html +++ b/classstdex_1_1stream_1_1replicator-members.html @@ -144,7 +144,7 @@ $(function() { diff --git a/classstdex_1_1stream_1_1replicator.html b/classstdex_1_1stream_1_1replicator.html index 76a98bc7a..939219e06 100644 --- a/classstdex_1_1stream_1_1replicator.html +++ b/classstdex_1_1stream_1_1replicator.html @@ -428,7 +428,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 687d4c550..77095053e 100644 --- a/classstdex_1_1stream_1_1replicator_1_1worker-members.html +++ b/classstdex_1_1stream_1_1replicator_1_1worker-members.html @@ -94,7 +94,7 @@ $(function() { diff --git a/classstdex_1_1stream_1_1replicator_1_1worker.html b/classstdex_1_1stream_1_1replicator_1_1worker.html index 584d571ee..55b470058 100644 --- a/classstdex_1_1stream_1_1replicator_1_1worker.html +++ b/classstdex_1_1stream_1_1replicator_1_1worker.html @@ -146,7 +146,7 @@ static void process_op diff --git a/classstdex_1_1stream_1_1window-members.html b/classstdex_1_1stream_1_1window-members.html index ecb098db4..693c38161 100644 --- a/classstdex_1_1stream_1_1window-members.html +++ b/classstdex_1_1stream_1_1window-members.html @@ -150,7 +150,7 @@ $(function() { diff --git a/classstdex_1_1stream_1_1window.html b/classstdex_1_1stream_1_1window.html index 828997f48..3298f4129 100644 --- a/classstdex_1_1stream_1_1window.html +++ b/classstdex_1_1stream_1_1window.html @@ -438,7 +438,7 @@ state_t m_state diff --git a/classstdex_1_1sys__object-members.html b/classstdex_1_1sys__object-members.html index 489a14860..7248b3c14 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 dcffd5912..61718a617 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 3d57cdd45..b86a8ac2c 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 0bd3edb2e..b6869412a 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_1user__cancelled.png b/classstdex_1_1user__cancelled.png index ffb5ebb8c..b2f069569 100644 Binary files a/classstdex_1_1user__cancelled.png and b/classstdex_1_1user__cancelled.png differ diff --git a/classstdex_1_1vector__queue-members.html b/classstdex_1_1vector__queue-members.html index 0eadc07a7..98f327e8d 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 11d31b751..09ec3c6fb 100644 --- a/classstdex_1_1vector__queue.html +++ b/classstdex_1_1vector__queue.html @@ -795,7 +795,7 @@ template<class T > diff --git a/common_8hpp_source.html b/common_8hpp_source.html deleted file mode 100644 index 54581c357..000000000 --- a/common_8hpp_source.html +++ /dev/null @@ -1,109 +0,0 @@ - - - - - - - -stdex: mac/UnitTests/common.hpp Source File - - - - - - - - - -
-
- - - - - - -
-
stdex -
-
Additional custom or not Standard C++ covered algorithms
-
-
- - - - - - - - - -
-
- - -
-
-
-
-
-
Loading...
-
Searching...
-
No Matches
-
-
-
-
- - -
-
-
common.hpp
-
-
-
1#pragma once
-
2
-
3#include <stdexcept>
-
4
-
5template <class T>
-
6void are_equal(const T& a, const T& b)
-
7{
-
8 if (!(a == b))
-
9 throw std::runtime_error("values are not equal");
-
10}
-
11
-
12template <class E, typename F>
-
13void expect_exception(F functor)
-
14{
-
15 try { functor(); }
-
16 catch (const E&) { return; }
-
17 throw std::runtime_error("exception expected");
-
18}
-
- - - - diff --git a/dir_2ac391ad55c056cf22300c181fd83614.html b/dir_2ac391ad55c056cf22300c181fd83614.html deleted file mode 100644 index 63122ecb8..000000000 --- a/dir_2ac391ad55c056cf22300c181fd83614.html +++ /dev/null @@ -1,92 +0,0 @@ - - - - - - - -stdex: mac Directory Reference - - - - - - - - - -
-
- - - - - - -
-
stdex -
-
Additional custom or not Standard C++ covered algorithms
-
-
- - - - - - - - -
-
- - -
-
-
-
-
-
Loading...
-
Searching...
-
No Matches
-
-
-
-
- - -
-
-
mac Directory Reference
-
-
- - - - -

-Directories

 UnitTests
 
-
- - - - diff --git a/dir_3da88de5f21f7abfb7840f289699aa66.html b/dir_3da88de5f21f7abfb7840f289699aa66.html deleted file mode 100644 index 7bd666d3b..000000000 --- a/dir_3da88de5f21f7abfb7840f289699aa66.html +++ /dev/null @@ -1,92 +0,0 @@ - - - - - - - -stdex: win Directory Reference - - - - - - - - - -
-
- - - - - - -
-
stdex -
-
Additional custom or not Standard C++ covered algorithms
-
-
- - - - - - - - -
-
- - -
-
-
-
-
-
Loading...
-
Searching...
-
No Matches
-
-
-
-
- - -
-
-
win Directory Reference
-
-
- - - - -

-Directories

 UnitTests
 
-
- - - - diff --git a/dir_43ee741e58281fecf80b971e8185276f.html b/dir_4be4f7b278e009bf0f1906cf31fb73bd.html similarity index 61% rename from dir_43ee741e58281fecf80b971e8185276f.html rename to dir_4be4f7b278e009bf0f1906cf31fb73bd.html index e21b57af2..b2921a475 100644 --- a/dir_43ee741e58281fecf80b971e8185276f.html +++ b/dir_4be4f7b278e009bf0f1906cf31fb73bd.html @@ -5,7 +5,7 @@ -stdex: mac/UnitTests Directory Reference +stdex: UnitTests Directory Reference @@ -70,7 +70,7 @@ $(function() {
@@ -80,15 +80,27 @@ $(function() { - + - + + + + + + + + + + + + +

Files

 common.hpp
 compat.hpp
 
 math.hpp
 math.cpp
 
 parser.cpp
 
 pch.h
 
 ring.cpp
 
 sgml.cpp
 
 stream.cpp
 
 unicode.cpp
 
diff --git a/dir_64495783006fc1014e5552143894ce30.html b/dir_64495783006fc1014e5552143894ce30.html deleted file mode 100644 index 42b399eda..000000000 --- a/dir_64495783006fc1014e5552143894ce30.html +++ /dev/null @@ -1,92 +0,0 @@ - - - - - - - -stdex: win/UnitTests Directory Reference - - - - - - - - - -
-
- - - - - - -
-
stdex -
-
Additional custom or not Standard C++ covered algorithms
-
-
- - - - - - - - -
-
- - -
-
-
-
-
-
Loading...
-
Searching...
-
No Matches
-
-
-
-
- - -
-
-
UnitTests Directory Reference
-
-
- - - - -

-Files

 pch.h
 
-
- - - - diff --git a/dir_d44c64559bbebec7f509842c48db8b23.html b/dir_d44c64559bbebec7f509842c48db8b23.html index c136c51fb..0caab544a 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 b8afbbbdc..ef040ece1 100644 --- a/dir_fca3c47b2ea228727bd6729832f89576.html +++ b/dir_fca3c47b2ea228727bd6729832f89576.html @@ -84,6 +84,8 @@ Files    chrono.hpp   + compat.hpp endian.hpp    errno.hpp @@ -98,7 +100,7 @@ Files    mapping.hpp   - math.hpp + math.hpp    memory.hpp   @@ -108,8 +110,6 @@ Files    ring.hpp   - sal.hpp sgml.hpp    sgml_unicode.hpp @@ -128,7 +128,7 @@ Files diff --git a/endian_8hpp_source.html b/endian_8hpp_source.html index e4f515b00..b03f0df7a 100644 --- a/endian_8hpp_source.html +++ b/endian_8hpp_source.html @@ -89,105 +89,134 @@ $(document).ready(function() { init_codefold(0); });
5
6#pragma once
7
-
8#include "sal.hpp"
+
8#include "compat.hpp"
9#include "system.hpp"
10#include <assert.h>
11#include <stdint.h>
12
-
13#ifdef _WIN32
-
14#if REG_DWORD == REG_DWORD_LITTLE_ENDIAN
-
15#elif REG_DWORD == REG_DWORD_BIG_ENDIAN
-
16#define BIG_ENDIAN
-
17#else
-
18#error Unknown endian
-
19#endif
-
20#else
-
21#include <endian.h>
-
22#if __BYTE_ORDER == __LITTLE_ENDIAN
-
23#elif __BYTE_ORDER == __BIG_ENDIAN
-
24#define BIG_ENDIAN
-
25#else
-
26#error Unknown endian
-
27#endif
-
28#endif
-
29
-
30namespace stdex
-
31{
-
32 inline uint16_t byteswap(_In_ const uint16_t value)
-
33 {
-
34 #if _MSC_VER >= 1300
-
35 return _byteswap_ushort(value);
-
36 #elif defined(_MSC_VER)
-
37 uint16_t t = (value & 0x00ff) << 8;
-
38 t |= (value) >> 8;
-
39 return t;
-
40 #else
-
41 return __builtin_bswap16(value);
-
42 #endif
-
43 }
+
13#ifndef LITTLE_ENDIAN
+
14#define LITTLE_ENDIAN 1234
+
15#endif
+
16#ifndef BIG_ENDIAN
+
17#define BIG_ENDIAN 4321
+
18#endif
+
19#ifndef BYTE_ORDER
+
20#if defined(_WIN32)
+
21#if REG_DWORD == REG_DWORD_LITTLE_ENDIAN
+
22#define BYTE_ORDER LITTLE_ENDIAN
+
23#elif REG_DWORD == REG_DWORD_BIG_ENDIAN
+
24#define BYTE_ORDER BIG_ENDIAN
+
25#endif
+
26#elif defined(__APPLE__)
+
27#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+
28#define BYTE_ORDER LITTLE_ENDIAN
+
29#elif __BYTE_ORDER == __ORDER_BIG_ENDIAN__
+
30#define BYTE_ORDER BIG_ENDIAN
+
31#endif
+
32#else
+
33#include <endian.h>
+
34#if __BYTE_ORDER == __LITTLE_ENDIAN
+
35#define BYTE_ORDER LITTLE_ENDIAN
+
36#elif __BYTE_ORDER == __BIG_ENDIAN
+
37#define BYTE_ORDER BIG_ENDIAN
+
38#endif
+
39#endif
+
40#ifndef BYTE_ORDER
+
41#error Unknown endian
+
42#endif
+
43#endif
44
-
45 inline uint32_t byteswap(_In_ const uint32_t value)
-
46 {
-
47 #if _MSC_VER >= 1300
-
48 return _byteswap_ulong(value);
-
49 #elif defined(_MSC_VER)
-
50 uint32_t t = (value & 0x000000ff) << 24;
-
51 t |= (value & 0x0000ff00) << 8;
-
52 t |= (value & 0x00ff0000) >> 8;
-
53 t |= (value) >> 24;
-
54 return t;
-
55 #else
-
56 return __builtin_bswap32(value);
-
57 #endif
-
58 }
-
59
-
60 inline uint64_t byteswap(_In_ const uint64_t value)
-
61 {
-
62 #if _MSC_VER >= 1300
-
63 return _byteswap_uint64(value);
-
64 #elif defined(_MSC_VER)
-
65 uint64_t t = (value & 0x00000000000000ff) << 56;
-
66 t |= (value & 0x000000000000ff00) << 40;
-
67 t |= (value & 0x0000000000ff0000) << 24;
-
68 t |= (value & 0x00000000ff000000) << 8;
-
69 t |= (value & 0x000000ff00000000) >> 8;
-
70 t |= (value & 0x0000ff0000000000) >> 24;
-
71 t |= (value & 0x00ff000000000000) >> 40;
-
72 t |= (value) >> 56;
-
73 return t;
-
74 #else
-
75 return __builtin_bswap64(value);
-
76 #endif
-
77 }
-
78
-
79 inline int16_t byteswap(_In_ const int16_t value) { return byteswap((uint16_t)value); }
-
80 inline int32_t byteswap(_In_ const int32_t value) { return byteswap((uint32_t)value); }
-
81 inline int64_t byteswap(_In_ const int64_t value) { return byteswap((uint64_t)value); }
-
82
-
83 inline void byteswap(_Inout_ uint16_t* value) { assert(value); *value = byteswap(*value); }
-
84 inline void byteswap(_Inout_ uint32_t* value) { assert(value); *value = byteswap(*value); }
-
85 inline void byteswap(_Inout_ uint64_t* value) { assert(value); *value = byteswap(*value); }
-
86
-
87 inline void byteswap(_Inout_ int16_t* value) { byteswap((uint16_t*)value); }
-
88 inline void byteswap(_Inout_ int32_t* value) { byteswap((uint32_t*)value); }
-
89 inline void byteswap(_Inout_ int64_t* value) { byteswap((uint64_t*)value); }
-
90}
-
91
-
92#ifdef BIG_ENDIAN
-
93#define LE2HE(x) stdex::byteswap(x)
-
94#define BE2HE(x) (x)
-
95#define HE2LE(x) stdex::byteswap(x)
-
96#define HE2BE(x) (x)
-
97#else
-
98#define LE2HE(x) (x)
-
99#define BE2HE(x) stdex::byteswap(x)
-
100#define HE2LE(x) (x)
-
101#define HE2BE(x) stdex::byteswap(x)
-
102#endif
+
45namespace stdex
+
46{
+
47 inline uint8_t byteswap(_In_ const uint8_t value)
+
48 {
+
49 return value;
+
50 }
+
51
+
52 inline uint16_t byteswap(_In_ const uint16_t value)
+
53 {
+
54#if _MSC_VER >= 1300
+
55 return _byteswap_ushort(value);
+
56#elif defined(_MSC_VER)
+
57 uint16_t t = (value & 0x00ff) << 8;
+
58 t |= (value) >> 8;
+
59 return t;
+
60#else
+
61 return __builtin_bswap16(value);
+
62#endif
+
63 }
+
64
+
65 inline uint32_t byteswap(_In_ const uint32_t value)
+
66 {
+
67#if _MSC_VER >= 1300
+
68 return _byteswap_ulong(value);
+
69#elif defined(_MSC_VER)
+
70 uint32_t t = (value & 0x000000ff) << 24;
+
71 t |= (value & 0x0000ff00) << 8;
+
72 t |= (value & 0x00ff0000) >> 8;
+
73 t |= (value) >> 24;
+
74 return t;
+
75#else
+
76 return __builtin_bswap32(value);
+
77#endif
+
78 }
+
79
+
80 inline uint64_t byteswap(_In_ const uint64_t value)
+
81 {
+
82#if _MSC_VER >= 1300
+
83 return _byteswap_uint64(value);
+
84#elif defined(_MSC_VER)
+
85 uint64_t t = (value & 0x00000000000000ff) << 56;
+
86 t |= (value & 0x000000000000ff00) << 40;
+
87 t |= (value & 0x0000000000ff0000) << 24;
+
88 t |= (value & 0x00000000ff000000) << 8;
+
89 t |= (value & 0x000000ff00000000) >> 8;
+
90 t |= (value & 0x0000ff0000000000) >> 24;
+
91 t |= (value & 0x00ff000000000000) >> 40;
+
92 t |= (value) >> 56;
+
93 return t;
+
94#else
+
95 return __builtin_bswap64(value);
+
96#endif
+
97 }
+
98
+
99 inline int8_t byteswap(_In_ const char value) { return byteswap(static_cast<uint8_t>(value)); }
+
100 inline int8_t byteswap(_In_ const int8_t value) { return byteswap(static_cast<uint8_t>(value)); }
+
101 inline int16_t byteswap(_In_ const int16_t value) { return byteswap(static_cast<uint16_t>(value)); }
+
102 inline int32_t byteswap(_In_ const int32_t value) { return byteswap(static_cast<uint32_t>(value)); }
+
103 inline int64_t byteswap(_In_ const int64_t value) { return byteswap(static_cast<uint64_t>(value)); }
+
104 inline float byteswap(_In_ const float value) { return byteswap(*reinterpret_cast<const uint32_t*>(&value)); }
+
105 inline double byteswap(_In_ const double value) { return byteswap(*reinterpret_cast<const uint64_t*>(&value)); }
+
106
+
107 inline void byteswap(_Inout_ uint8_t* value) { assert(value); *value = byteswap(*value); }
+
108 inline void byteswap(_Inout_ uint16_t* value) { assert(value); *value = byteswap(*value); }
+
109 inline void byteswap(_Inout_ uint32_t* value) { assert(value); *value = byteswap(*value); }
+
110 inline void byteswap(_Inout_ uint64_t* value) { assert(value); *value = byteswap(*value); }
+
111
+
112 inline void byteswap(_Inout_ char* value) { byteswap(reinterpret_cast<uint8_t*>(value)); }
+
113 inline void byteswap(_Inout_ int8_t* value) { byteswap(reinterpret_cast<uint8_t*>(value)); }
+
114 inline void byteswap(_Inout_ int16_t* value) { byteswap(reinterpret_cast<uint16_t*>(value)); }
+
115 inline void byteswap(_Inout_ int32_t* value) { byteswap(reinterpret_cast<uint32_t*>(value)); }
+
116 inline void byteswap(_Inout_ int64_t* value) { byteswap(reinterpret_cast<uint64_t*>(value)); }
+
117 inline void byteswap(_Inout_ float* value) { byteswap(reinterpret_cast<uint32_t*>(value)); }
+
118 inline void byteswap(_Inout_ double* value) { byteswap(reinterpret_cast<uint64_t*>(value)); }
+
119}
+
120
+
121#if BYTE_ORDER == BIG_ENDIAN
+
122#define LE2HE(x) stdex::byteswap(x)
+
123#define BE2HE(x) (x)
+
124#define HE2LE(x) stdex::byteswap(x)
+
125#define HE2BE(x) (x)
+
126#else
+
127#define LE2HE(x) (x)
+
128#define BE2HE(x) stdex::byteswap(x)
+
129#define HE2LE(x) (x)
+
130#define HE2BE(x) stdex::byteswap(x)
+
131#endif
diff --git a/errno_8hpp_source.html b/errno_8hpp_source.html index ebae515a4..04f73e406 100644 --- a/errno_8hpp_source.html +++ b/errno_8hpp_source.html @@ -89,7 +89,7 @@ $(document).ready(function() { init_codefold(0); });
5
6#pragma once
7
-
8#include "sal.hpp"
+
8#include "compat.hpp"
9#include <stdexcept>
10#include <cstring>
11
@@ -153,7 +153,7 @@ $(document).ready(function() { init_codefold(0); }); diff --git a/exception_8hpp_source.html b/exception_8hpp_source.html index c3010aaec..3cfd51047 100644 --- a/exception_8hpp_source.html +++ b/exception_8hpp_source.html @@ -89,17 +89,17 @@ $(document).ready(function() { init_codefold(0); });
5
6#pragma once
7
-
8#include "sal.hpp"
+
8#include "compat.hpp"
9#include <exception>
10
11namespace stdex
12{
-
16 class user_cancelled : public std::exception
+
16 class user_cancelled : public std::runtime_error
17 {
18 public:
-
24 user_cancelled(_In_opt_z_ const char *msg = nullptr) : exception(msg)
+
24 user_cancelled(_In_opt_z_ const char *msg = nullptr) : runtime_error(msg)
25 {
26 }
@@ -111,7 +111,7 @@ $(document).ready(function() { init_codefold(0); });
diff --git a/files.html b/files.html index 1046b744b..43d3a3a3e 100644 --- a/files.html +++ b/files.html @@ -79,19 +79,19 @@ $(function() {   stdex  base64.hpp  chrono.hpp - endian.hpp - errno.hpp - exception.hpp - hex.hpp - idrec.hpp - interval.hpp - mapping.hpp - math.hpp - memory.hpp - parser.hpp - progress.hpp - ring.hpp - sal.hpp + compat.hpp + endian.hpp + errno.hpp + exception.hpp + hex.hpp + idrec.hpp + interval.hpp + mapping.hpp + math.hpp + memory.hpp + parser.hpp + progress.hpp + ring.hpp  sgml.hpp  sgml_unicode.hpp  stream.hpp @@ -99,19 +99,21 @@ $(function() {  system.hpp  unicode.hpp  vector_queue.hpp -  mac -  UnitTests - common.hpp - math.hpp -  win -  UnitTests - pch.h +  UnitTests + compat.hpp + math.cpp + parser.cpp + pch.h + ring.cpp + sgml.cpp + stream.cpp + unicode.cpp diff --git a/functions.html b/functions.html index ffbfe19e0..24da5a934 100644 --- a/functions.html +++ b/functions.html @@ -84,7 +84,7 @@ $(function() { diff --git a/functions_b.html b/functions_b.html index de3209b85..02395791b 100644 --- a/functions_b.html +++ b/functions_b.html @@ -81,7 +81,7 @@ $(function() { diff --git a/functions_c.html b/functions_c.html index 50ff31c46..c572501a8 100644 --- a/functions_c.html +++ b/functions_c.html @@ -89,7 +89,7 @@ $(function() { diff --git a/functions_d.html b/functions_d.html index 89d94923d..4e70757fe 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 09aeb5610..69258e694 100644 --- a/functions_e.html +++ b/functions_e.html @@ -86,7 +86,7 @@ $(function() { diff --git a/functions_f.html b/functions_f.html index 89670705d..cc0703a76 100644 --- a/functions_f.html +++ b/functions_f.html @@ -86,7 +86,7 @@ $(function() { diff --git a/functions_func.html b/functions_func.html index 0b44cb633..5e8ca285c 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 606bb70c2..b0ae28052 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 0c4b10a2b..c5f9a8c0d 100644 --- a/functions_func_c.html +++ b/functions_func_c.html @@ -84,7 +84,7 @@ $(function() { diff --git a/functions_func_d.html b/functions_func_d.html index c4adeae3c..7ce512b93 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 5f629088c..4295fba4f 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 f48b39b1c..951d55395 100644 --- a/functions_func_f.html +++ b/functions_func_f.html @@ -85,7 +85,7 @@ $(function() { diff --git a/functions_func_g.html b/functions_func_g.html index 9ead85db9..601d30d24 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 00ae6dcd4..27cc028ca 100644 --- a/functions_func_h.html +++ b/functions_func_h.html @@ -80,7 +80,7 @@ $(function() { diff --git a/functions_func_i.html b/functions_func_i.html index f32e48af6..36fa11f92 100644 --- a/functions_func_i.html +++ b/functions_func_i.html @@ -79,7 +79,7 @@ $(function() { diff --git a/functions_func_l.html b/functions_func_l.html index 5eb73b75c..42f522c12 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 c87285bdf..d4682a793 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 57d18a017..fabd0df4d 100644 --- a/functions_func_n.html +++ b/functions_func_n.html @@ -79,7 +79,7 @@ $(function() { diff --git a/functions_func_o.html b/functions_func_o.html index e41e6b517..34c6b7e7f 100644 --- a/functions_func_o.html +++ b/functions_func_o.html @@ -85,7 +85,7 @@ $(function() { diff --git a/functions_func_p.html b/functions_func_p.html index 70ae2ee07..dce1f327e 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 1e8bbf55f..fe19e20a8 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 0820319dd..be3b51678 100644 --- a/functions_func_r.html +++ b/functions_func_r.html @@ -76,7 +76,7 @@ $(function() {
  • read() : stdex::stream::async_reader< CAPACITY >, stdex::stream::basic, stdex::stream::basic_sys, stdex::stream::buffer, stdex::stream::cache, stdex::stream::converter, stdex::stream::diag_file, stdex::stream::fifo, stdex::stream::file_window, stdex::stream::limiter, stdex::stream::memory_file, stdex::stream::window
  • read_array() : stdex::stream::basic
  • read_byte() : stdex::stream::basic
  • -
  • read_charset() : stdex::stream::basic_file
  • +
  • read_charset() : stdex::stream::basic_file
  • read_data() : stdex::stream::basic, stdex::stream::memory_file
  • read_remainder() : stdex::stream::basic, stdex::stream::basic_file
  • read_str() : stdex::stream::basic, stdex::stream::memory_file
  • @@ -89,7 +89,7 @@ $(function() { diff --git a/functions_func_s.html b/functions_func_s.html index 755374730..88f2aea3e 100644 --- a/functions_func_s.html +++ b/functions_func_s.html @@ -95,7 +95,7 @@ $(function() { diff --git a/functions_func_t.html b/functions_func_t.html index 92d7d2aa5..e0a6d3ee9 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 da0b1bd69..77ba20eb8 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 1ed5c23fa..a3c1f68e5 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 5a2295530..8a26519cd 100644 --- a/functions_func_w.html +++ b/functions_func_w.html @@ -86,7 +86,7 @@ $(function() { diff --git a/functions_func_~.html b/functions_func_~.html index b80e9f66e..429d115b2 100644 --- a/functions_func_~.html +++ b/functions_func_~.html @@ -78,7 +78,7 @@ $(function() { diff --git a/functions_g.html b/functions_g.html index af06f2ae5..fbf7309d8 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 aef25ba04..10f9252b1 100644 --- a/functions_h.html +++ b/functions_h.html @@ -81,7 +81,7 @@ $(function() { diff --git a/functions_i.html b/functions_i.html index 89dad1d62..d74ed402a 100644 --- a/functions_i.html +++ b/functions_i.html @@ -80,7 +80,7 @@ $(function() { diff --git a/functions_l.html b/functions_l.html index 7cf1401d9..4c3da0512 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 ca59f69ab..d0cd6de63 100644 --- a/functions_m.html +++ b/functions_m.html @@ -95,7 +95,7 @@ $(function() { diff --git a/functions_n.html b/functions_n.html index daa303e91..9974e7c6c 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 84f0397cd..3b8ba19d1 100644 --- a/functions_o.html +++ b/functions_o.html @@ -86,7 +86,7 @@ $(function() { diff --git a/functions_p.html b/functions_p.html index 744a5de32..5d203d4a1 100644 --- a/functions_p.html +++ b/functions_p.html @@ -87,7 +87,7 @@ $(function() { diff --git a/functions_q.html b/functions_q.html index 322d152a7..c0093cba6 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 65b05f1c7..b236a0260 100644 --- a/functions_r.html +++ b/functions_r.html @@ -76,7 +76,7 @@ $(function() {
  • read() : stdex::stream::async_reader< CAPACITY >, stdex::stream::basic, stdex::stream::basic_sys, stdex::stream::buffer, stdex::stream::cache, stdex::stream::converter, stdex::stream::diag_file, stdex::stream::fifo, stdex::stream::file_window, stdex::stream::limiter, stdex::stream::memory_file, stdex::stream::window
  • read_array() : stdex::stream::basic
  • read_byte() : stdex::stream::basic
  • -
  • read_charset() : stdex::stream::basic_file
  • +
  • read_charset() : stdex::stream::basic_file
  • read_data() : stdex::stream::basic, stdex::stream::memory_file
  • read_limit : stdex::stream::limiter
  • read_offset : stdex::stream::window
  • @@ -93,7 +93,7 @@ $(function() { diff --git a/functions_s.html b/functions_s.html index 82530d57e..7ebbc621b 100644 --- a/functions_s.html +++ b/functions_s.html @@ -101,7 +101,7 @@ $(function() { diff --git a/functions_t.html b/functions_t.html index 97f1f9d75..49eb30f3e 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 d99e09d70..7a0e0057f 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 8c03943b7..d089901ab 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 bd23967b6..ba8cd86dc 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 f127c6148..a9b95b6f8 100644 --- a/functions_vars.html +++ b/functions_vars.html @@ -204,7 +204,7 @@ $(function() { diff --git a/functions_w.html b/functions_w.html index 01943c379..0a59eb446 100644 --- a/functions_w.html +++ b/functions_w.html @@ -88,7 +88,7 @@ $(function() { diff --git a/functions_~.html b/functions_~.html index b40e005b2..3cadbb096 100644 --- a/functions_~.html +++ b/functions_~.html @@ -78,7 +78,7 @@ $(function() { diff --git a/hex_8hpp_source.html b/hex_8hpp_source.html index cca8336e8..670a24060 100644 --- a/hex_8hpp_source.html +++ b/hex_8hpp_source.html @@ -89,7 +89,7 @@ $(document).ready(function() { init_codefold(0); });
    5
    6#pragma once
    7
    -
    8#include "sal.hpp"
    +
    8#include "compat.hpp"
    9#include <assert.h>
    10#include <cstdint>
    11#include <string>
    @@ -232,7 +232,7 @@ $(document).ready(function() { init_codefold(0); }); diff --git a/hierarchy.html b/hierarchy.html index 181c44b67..68cb6698a 100644 --- a/hierarchy.html +++ b/hierarchy.html @@ -198,41 +198,40 @@ $(function() {  Cstdex::parser::sgml_stringTest for SGML given string  Cstdex::stream::buffer::buffer_t  Cstdex::stream::cache::cache_t - Cstd::exception - Cstdex::user_cancelledUser cancelled exception - Cstdex::free_locale_deleteDeleter for unique_ptr using free_locale - Cstdex::hex_decHexadecimal decoding session - Cstdex::hex_encHexadecimal encoding session - Cstdex::parser::http_factor_more< T > + Cstdex::free_locale_deleteDeleter for unique_ptr using free_locale + Cstdex::hex_decHexadecimal decoding session + Cstdex::hex_encHexadecimal encoding session + Cstdex::parser::http_factor_more< T > + Cstdex::iconverter< T_from, T_to >Unicode converter context  Cstdex::interval< T >Numerical interval  Cstdex::interval< fpos_t >  Cstdex::interval< size_t >  Cstdex::mapping< T >Maps index in source string to index in destination string - CUnitTests::math - Cstdex::no_delete< T >Noop deleter - Cstdex::no_delete< T[]>Noop array deleter - Cstdex::stream::fifo::node_t - Cstdex::progress< T >Progress indicator base class - Cstdex::global_progress< T >Global progress indicator base class - Cstdex::progress_switcher< T >Progress indicator switcher - Cstdex::lazy_progress< T >Lazy progress indicator base class - Cstdex::idrec::record< T, T_ID, ID, T_SIZE, ALIGN >Helper class for read/write of records to/from memory - Cstdex::ring< T, CAPACITY >Ring buffer - Cstdex::ring< uint8_t, default_async_limit > - Cstd::runtime_error - Cstdex::errno_errorStandard C runtime library error - Cstdex::sys_objectOperating system object (file, pipe, anything with an OS handle etc.) - Cstdex::stream::basic_sysOS data stream (file, pipe, socket...) - CT - Cstdex::parser::http_value_collection< T >Collection of HTTP values - Cstdex::vector_queue< T >Helper class to allow limited size FIFO queues implemented as vector of elements - Cstdex::stream::replicator::worker + Cstdex::no_delete< T >Noop deleter + Cstdex::no_delete< T[]>Noop array deleter + Cstdex::stream::fifo::node_t + Cstdex::progress< T >Progress indicator base class + Cstdex::global_progress< T >Global progress indicator base class + Cstdex::progress_switcher< T >Progress indicator switcher + Cstdex::lazy_progress< T >Lazy progress indicator base class + Cstdex::idrec::record< T, T_ID, ID, T_SIZE, ALIGN >Helper class for read/write of records to/from memory + Cstdex::ring< T, CAPACITY >Ring buffer + Cstdex::ring< uint8_t, default_async_limit > + Cstd::runtime_error + Cstdex::errno_errorStandard C runtime library error + Cstdex::user_cancelledUser cancelled exception + Cstdex::sys_objectOperating system object (file, pipe, anything with an OS handle etc.) + Cstdex::stream::basic_sysOS data stream (file, pipe, socket...) + CT + Cstdex::parser::http_value_collection< _Key, T >Collection of HTTP values + Cstdex::vector_queue< T >Helper class to allow limited size FIFO queues implemented as vector of elements + Cstdex::stream::replicator::worker diff --git a/idrec_8hpp_source.html b/idrec_8hpp_source.html index d993d2ebf..4459fdf25 100644 --- a/idrec_8hpp_source.html +++ b/idrec_8hpp_source.html @@ -89,7 +89,7 @@ $(document).ready(function() { init_codefold(0); });
    5
    6#pragma once
    7
    -
    8#include "sal.hpp"
    +
    8#include "compat.hpp"
    9#include "stream.hpp"
    10#include <ios>
    11#include <istream>
    @@ -416,12 +416,12 @@ $(document).ready(function() { init_codefold(0); });
    stdex::idrec::record::find
    static bool find(stdex::stream::basic_file &stream, stdex::stream::foff_t end=stdex::stream::foff_max)
    Finds record data.
    Definition idrec.hpp:392
    stdex::idrec::record::record
    record(const T &d)
    Constructs the class.
    Definition idrec.hpp:294
    stdex::idrec::record::close
    static std::streamoff close(std::ostream &stream, std::streamoff start)
    Updates record header.
    Definition idrec.hpp:349
    -
    stdex::stream::basic_file
    Basic seekable stream operations.
    Definition stream.hpp:695
    -
    stdex::stream::limiter
    Limits reading from/writing to stream to a predefined number of bytes.
    Definition stream.hpp:1413
    +
    stdex::stream::basic_file
    Basic seekable stream operations.
    Definition stream.hpp:696
    +
    stdex::stream::limiter
    Limits reading from/writing to stream to a predefined number of bytes.
    Definition stream.hpp:1415
    diff --git a/include_2stdex_2compat_8hpp_source.html b/include_2stdex_2compat_8hpp_source.html new file mode 100644 index 000000000..fce010792 --- /dev/null +++ b/include_2stdex_2compat_8hpp_source.html @@ -0,0 +1,252 @@ + + + + + + + +stdex: include/stdex/compat.hpp Source File + + + + + + + + + +
    +
    + + + + + + +
    +
    stdex +
    +
    Additional custom or not Standard C++ covered algorithms
    +
    +
    + + + + + + + + + +
    +
    + + +
    +
    +
    +
    +
    +
    Loading...
    +
    Searching...
    +
    No Matches
    +
    +
    +
    +
    + + +
    +
    +
    compat.hpp
    +
    +
    +
    1/*
    +
    2 SPDX-License-Identifier: MIT
    +
    3 Copyright © 2022-2023 Amebis
    +
    4*/
    +
    5
    +
    6#pragma once
    +
    7
    +
    8#include <stddef.h>
    +
    9#ifdef _WIN32
    +
    10#include <sal.h>
    +
    11#endif
    +
    12#include <type_traits>
    +
    13
    +
    14#ifndef _In_
    +
    15#define _In_
    +
    16#endif
    +
    17#ifndef _In_bytecount_
    +
    18#define _In_bytecount_(p)
    +
    19#endif
    +
    20#ifndef _In_count_
    +
    21#define _In_count_(p)
    +
    22#endif
    +
    23#ifndef _In_opt_
    +
    24#define _In_opt_
    +
    25#endif
    +
    26#ifndef _In_opt_count_
    +
    27#define _In_opt_count_(p)
    +
    28#endif
    +
    29#ifndef _In_opt_z_count_
    +
    30#define _In_opt_z_count_(p)
    +
    31#endif
    +
    32#ifndef _In_z_
    +
    33#define _In_z_
    +
    34#endif
    +
    35#ifndef _In_opt_z_
    +
    36#define _In_opt_z_
    +
    37#endif
    +
    38#ifndef _In_z_count_
    +
    39#define _In_z_count_(p)
    +
    40#endif
    +
    41#ifndef _In_reads_
    +
    42#define _In_reads_(p)
    +
    43#endif
    +
    44#ifndef _In_reads_or_z_
    +
    45#define _In_reads_or_z_(p)
    +
    46#endif
    +
    47#ifndef _In_reads_or_z_opt_
    +
    48#define _In_reads_or_z_opt_(p)
    +
    49#endif
    +
    50#ifndef _In_reads_bytes_opt_
    +
    51#define _In_reads_bytes_opt_(p)
    +
    52#endif
    +
    53#ifndef _Printf_format_string_params_
    +
    54#define _Printf_format_string_params_(n)
    +
    55#endif
    +
    56
    +
    57#ifndef _Inout_
    +
    58#define _Inout_
    +
    59#endif
    +
    60#ifndef _Inout_opt_
    +
    61#define _Inout_opt_
    +
    62#endif
    +
    63#ifndef _Inout_cap_
    +
    64#define _Inout_cap_(p)
    +
    65#endif
    +
    66
    +
    67#ifndef _Use_decl_annotations_
    +
    68#define _Use_decl_annotations_
    +
    69#endif
    +
    70
    +
    71#ifndef _Out_
    +
    72#define _Out_
    +
    73#endif
    +
    74#ifndef _Out_opt_
    +
    75#define _Out_opt_
    +
    76#endif
    +
    77#ifndef _Out_z_cap_
    +
    78#define _Out_z_cap_(p)
    +
    79#endif
    +
    80#ifndef _Out_writes_
    +
    81#define _Out_writes_(p)
    +
    82#endif
    +
    83#ifndef _Out_writes_bytes_
    +
    84#define _Out_writes_bytes_(p)
    +
    85#endif
    +
    86#ifndef _Out_writes_z_
    +
    87#define _Out_writes_z_(p)
    +
    88#endif
    +
    89#ifndef _Out_writes_bytes_to_opt_
    +
    90#define _Out_writes_bytes_to_opt_(p, q)
    +
    91#endif
    +
    92
    +
    93#ifndef _Success_
    +
    94#define _Success_(p)
    +
    95#endif
    +
    96#ifndef _Ret_maybenull_z_
    +
    97#define _Ret_maybenull_z_
    +
    98#endif
    +
    99#ifndef _Ret_notnull_
    +
    100#define _Ret_notnull_
    +
    101#endif
    +
    102#ifndef _Ret_z_
    +
    103#define _Ret_z_
    +
    104#endif
    +
    105#ifndef _Must_inspect_result_
    +
    106#define _Must_inspect_result_
    +
    107#endif
    +
    108#ifndef _Check_return_
    +
    109#define _Check_return_
    +
    110#endif
    +
    111#ifndef _Post_maybez_
    +
    112#define _Post_maybez_
    +
    113#endif
    +
    114
    +
    115#ifndef _Analysis_assume_
    +
    116#define _Analysis_assume_(p)
    +
    117#endif
    +
    118
    +
    119#ifndef _Likely_
    +
    120#if _HAS_CXX20
    +
    121#define _Likely_ [[likely]]
    +
    122#else
    +
    123#define _Likely_
    +
    124#endif
    +
    125#endif
    +
    126
    +
    127#ifndef _Unlikely_
    +
    128#if _HAS_CXX20
    +
    129#define _Unlikely_ [[unlikely]]
    +
    130#else
    +
    131#define _Unlikely_
    +
    132#endif
    +
    133#endif
    +
    134
    +
    135#ifdef _MSC_VER
    +
    136#define _Deprecated_(message) __declspec(deprecated(message))
    +
    137#else
    +
    138#define _Deprecated_(message) [[deprecated(message)]]
    +
    139#endif
    +
    140
    +
    141#ifdef _WIN32
    +
    142#define _Unreferenced_(x) UNREFERENCED_PARAMETER(x)
    +
    143#else
    +
    144#define _Unreferenced_(x)
    +
    145#endif
    +
    146
    +
    147#ifndef _WIN32
    +
    148template <typename T, size_t N>
    +
    149size_t _countof(T (&arr)[N])
    +
    150{
    +
    151 return std::extent<T[N]>::value;
    +
    152}
    +
    153#endif
    +
    154
    +
    155#ifdef __APPLE__
    +
    156#define off64_t off_t
    +
    157#define lseek64 lseek
    +
    158#define lockf64 lockf
    +
    159#define ftruncate64 ftruncate
    +
    160#endif
    +
    161
    +
    + + + + diff --git a/index.html b/index.html index 6e2062315..ebe02c281 100644 --- a/index.html +++ b/index.html @@ -76,7 +76,7 @@ $(function() { diff --git a/interval_8hpp_source.html b/interval_8hpp_source.html index 4f4f2f256..32e9b91c7 100644 --- a/interval_8hpp_source.html +++ b/interval_8hpp_source.html @@ -89,7 +89,7 @@ $(document).ready(function() { init_codefold(0); });
    5
    6#pragma once
    7
    -
    8#include "sal.hpp"
    +
    8#include "compat.hpp"
    9#include <vector>
    10
    11namespace stdex
    @@ -202,7 +202,7 @@ $(document).ready(function() { init_codefold(0); }); diff --git a/mapping_8hpp_source.html b/mapping_8hpp_source.html index fce319a4d..1b3b104e2 100644 --- a/mapping_8hpp_source.html +++ b/mapping_8hpp_source.html @@ -89,7 +89,7 @@ $(document).ready(function() { init_codefold(0); });
    5
    6#pragma once
    7
    -
    8#include "sal.hpp"
    +
    8#include "compat.hpp"
    9#include <vector>
    10
    11namespace stdex
    @@ -124,7 +124,7 @@ $(document).ready(function() { init_codefold(0); }); diff --git a/mac_2_unit_tests_2math_8hpp_source.html b/math_8cpp_source.html similarity index 60% rename from mac_2_unit_tests_2math_8hpp_source.html rename to math_8cpp_source.html index 646c5dceb..78e4a792d 100644 --- a/mac_2_unit_tests_2math_8hpp_source.html +++ b/math_8cpp_source.html @@ -5,7 +5,7 @@ -stdex: mac/UnitTests/math.hpp Source File +stdex: UnitTests/math.cpp Source File @@ -75,59 +75,61 @@ $(document).ready(function() { init_codefold(0); });
    -
    math.hpp
    +
    math.cpp
    -
    1#pragma once
    -
    2
    -
    3#include "common.hpp"
    -
    4#include <stdex/math.hpp>
    +
    1/*
    +
    2 SPDX-License-Identifier: MIT
    +
    3 Copyright © 2023 Amebis
    +
    4*/
    5
    -
    6using namespace std;
    +
    6#include "pch.h"
    7
    -
    8namespace UnitTests
    -
    9{
    -
    -
    10 class math
    -
    11 {
    -
    12 public:
    -
    13 static void mul()
    -
    14 {
    -
    15 are_equal<size_t>(10, stdex::mul(2, 5));
    -
    16 are_equal<size_t>(10, stdex::mul(5, 2));
    -
    17 are_equal<size_t>(0, stdex::mul(0, 10));
    -
    18 are_equal<size_t>(0, stdex::mul(10, 0));
    -
    19 are_equal<size_t>(0, stdex::mul(SIZE_MAX, 0));
    -
    20 are_equal<size_t>(0, stdex::mul(0, SIZE_MAX));
    -
    21 are_equal<size_t>(SIZE_MAX, stdex::mul(SIZE_MAX, 1));
    -
    22 are_equal<size_t>(SIZE_MAX, stdex::mul(1, SIZE_MAX));
    -
    23 expect_exception<std::invalid_argument>([] { stdex::mul(SIZE_MAX, 2); });
    -
    24 expect_exception<std::invalid_argument>([] { stdex::mul(2, SIZE_MAX); });
    -
    25 }
    -
    26
    -
    27 static void add()
    -
    28 {
    -
    29 are_equal<size_t>(7, stdex::add(2, 5));
    -
    30 are_equal<size_t>(7, stdex::add(5, 2));
    -
    31 are_equal<size_t>(10, stdex::add(0, 10));
    -
    32 are_equal<size_t>(10, stdex::add(10, 0));
    -
    33 are_equal<size_t>(SIZE_MAX, stdex::add(SIZE_MAX, 0));
    -
    34 are_equal<size_t>(SIZE_MAX, stdex::add(0, SIZE_MAX));
    -
    35 expect_exception<std::invalid_argument>([] { stdex::add(SIZE_MAX, 1); });
    -
    36 expect_exception<std::invalid_argument>([] { stdex::add(1, SIZE_MAX); });
    -
    37 }
    -
    38 };
    -
    -
    39}
    -
    Definition math.hpp:11
    +
    8using namespace std;
    +
    9#ifdef _WIN32
    +
    10using namespace Microsoft::VisualStudio::CppUnitTestFramework;
    +
    11#endif
    +
    12
    +
    13namespace UnitTests
    +
    14{
    +
    15 TEST_CLASS(math)
    +
    16 {
    +
    17 public:
    +
    18 TEST_METHOD(mul)
    +
    19 {
    +
    20 Assert::AreEqual<size_t>(10, stdex::mul(2, 5));
    +
    21 Assert::AreEqual<size_t>(10, stdex::mul(5, 2));
    +
    22 Assert::AreEqual<size_t>(0, stdex::mul(0, 10));
    +
    23 Assert::AreEqual<size_t>(0, stdex::mul(10, 0));
    +
    24 Assert::AreEqual<size_t>(0, stdex::mul(SIZE_MAX, 0));
    +
    25 Assert::AreEqual<size_t>(0, stdex::mul(0, SIZE_MAX));
    +
    26 Assert::AreEqual<size_t>(SIZE_MAX, stdex::mul(SIZE_MAX, 1));
    +
    27 Assert::AreEqual<size_t>(SIZE_MAX, stdex::mul(1, SIZE_MAX));
    +
    28 Assert::ExpectException<std::invalid_argument>([] { stdex::mul(SIZE_MAX, 2); });
    +
    29 Assert::ExpectException<std::invalid_argument>([] { stdex::mul(2, SIZE_MAX); });
    +
    30 }
    +
    31
    +
    32 TEST_METHOD(add)
    +
    33 {
    +
    34 Assert::AreEqual<size_t>(7, stdex::add(2, 5));
    +
    35 Assert::AreEqual<size_t>(7, stdex::add(5, 2));
    +
    36 Assert::AreEqual<size_t>(10, stdex::add(0, 10));
    +
    37 Assert::AreEqual<size_t>(10, stdex::add(10, 0));
    +
    38 Assert::AreEqual<size_t>(SIZE_MAX, stdex::add(SIZE_MAX, 0));
    +
    39 Assert::AreEqual<size_t>(SIZE_MAX, stdex::add(0, SIZE_MAX));
    +
    40 Assert::ExpectException<std::invalid_argument>([] { stdex::add(SIZE_MAX, 1); });
    +
    41 Assert::ExpectException<std::invalid_argument>([] { stdex::add(1, SIZE_MAX); });
    +
    42 }
    +
    43 };
    +
    44}
    diff --git a/include_2stdex_2math_8hpp_source.html b/math_8hpp_source.html similarity index 98% rename from include_2stdex_2math_8hpp_source.html rename to math_8hpp_source.html index 0970cd4f0..b0635d192 100644 --- a/include_2stdex_2math_8hpp_source.html +++ b/math_8hpp_source.html @@ -89,7 +89,7 @@ $(document).ready(function() { init_codefold(0); });
    5
    6#pragma once
    7
    -
    8#include "sal.hpp"
    +
    8#include "compat.hpp"
    9#include "system.hpp"
    10#include <stdexcept>
    11
    @@ -134,7 +134,7 @@ $(document).ready(function() { init_codefold(0); });
    diff --git a/memory_8hpp_source.html b/memory_8hpp_source.html index 199453fde..057541692 100644 --- a/memory_8hpp_source.html +++ b/memory_8hpp_source.html @@ -101,7 +101,7 @@ $(document).ready(function() { init_codefold(0); });
    19 template <class T2, std::enable_if_t<std::is_convertible_v<T2*, T*>, int> = 0>
    20 inline no_delete(const no_delete<T2>&) noexcept {}
    21
    -
    22 inline void operator()(T* p) const noexcept { p; }
    +
    22 inline void operator()(T* p) const noexcept { _Unreferenced_(p); }
    23 };
    24
    @@ -128,7 +128,7 @@ $(document).ready(function() { init_codefold(0); }); diff --git a/parser_8cpp_source.html b/parser_8cpp_source.html new file mode 100644 index 000000000..2264cae76 --- /dev/null +++ b/parser_8cpp_source.html @@ -0,0 +1,421 @@ + + + + + + + +stdex: UnitTests/parser.cpp Source File + + + + + + + + + +
    +
    + + + + + + +
    +
    stdex +
    +
    Additional custom or not Standard C++ covered algorithms
    +
    +
    + + + + + + + + + +
    +
    + + +
    +
    +
    +
    +
    +
    Loading...
    +
    Searching...
    +
    No Matches
    +
    +
    +
    +
    + + +
    +
    +
    parser.cpp
    +
    +
    +
    1/*
    +
    2 SPDX-License-Identifier: MIT
    +
    3 Copyright © 2023 Amebis
    +
    4*/
    +
    5
    +
    6#include "pch.h"
    +
    7
    +
    8using namespace std;
    +
    9using namespace stdex;
    +
    10using namespace stdex::parser;
    +
    11#ifdef _WIN32
    +
    12using namespace Microsoft::VisualStudio::CppUnitTestFramework;
    +
    13#endif
    +
    14
    +
    15namespace UnitTests
    +
    16{
    +
    17 TEST_CLASS(parser)
    +
    18 {
    +
    19 public:
    + +
    21 {
    +
    22 static const wchar_t text[] = L"This is a test.\nSecond line.";
    +
    23
    +
    24 {
    +
    25 wnoop p;
    +
    26 Assert::IsTrue(p.match(text));
    +
    27 Assert::AreEqual((size_t)0, p.interval.start);
    +
    28 Assert::AreEqual((size_t)0, p.interval.end);
    +
    29 }
    +
    30
    +
    31 {
    +
    32 wcu p(L't');
    +
    33 Assert::IsFalse(p.match(text));
    +
    34 Assert::IsTrue(p.match(text, 0, _countof(text), match_case_insensitive));
    +
    35 Assert::AreEqual((size_t)0, p.interval.start);
    +
    36 Assert::AreEqual((size_t)1, p.interval.end);
    +
    37 }
    +
    38
    +
    39 {
    + +
    41 Assert::IsFalse(p.match(text));
    +
    42 Assert::IsTrue(p.match(text, 4));
    +
    43 Assert::AreEqual((size_t)4, p.interval.start);
    +
    44 Assert::AreEqual((size_t)5, p.interval.end);
    +
    45 }
    +
    46
    +
    47 {
    + +
    49 Assert::IsFalse(p.match(text));
    +
    50 Assert::IsTrue(p.match(text, 14));
    +
    51 Assert::AreEqual((size_t)14, p.interval.start);
    +
    52 Assert::AreEqual((size_t)15, p.interval.end);
    +
    53 }
    +
    54
    +
    55 {
    + +
    57 Assert::IsFalse(p.match(text));
    +
    58 Assert::IsTrue(p.match(text, 4));
    +
    59 Assert::AreEqual((size_t)4, p.interval.start);
    +
    60 Assert::AreEqual((size_t)5, p.interval.end);
    +
    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);
    +
    64 }
    +
    65
    +
    66 {
    +
    67 wbol p;
    +
    68 Assert::IsTrue(p.match(text));
    +
    69 Assert::AreEqual((size_t)0, p.interval.start);
    +
    70 Assert::AreEqual((size_t)0, p.interval.end);
    +
    71 Assert::IsFalse(p.match(text, 1));
    +
    72 Assert::IsFalse(p.match(text, 15));
    +
    73 Assert::IsTrue(p.match(text, 16));
    +
    74 Assert::AreEqual((size_t)16, p.interval.start);
    +
    75 Assert::AreEqual((size_t)16, p.interval.end);
    +
    76 }
    +
    77
    +
    78 {
    +
    79 weol p;
    +
    80 Assert::IsFalse(p.match(text));
    +
    81 Assert::IsFalse(p.match(text, 1));
    +
    82 Assert::IsTrue(p.match(text, 15));
    +
    83 Assert::AreEqual((size_t)15, p.interval.start);
    +
    84 Assert::AreEqual((size_t)15, p.interval.end);
    +
    85 Assert::IsFalse(p.match(text, 16));
    +
    86 }
    +
    87
    +
    88 {
    +
    89 wcu_set p(L"abcD");
    +
    90 Assert::IsFalse(p.match(text));
    +
    91 Assert::IsTrue(p.match(text, 8));
    +
    92 Assert::AreEqual((size_t)8, p.interval.start);
    +
    93 Assert::AreEqual((size_t)9, p.interval.end);
    +
    94 Assert::AreEqual((size_t)0, p.hit_offset);
    +
    95 Assert::IsFalse(p.match(text, 21));
    +
    96 Assert::IsTrue(p.match(text, 21, _countof(text), match_case_insensitive));
    +
    97 Assert::AreEqual((size_t)21, p.interval.start);
    +
    98 Assert::AreEqual((size_t)22, p.interval.end);
    +
    99 Assert::AreEqual((size_t)3, p.hit_offset);
    +
    100 }
    +
    101
    +
    102 {
    +
    103 stdex::parser::wstring p(L"this");
    +
    104 Assert::IsFalse(p.match(text));
    +
    105 Assert::IsTrue(p.match(text, 0, sizeof(text), match_case_insensitive));
    +
    106 Assert::AreEqual((size_t)0, p.interval.start);
    +
    107 Assert::AreEqual((size_t)4, p.interval.end);
    +
    108 }
    +
    109
    +
    110 {
    +
    111 wany_cu chr;
    +
    112 witerations p(make_shared_no_delete(&chr), 1, 5);
    +
    113 Assert::IsTrue(p.match(text));
    +
    114 Assert::AreEqual((size_t)0, p.interval.start);
    +
    115 Assert::AreEqual((size_t)5, p.interval.end);
    +
    116 }
    +
    117
    +
    118 {
    +
    119 wspace_cu nospace(true);
    +
    120 witerations p(make_shared_no_delete(&nospace), 1);
    +
    121 Assert::IsTrue(p.match(text));
    +
    122 Assert::AreEqual((size_t)0, p.interval.start);
    +
    123 Assert::AreEqual((size_t)4, p.interval.end);
    +
    124 }
    +
    125
    +
    126 {
    +
    127 wcu chr_t(L't'), chr_h(L'h'), chr_i(L'i'), chr_s(L's');
    +
    128 wspace_cu space;
    +
    129 wsequence p({
    +
    130 make_shared_no_delete(&chr_t),
    +
    131 make_shared_no_delete(&chr_h),
    +
    132 make_shared_no_delete(&chr_i),
    +
    133 make_shared_no_delete(&chr_s),
    +
    134 make_shared_no_delete(&space) });
    +
    135 Assert::IsFalse(p.match(text));
    +
    136 Assert::IsTrue(p.match(text, 0, _countof(text), match_case_insensitive));
    +
    137 Assert::AreEqual((size_t)0, p.interval.start);
    +
    138 Assert::AreEqual((size_t)5, p.interval.end);
    +
    139 }
    +
    140
    +
    141 {
    +
    142 stdex::parser::wstring apple(L"apple"), orange(L"orange"), _this(L"this");
    +
    143 wspace_cu space;
    +
    144 wbranch p({
    +
    145 make_shared_no_delete(&apple),
    +
    146 make_shared_no_delete(&orange),
    +
    147 make_shared_no_delete(&_this),
    +
    148 make_shared_no_delete(&space) });
    +
    149 Assert::IsFalse(p.match(text));
    +
    150 Assert::IsTrue(p.match(text, 0, _countof(text), match_case_insensitive));
    +
    151 Assert::AreEqual((size_t)2, p.hit_offset);
    +
    152 Assert::AreEqual((size_t)0, p.interval.start);
    +
    153 Assert::AreEqual((size_t)4, p.interval.end);
    +
    154 }
    +
    155
    +
    156 {
    +
    157 wstring_branch p(L"apple", L"orange", L"this", nullptr);
    +
    158 Assert::IsFalse(p.match(text));
    +
    159 Assert::IsTrue(p.match(text, 0, _countof(text), match_case_insensitive));
    +
    160 Assert::AreEqual((size_t)2, p.hit_offset);
    +
    161 Assert::AreEqual((size_t)0, p.interval.start);
    +
    162 Assert::AreEqual((size_t)4, p.interval.end);
    +
    163 }
    +
    164
    +
    165 {
    +
    166 wcu chr_s(L's'), chr_h(L'h'), chr_i(L'i'), chr_t(L't');
    + +
    168 make_shared_no_delete(&chr_s),
    +
    169 make_shared_no_delete(&chr_h),
    +
    170 make_shared_no_delete(&chr_i),
    +
    171 make_shared_no_delete(&chr_t) });
    +
    172 Assert::IsFalse(p.match(text));
    +
    173 Assert::IsTrue(p.match(text, 0, _countof(text), match_case_insensitive));
    +
    174 Assert::AreEqual((size_t)0, p.interval.start);
    +
    175 Assert::AreEqual((size_t)4, p.interval.end);
    +
    176 }
    +
    177 }
    +
    178
    + +
    180 {
    +
    181 std::locale locale_slSI("sl_SI");
    +
    182 static const char text[] = "V ko&zcaron;u&scaron;&ccaron;ku zlobnega mizarja stopiclja fant\nin kli&ccaron;e&nbsp;1234567890.";
    +
    183
    +
    184 {
    +
    185 sgml_noop p;
    +
    186 Assert::IsTrue(p.match(text));
    +
    187 Assert::AreEqual((size_t)0, p.interval.start);
    +
    188 Assert::AreEqual((size_t)0, p.interval.end);
    +
    189 }
    +
    190
    +
    191 {
    +
    192 sgml_cp p("v");
    +
    193 Assert::IsFalse(p.match(text));
    +
    194 Assert::IsTrue(p.match(text, 0, _countof(text), match_case_insensitive));
    +
    195 Assert::AreEqual((size_t)0, p.interval.start);
    +
    196 Assert::AreEqual((size_t)1, p.interval.end);
    +
    197 }
    +
    198
    +
    199 {
    +
    200 sgml_cp p("&Zcaron;", SIZE_MAX, false, locale_slSI);
    +
    201 Assert::IsFalse(p.match(text, 4));
    +
    202 Assert::IsTrue(p.match(text, 4, _countof(text), match_case_insensitive));
    +
    203 Assert::AreEqual((size_t)4, p.interval.start);
    +
    204 Assert::AreEqual((size_t)12, p.interval.end);
    +
    205 }
    +
    206
    +
    207 {
    + +
    209 Assert::IsFalse(p.match(text));
    +
    210 Assert::IsTrue(p.match(text, 1));
    +
    211 Assert::AreEqual((size_t)1, p.interval.start);
    +
    212 Assert::AreEqual((size_t)2, p.interval.end);
    +
    213 Assert::IsTrue(p.match(text, 79));
    +
    214 Assert::AreEqual((size_t)79, p.interval.start);
    +
    215 Assert::AreEqual((size_t)85, p.interval.end);
    +
    216 }
    +
    217
    +
    218 {
    +
    219 sgml_string_branch p(locale_slSI, "apple", "orange", "Ko&Zcaron;u&Scaron;&ccaron;Ku", nullptr);
    +
    220 Assert::IsFalse(p.match(text, 2));
    +
    221 Assert::IsTrue(p.match(text, 2, _countof(text), match_case_insensitive));
    +
    222 Assert::AreEqual((size_t)2, p.hit_offset);
    +
    223 Assert::AreEqual((size_t)2, p.interval.start);
    +
    224 Assert::AreEqual((size_t)31, p.interval.end);
    +
    225 }
    +
    226 }
    +
    227
    + +
    229 {
    +
    230 static const std::locale locale("en_US.UTF-8");
    +
    231 static const char request[] =
    +
    232 "GET / HTTP/2\r\n"
    +
    233 "Host: stackoverflow.com\r\n"
    +
    234 "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/110.0\r\n"
    +
    235 "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8\r\n"
    +
    236 "Accept-Language: sl,en-US;q=0.8,en;q=0.6,de-DE;q=0.4,de;q=0.2\r\n"
    +
    237 "Accept-Encoding: gzip, deflate, br\r\n"
    +
    238 "DNT: 1\r\n"
    +
    239 "Connection: keep-alive\r\n"
    +
    240 "Cookie: prov=00000000-0000-0000-0000-000000000000; acct=t=00000000000000000%2f%2f0000%2b0000%2b000&s=00000000000000000000000000000000; OptanonConsent=isGpcEnabled=0&datestamp=Fri+Feb+03+2023+11%3A11%3A08+GMT%2B0100+(Srednjeevropski+standardni+%C4%8Das)&version=6.37.0&isIABGlobal=false&hosts=&consentId=00000000-0000-0000-0000-000000000000&interactionCount=1&landingPath=NotLandingPage&groups=00000%3A0%2C00000%3A0%2C00000%3A0%2C00000%3A0; OptanonAlertBoxClosed=2023-02-03T10:11:08.683Z\r\n"
    +
    241 "Upgrade-Insecure-Requests: 1\r\n"
    +
    242 "Sec-Fetch-Dest: document\r\n"
    +
    243 "Sec-Fetch-Mode: navigate\r\n"
    +
    244 "Sec-Fetch-Site: none\r\n"
    +
    245 "Sec-Fetch-User: ?1\r\n"
    +
    246 "Pragma: no-cache\r\n"
    +
    247 "Cache-Control: no-cache\r\n"
    +
    248 "\r\n";
    +
    249
    +
    250 {
    +
    251 http_request p(locale);
    +
    252 Assert::IsTrue(p.match(request));
    +
    253 Assert::AreEqual((size_t)0, p.interval.start);
    +
    254 Assert::AreEqual((size_t)14, p.interval.end);
    +
    255 Assert::AreEqual((size_t)0, p.verb.start);
    +
    256 Assert::AreEqual((size_t)3, p.verb.end);
    +
    257 Assert::AreEqual((size_t)4, p.url.interval.start);
    +
    258 Assert::AreEqual((size_t)5, p.url.interval.end);
    +
    259 Assert::AreEqual((size_t)6, p.protocol.interval.start);
    +
    260 Assert::AreEqual((size_t)12, p.protocol.interval.end);
    +
    261 Assert::AreEqual((uint16_t)0x200, p.protocol.version);
    +
    262 }
    +
    263
    +
    264 {
    +
    265 std::list<http_header> hdrs;
    +
    266 size_t offset = 14;
    +
    267 for (;;) {
    + +
    269 if (h.match(request, offset)) {
    +
    270 offset = h.interval.end;
    +
    271 hdrs.push_back(std::move(h));
    +
    272 }
    +
    273 else
    +
    274 break;
    +
    275 }
    +
    276 Assert::AreEqual((size_t)15, hdrs.size());
    + +
    278 for (const auto& h : hdrs)
    +
    279 if (strnicmp(request + h.name.start, h.name.size(), "Accept-Language", (size_t)-1, locale) == 0)
    +
    280 langs.insert(request, h.value.start, h.value.end);
    +
    281 Assert::IsTrue(!langs.empty());
    +
    282 {
    + +
    284 "sl", "en-US", "en", "de-DE", "de"
    +
    285 };
    +
    286 auto c = control.cbegin();
    +
    287 auto l = langs.cbegin();
    +
    288 for (; c != control.cend() && l != langs.cend(); ++c, ++l)
    +
    289 Assert::IsTrue(strnicmp(request + l->value.interval.start, l->value.interval.size(), c->c_str(), c->size(), locale) == 0);
    +
    290 Assert::IsTrue(c == control.cend());
    +
    291 Assert::IsTrue(l == langs.cend());
    +
    292 }
    +
    293 }
    +
    294
    +
    295 //static const char response[] =
    +
    296 // "HTTP/2 200 OK\r\n"
    +
    297 // "cache-control: private\r\n"
    +
    298 // "content-type: text/html; charset=utf-8\r\n"
    +
    299 // "content-encoding: gzip\r\n"
    +
    300 // "strict-transport-security: max-age=15552000\r\n"
    +
    301 // "x-frame-options: SAMEORIGIN\r\n"
    +
    302 // "set-cookie: acct=t=00000000000000000%2f%2f0000%2b0000%2b000&s=00000000000000000000000000000000; expires=Sat, 16 Sep 2023 10:23:00 GMT; domain=.stackoverflow.com; path=/; secure; samesite=none; httponly\r\n"
    +
    303 // "set-cookie: prov_tgt=; expires=Tue, 14 Mar 2023 10:23:00 GMT; domain=.stackoverflow.com; path=/; secure; samesite=none; httponly\r\n"
    +
    304 // "x-request-guid: a6536a49-b473-4c6f-b313-c1e7c0d8f600\r\n"
    +
    305 // "feature-policy: microphone 'none'; speaker 'none'\r\n"
    +
    306 // "content-security-policy: upgrade-insecure-requests; frame-ancestors 'self' https://stackexchange.com\r\n"
    +
    307 // "accept-ranges: bytes\r\n"
    +
    308 // "date: Thu, 16 Mar 2023 10:23:00 GMT\r\n"
    +
    309 // "via: 1.1 varnish\r\n"
    +
    310 // "x-served-by: cache-vie6354-VIE\r\n"
    +
    311 // "x-cache: MISS\r\n"
    +
    312 // "x-cache-hits: 0\r\n"
    +
    313 // "x-timer: S1678962181.533907,VS0,VE144\r\n"
    +
    314 // "vary: Accept-Encoding,Fastly-SSL\r\n"
    +
    315 // "x-dns-prefetch-control: off\r\n"
    +
    316 // "X-Firefox-Spdy: h2\r\n"
    +
    317 // "\r\n";
    +
    318 }
    +
    319 };
    +
    320}
    + +
    interval< size_t > interval
    Region of the last match.
    Definition parser.hpp:169
    +
    Test for given string.
    Definition parser.hpp:815
    +
    Test for HTTP header.
    Definition parser.hpp:6277
    +
    Test for HTTP request.
    Definition parser.hpp:6139
    +
    Test for specific SGML code point.
    Definition parser.hpp:340
    +
    Test for any SGML space code point.
    Definition parser.hpp:427
    +
    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
    +
    + + + + diff --git a/parser_8hpp_source.html b/parser_8hpp_source.html index 2c66a719a..6e14ca00a 100644 --- a/parser_8hpp_source.html +++ b/parser_8hpp_source.html @@ -89,6645 +89,6648 @@ $(document).ready(function() { init_codefold(0); });
    5
    6#pragma once
    7
    -
    8#include "interval.hpp"
    -
    9#include "memory.hpp"
    -
    10#include "sal.hpp"
    +
    8#include "compat.hpp"
    +
    9#include "interval.hpp"
    +
    10#include "memory.hpp"
    11#include "sgml.hpp"
    12#include "string.hpp"
    13#include "system.hpp"
    14#include <assert.h>
    15#include <stdarg.h>
    16#include <stdint.h>
    -
    17#ifdef _WIN32
    +
    17#if defined(_WIN32)
    18#ifndef _WINSOCKAPI_
    19#include <winsock2.h>
    20#include <ws2ipdef.h>
    21#endif
    -
    22#else
    -
    23#include <inaddr.h>
    -
    24#include <in6addr.h>
    -
    25#endif
    -
    26#include <limits>
    -
    27#include <list>
    -
    28#include <locale>
    -
    29#include <memory>
    -
    30#include <set>
    -
    31#include <string>
    -
    32
    -
    33#ifdef _MSC_VER
    -
    34#pragma warning(push)
    -
    35#pragma warning(disable: 4100)
    -
    36#endif
    -
    37
    -
    38#define ENUM_FLAG_OPERATOR(T,X) \
    -
    39inline 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)); } \
    -
    40inline 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); } \
    -
    41inline 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)); } \
    -
    42inline T& operator X= (T& lhs, const T rhs) { return lhs = lhs X rhs; } \
    -
    43inline T& operator X= (T& lhs, const std::underlying_type_t<T> rhs) { return lhs = lhs X rhs; }
    -
    44#define ENUM_FLAGS(T, type) \
    -
    45enum class T : type; \
    -
    46inline T operator ~ (T t) { return (T) (~static_cast<std::underlying_type_t <T>>(t)); } \
    -
    47ENUM_FLAG_OPERATOR(T,|) \
    -
    48ENUM_FLAG_OPERATOR(T,^) \
    -
    49ENUM_FLAG_OPERATOR(T,&) \
    -
    50enum class T : type
    -
    51
    -
    52namespace stdex
    -
    53{
    -
    54 namespace parser
    -
    55 {
    -
    59 constexpr int match_default = 0;
    -
    60 constexpr int match_case_insensitive = 0x1;
    -
    61 constexpr int match_multiline = 0x2;
    -
    62
    -
    66 template <class T>
    -
    -
    67 class basic_parser
    -
    68 {
    -
    69 public:
    -
    70 basic_parser(_In_ const std::locale& locale = std::locale()) : m_locale(locale) {}
    -
    71 virtual ~basic_parser() {}
    -
    72
    -
    73 bool search(
    -
    74 _In_reads_or_z_(end) const T* text,
    -
    75 _In_ size_t start = 0,
    -
    76 _In_ size_t end = (size_t)-1,
    -
    77 _In_ int flags = match_default)
    -
    78 {
    -
    79 for (size_t i = start; i < end && text[i]; i++)
    -
    80 if (match(text, i, end, flags))
    -
    81 return true;
    -
    82 return false;
    -
    83 }
    -
    84
    -
    85 virtual bool match(
    -
    86 _In_reads_or_z_(end) const T* text,
    -
    87 _In_ size_t start = 0,
    -
    88 _In_ size_t end = (size_t)-1,
    -
    89 _In_ int flags = match_default) = 0;
    -
    90
    -
    91 template<class _Traits, class _Ax>
    -
    92 inline bool match(
    -
    93 const std::basic_string<T, _Traits, _Ax>& text,
    -
    94 _In_ size_t start = 0,
    -
    95 _In_ size_t end = (size_t)-1,
    -
    96 _In_ int flags = match_default)
    -
    97 {
    -
    98 return match(text.c_str(), start, std::min<size_t>(end, text.size()), flags);
    -
    99 }
    -
    100
    -
    101 virtual void invalidate()
    -
    102 {
    -
    103 interval.start = 1;
    -
    104 interval.end = 0;
    -
    105 }
    -
    106
    -
    107 protected:
    -
    109 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])
    -
    110 {
    -
    111 if (text[start] == '&') {
    -
    112 // Potential entity start
    -
    113 const auto& ctype = std::use_facet<std::ctype<T>>(m_locale);
    -
    114 for (chr_end = start + 1;; chr_end++) {
    -
    115 if (chr_end >= end || text[chr_end] == 0) {
    -
    116 // Unterminated entity
    -
    117 break;
    -
    118 }
    -
    119 if (text[chr_end] == ';') {
    -
    120 // Entity end
    -
    121 size_t n = chr_end - start - 1;
    -
    122 if (n >= 2 && text[start + 1] == '#') {
    -
    123 // Numerical entity
    -
    124 char32_t unicode;
    -
    125 if (text[start + 2] == 'x' || text[start + 2] == 'X')
    -
    126 unicode = strtou32(text + start + 3, n - 2, nullptr, 16);
    -
    127 else
    -
    128 unicode = strtou32(text + start + 2, n - 1, nullptr, 10);
    -
    129#ifdef _WIN32
    -
    130 if (unicode < 0x10000) {
    -
    131 buf[0] = (wchar_t)unicode;
    -
    132 buf[1] = 0;
    -
    133 }
    -
    134 else {
    -
    135 ucs4_to_surrogate_pair(buf, unicode);
    -
    136 buf[2] = 0;
    -
    137 }
    -
    138#else
    -
    139 buf[0] = (wchar_t)unicode;
    -
    140 buf[1] = 0;
    -
    141#endif
    -
    142 chr_end++;
    -
    143 return buf;
    -
    144 }
    -
    145 const wchar_t* entity_w = sgml2uni(text + start + 1, n);
    -
    146 if (entity_w) {
    -
    147 chr_end++;
    -
    148 return entity_w;
    -
    149 }
    -
    150 // Unknown entity.
    -
    151 break;
    -
    152 }
    -
    153 else if (text[chr_end] == '&' || ctype.is(ctype.space, text[chr_end])) {
    -
    154 // This char cannot possibly be a part of entity.
    -
    155 break;
    -
    156 }
    -
    157 }
    -
    158 }
    -
    159 buf[0] = text[start];
    -
    160 buf[1] = 0;
    -
    161 chr_end = start + 1;
    -
    162 return buf;
    -
    163 }
    -
    165
    -
    166 public:
    -
    167 interval<size_t> interval;
    -
    168
    -
    169 protected:
    -
    170 std::locale m_locale;
    -
    171 };
    +
    22#elif defined(__APPLE__)
    +
    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
    +
    54namespace stdex
    +
    55{
    +
    56 namespace parser
    +
    57 {
    +
    61 constexpr int match_default = 0;
    +
    62 constexpr int match_case_insensitive = 0x1;
    +
    63 constexpr int match_multiline = 0x2;
    +
    64
    +
    68 template <class T>
    +
    + +
    70 {
    +
    71 public:
    +
    72 basic_parser(_In_ const std::locale& locale = std::locale()) : m_locale(locale) {}
    +
    73 virtual ~basic_parser() {}
    +
    74
    +
    75 bool search(
    +
    76 _In_reads_or_z_(end) const T* text,
    +
    77 _In_ size_t start = 0,
    +
    78 _In_ size_t end = (size_t)-1,
    +
    79 _In_ int flags = match_default)
    +
    80 {
    +
    81 for (size_t i = start; i < end && text[i]; i++)
    +
    82 if (match(text, i, end, flags))
    +
    83 return true;
    +
    84 return false;
    +
    85 }
    +
    86
    +
    87 virtual bool match(
    +
    88 _In_reads_or_z_(end) const T* text,
    +
    89 _In_ size_t start = 0,
    +
    90 _In_ size_t end = (size_t)-1,
    +
    91 _In_ int flags = match_default) = 0;
    +
    92
    +
    93 template<class _Traits, class _Ax>
    +
    94 inline bool match(
    +
    95 const std::basic_string<T, _Traits, _Ax>& text,
    +
    96 _In_ size_t start = 0,
    +
    97 _In_ size_t end = (size_t)-1,
    +
    98 _In_ int flags = match_default)
    +
    99 {
    +
    100 return match(text.c_str(), start, std::min<size_t>(end, text.size()), flags);
    +
    101 }
    +
    102
    +
    103 virtual void invalidate()
    +
    104 {
    +
    105 this->interval.start = 1;
    +
    106 this->interval.end = 0;
    +
    107 }
    +
    108
    +
    109 protected:
    +
    111 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])
    +
    112 {
    +
    113 if (text[start] == '&') {
    +
    114 // Potential entity start
    +
    115 const auto& ctype = std::use_facet<std::ctype<T>>(m_locale);
    +
    116 for (chr_end = start + 1;; chr_end++) {
    +
    117 if (chr_end >= end || text[chr_end] == 0) {
    +
    118 // Unterminated entity
    +
    119 break;
    +
    120 }
    +
    121 if (text[chr_end] == ';') {
    +
    122 // Entity end
    +
    123 size_t n = chr_end - start - 1;
    +
    124 if (n >= 2 && text[start + 1] == '#') {
    +
    125 // Numerical entity
    +
    126 char32_t unicode;
    +
    127 if (text[start + 2] == 'x' || text[start + 2] == 'X')
    +
    128 unicode = strtou32(text + start + 3, n - 2, nullptr, 16);
    +
    129 else
    +
    130 unicode = strtou32(text + start + 2, n - 1, nullptr, 10);
    +
    131#ifdef _WIN32
    +
    132 if (unicode < 0x10000) {
    +
    133 buf[0] = (wchar_t)unicode;
    +
    134 buf[1] = 0;
    +
    135 }
    +
    136 else {
    +
    137 ucs4_to_surrogate_pair(buf, unicode);
    +
    138 buf[2] = 0;
    +
    139 }
    +
    140#else
    +
    141 buf[0] = (wchar_t)unicode;
    +
    142 buf[1] = 0;
    +
    143#endif
    +
    144 chr_end++;
    +
    145 return buf;
    +
    146 }
    +
    147 const wchar_t* entity_w = sgml2uni(text + start + 1, n);
    +
    148 if (entity_w) {
    +
    149 chr_end++;
    +
    150 return entity_w;
    +
    151 }
    +
    152 // Unknown entity.
    +
    153 break;
    +
    154 }
    +
    155 else if (text[chr_end] == '&' || ctype.is(ctype.space, text[chr_end])) {
    +
    156 // This char cannot possibly be a part of entity.
    +
    157 break;
    +
    158 }
    +
    159 }
    +
    160 }
    +
    161 buf[0] = text[start];
    +
    162 buf[1] = 0;
    +
    163 chr_end = start + 1;
    +
    164 return buf;
    +
    165 }
    +
    167
    +
    168 public:
    + +
    170
    +
    171 protected:
    +
    172 std::locale m_locale;
    +
    173 };
    -
    172
    -
    173 using parser = basic_parser<char>;
    -
    174 using wparser = basic_parser<wchar_t>;
    -
    175#ifdef _UNICODE
    -
    176 using tparser = wparser;
    -
    177#else
    -
    178 using tparser = parser;
    -
    179#endif
    -
    180 using sgml_parser = basic_parser<char>;
    -
    181
    -
    185 template <class T>
    -
    -
    186 class basic_noop : public basic_parser<T>
    -
    187 {
    -
    188 public:
    -
    189 virtual bool match(
    -
    190 _In_reads_or_z_(end) const T* text,
    -
    191 _In_ size_t start = 0,
    -
    192 _In_ size_t end = (size_t)-1,
    -
    193 _In_ int flags = match_default)
    -
    194 {
    -
    195 assert(text || start >= end);
    -
    196 if (start < end && text[start]) {
    -
    197 interval.start = interval.end = start;
    -
    198 return true;
    -
    199 }
    -
    200 interval.start = (interval.end = start) + 1;
    -
    201 return false;
    -
    202 }
    -
    203 };
    +
    174
    + + +
    177#ifdef _UNICODE
    +
    178 using tparser = wparser;
    +
    179#else
    +
    180 using tparser = parser;
    +
    181#endif
    + +
    183
    +
    187 template <class T>
    +
    +
    188 class basic_noop : public basic_parser<T>
    +
    189 {
    +
    190 public:
    +
    191 virtual bool match(
    +
    192 _In_reads_or_z_(end) const T* text,
    +
    193 _In_ size_t start = 0,
    +
    194 _In_ size_t end = (size_t)-1,
    +
    195 _In_ int flags = match_default)
    +
    196 {
    +
    197 assert(text || start >= end);
    +
    198 if (start < end && text[start]) {
    +
    199 this->interval.start = this->interval.end = start;
    +
    200 return true;
    +
    201 }
    +
    202 this->interval.start = (this->interval.end = start) + 1;
    +
    203 return false;
    +
    204 }
    +
    205 };
    -
    204
    -
    205 using noop = basic_noop<char>;
    - -
    207#ifdef _UNICODE
    -
    208 using tnoop = wnoop;
    -
    209#else
    -
    210 using tnoop = noop;
    -
    211#endif
    - -
    213
    -
    217 template <class T>
    -
    -
    218 class basic_any_cu : public basic_parser<T>
    -
    219 {
    -
    220 public:
    -
    221 basic_any_cu(_In_ const std::locale& locale = std::locale()) : basic_parser<T>(locale) {}
    -
    222
    -
    223 virtual bool match(
    -
    224 _In_reads_or_z_(end) const T* text,
    -
    225 _In_ size_t start = 0,
    -
    226 _In_ size_t end = (size_t)-1,
    -
    227 _In_ int flags = match_default)
    -
    228 {
    -
    229 assert(text || start >= end);
    -
    230 if (start < end && text[start]) {
    -
    231 interval.end = (interval.start = start) + 1;
    -
    232 return true;
    -
    233 }
    -
    234 interval.start = (interval.end = start) + 1;
    -
    235 return false;
    -
    236 }
    -
    237 };
    +
    206
    +
    207 using noop = basic_noop<char>;
    + +
    209#ifdef _UNICODE
    +
    210 using tnoop = wnoop;
    +
    211#else
    +
    212 using tnoop = noop;
    +
    213#endif
    + +
    215
    +
    219 template <class T>
    +
    +
    220 class basic_any_cu : public basic_parser<T>
    +
    221 {
    +
    222 public:
    +
    223 basic_any_cu(_In_ const std::locale& locale = std::locale()) : basic_parser<T>(locale) {}
    +
    224
    +
    225 virtual bool match(
    +
    226 _In_reads_or_z_(end) const T* text,
    +
    227 _In_ size_t start = 0,
    +
    228 _In_ size_t end = (size_t)-1,
    +
    229 _In_ int flags = match_default)
    +
    230 {
    +
    231 assert(text || start >= end);
    +
    232 if (start < end && text[start]) {
    +
    233 this->interval.end = (this->interval.start = start) + 1;
    +
    234 return true;
    +
    235 }
    +
    236 this->interval.start = (this->interval.end = start) + 1;
    +
    237 return false;
    +
    238 }
    +
    239 };
    -
    238
    - - -
    241#ifdef _UNICODE
    -
    242 using tany_cu = wany_cu;
    -
    243#else
    -
    244 using tany_cu = any_cu;
    -
    245#endif
    -
    246
    -
    -
    250 class sgml_any_cp : public basic_any_cu<char>
    -
    251 {
    -
    252 public:
    -
    253 sgml_any_cp(_In_ const std::locale& locale = std::locale()) : basic_any_cu<char>(locale) {}
    -
    254
    -
    255 virtual bool match(
    -
    256 _In_reads_or_z_(end) const char* text,
    -
    257 _In_ size_t start = 0,
    -
    258 _In_ size_t end = (size_t)-1,
    -
    259 _In_ int flags = match_default)
    -
    260 {
    -
    261 assert(text || start >= end);
    -
    262 if (start < end && text[start]) {
    -
    263 if (text[start] == '&') {
    -
    264 // SGML entity
    -
    265 const auto& ctype = std::use_facet<std::ctype<char>>(m_locale);
    -
    266 for (interval.end = start + 1; interval.end < end && text[interval.end]; interval.end++)
    -
    267 if (text[interval.end] == ';') {
    -
    268 interval.end++;
    -
    269 interval.start = start;
    -
    270 return true;
    -
    271 }
    -
    272 else if (text[interval.end] == '&' || ctype.is(ctype.space, text[interval.end]))
    -
    273 break;
    -
    274 // Unterminated entity
    -
    275 }
    -
    276 interval.end = (interval.start = start) + 1;
    -
    277 return true;
    -
    278 }
    -
    279 interval.start = (interval.end = start) + 1;
    -
    280 return false;
    -
    281 }
    -
    282 };
    +
    240
    + + +
    243#ifdef _UNICODE
    +
    244 using tany_cu = wany_cu;
    +
    245#else
    +
    246 using tany_cu = any_cu;
    +
    247#endif
    +
    248
    +
    +
    252 class sgml_any_cp : public basic_any_cu<char>
    +
    253 {
    +
    254 public:
    +
    255 sgml_any_cp(_In_ const std::locale& locale = std::locale()) : basic_any_cu<char>(locale) {}
    +
    256
    +
    257 virtual bool match(
    +
    258 _In_reads_or_z_(end) const char* text,
    +
    259 _In_ size_t start = 0,
    +
    260 _In_ size_t end = (size_t)-1,
    +
    261 _In_ int flags = match_default)
    +
    262 {
    +
    263 assert(text || start >= end);
    +
    264 if (start < end && text[start]) {
    +
    265 if (text[start] == '&') {
    +
    266 // SGML entity
    +
    267 const auto& ctype = std::use_facet<std::ctype<char>>(m_locale);
    +
    268 for (this->interval.end = start + 1; this->interval.end < end && text[this->interval.end]; this->interval.end++)
    +
    269 if (text[this->interval.end] == ';') {
    +
    270 this->interval.end++;
    +
    271 this->interval.start = start;
    +
    272 return true;
    +
    273 }
    +
    274 else if (text[this->interval.end] == '&' || ctype.is(ctype.space, text[this->interval.end]))
    +
    275 break;
    +
    276 // Unterminated entity
    +
    277 }
    +
    278 this->interval.end = (this->interval.start = start) + 1;
    +
    279 return true;
    +
    280 }
    +
    281 this->interval.start = (this->interval.end = start) + 1;
    +
    282 return false;
    +
    283 }
    +
    284 };
    -
    283
    -
    287 template <class T>
    -
    -
    288 class basic_cu : public basic_parser<T>
    -
    289 {
    -
    290 public:
    -
    291 basic_cu(T chr, bool invert = false, _In_ const std::locale& locale = std::locale()) :
    -
    292 basic_parser<T>(locale),
    -
    293 m_chr(chr),
    -
    294 m_invert(invert)
    -
    295 {}
    -
    296
    -
    297 virtual bool match(
    -
    298 _In_reads_or_z_(end) const T* text,
    -
    299 _In_ size_t start = 0,
    -
    300 _In_ size_t end = (size_t)-1,
    -
    301 _In_ int flags = match_default)
    -
    302 {
    -
    303 assert(text || start >= end);
    -
    304 if (start < end && text[start]) {
    -
    305 bool r;
    -
    306 if (flags & match_case_insensitive) {
    -
    307 const auto& ctype = std::use_facet<std::ctype<T>>(m_locale);
    -
    308 r = ctype.tolower(text[start]) == ctype.tolower(m_chr);
    -
    309 }
    -
    310 else
    -
    311 r = text[start] == m_chr;
    -
    312 if (r && !m_invert || !r && m_invert) {
    -
    313 interval.end = (interval.start = start) + 1;
    -
    314 return true;
    -
    315 }
    -
    316 }
    -
    317 interval.start = (interval.end = start) + 1;
    -
    318 return false;
    -
    319 }
    -
    320
    -
    321 protected:
    -
    322 T m_chr;
    -
    323 bool m_invert;
    -
    324 };
    +
    285
    +
    289 template <class T>
    +
    +
    290 class basic_cu : public basic_parser<T>
    +
    291 {
    +
    292 public:
    +
    293 basic_cu(T chr, bool invert = false, _In_ const std::locale& locale = std::locale()) :
    +
    294 basic_parser<T>(locale),
    +
    295 m_chr(chr),
    +
    296 m_invert(invert)
    +
    297 {}
    +
    298
    +
    299 virtual bool match(
    +
    300 _In_reads_or_z_(end) const T* text,
    +
    301 _In_ size_t start = 0,
    +
    302 _In_ size_t end = (size_t)-1,
    +
    303 _In_ int flags = match_default)
    +
    304 {
    +
    305 assert(text || start >= end);
    +
    306 if (start < end && text[start]) {
    +
    307 bool r;
    +
    308 if (flags & match_case_insensitive) {
    +
    309 const auto& ctype = std::use_facet<std::ctype<T>>(this->m_locale);
    +
    310 r = ctype.tolower(text[start]) == ctype.tolower(m_chr);
    +
    311 }
    +
    312 else
    +
    313 r = text[start] == m_chr;
    +
    314 if ((r && !m_invert) || (!r && m_invert)) {
    +
    315 this->interval.end = (this->interval.start = start) + 1;
    +
    316 return true;
    +
    317 }
    +
    318 }
    +
    319 this->interval.start = (this->interval.end = start) + 1;
    +
    320 return false;
    +
    321 }
    +
    322
    +
    323 protected:
    +
    324 T m_chr;
    +
    325 bool m_invert;
    +
    326 };
    -
    325
    -
    326 using cu = basic_cu<char>;
    -
    327 using wcu = basic_cu<wchar_t>;
    -
    328#ifdef _UNICODE
    -
    329 using tcu = wcu;
    -
    330#else
    -
    331 using tcu = cu;
    -
    332#endif
    -
    333
    -
    -
    337 class sgml_cp : public sgml_parser
    -
    338 {
    -
    339 public:
    -
    340 sgml_cp(const char* chr, size_t count = (size_t)-1, bool invert = false, _In_ const std::locale& locale = std::locale()) :
    -
    341 sgml_parser(locale),
    -
    342 m_invert(invert)
    -
    343 {
    -
    344 assert(chr || !count);
    -
    345 wchar_t buf[3];
    -
    346 size_t chr_end;
    -
    347 m_chr.assign(count ? next_sgml_cp(chr, 0, count, chr_end, buf) : L"");
    -
    348 }
    -
    349
    -
    350 virtual bool match(
    -
    351 _In_reads_or_z_(end) const char* text,
    -
    352 _In_ size_t start = 0,
    -
    353 _In_ size_t end = (size_t)-1,
    -
    354 _In_ int flags = match_default)
    -
    355 {
    -
    356 assert(text || start >= end);
    -
    357 if (start < end && text[start]) {
    -
    358 wchar_t buf[3];
    -
    359 const wchar_t* chr = next_sgml_cp(text, start, end, interval.end, buf);
    -
    360 bool r = ((flags & match_case_insensitive) ?
    -
    361 stdex::strnicmp(chr, (size_t)-1, m_chr.c_str(), m_chr.size(), m_locale) :
    -
    362 stdex::strncmp(chr, (size_t)-1, m_chr.c_str(), m_chr.size())) == 0;
    -
    363 if (r && !m_invert || !r && m_invert) {
    -
    364 interval.start = start;
    -
    365 return true;
    -
    366 }
    -
    367 }
    -
    368 interval.start = (interval.end = start) + 1;
    -
    369 return false;
    -
    370 }
    -
    371
    -
    372 protected:
    -
    373 std::wstring m_chr;
    -
    374 bool m_invert;
    -
    375 };
    +
    327
    +
    328 using cu = basic_cu<char>;
    +
    329 using wcu = basic_cu<wchar_t>;
    +
    330#ifdef _UNICODE
    +
    331 using tcu = wcu;
    +
    332#else
    +
    333 using tcu = cu;
    +
    334#endif
    +
    335
    +
    +
    339 class sgml_cp : public sgml_parser
    +
    340 {
    +
    341 public:
    +
    342 sgml_cp(const char* chr, size_t count = (size_t)-1, bool invert = false, _In_ const std::locale& locale = std::locale()) :
    +
    343 sgml_parser(locale),
    +
    344 m_invert(invert)
    +
    345 {
    +
    346 assert(chr || !count);
    +
    347 wchar_t buf[3];
    +
    348 size_t chr_end;
    +
    349 m_chr.assign(count ? next_sgml_cp(chr, 0, count, chr_end, buf) : L"");
    +
    350 }
    +
    351
    +
    352 virtual bool match(
    +
    353 _In_reads_or_z_(end) const char* text,
    +
    354 _In_ size_t start = 0,
    +
    355 _In_ size_t end = (size_t)-1,
    +
    356 _In_ int flags = match_default)
    +
    357 {
    +
    358 assert(text || start >= end);
    +
    359 if (start < end && text[start]) {
    +
    360 wchar_t buf[3];
    +
    361 const wchar_t* chr = next_sgml_cp(text, start, end, this->interval.end, buf);
    +
    362 bool r = ((flags & match_case_insensitive) ?
    +
    363 stdex::strnicmp(chr, (size_t)-1, m_chr.c_str(), m_chr.size(), m_locale) :
    +
    364 stdex::strncmp(chr, (size_t)-1, m_chr.c_str(), m_chr.size())) == 0;
    +
    365 if ((r && !m_invert) || (!r && m_invert)) {
    +
    366 this->interval.start = start;
    +
    367 return true;
    +
    368 }
    +
    369 }
    +
    370 this->interval.start = (this->interval.end = start) + 1;
    +
    371 return false;
    +
    372 }
    +
    373
    +
    374 protected:
    +
    375 std::wstring m_chr;
    +
    376 bool m_invert;
    +
    377 };
    -
    376
    -
    380 template <class T>
    -
    -
    381 class basic_space_cu : public basic_parser<T>
    -
    382 {
    -
    383 public:
    -
    384 basic_space_cu(bool invert = false, _In_ const std::locale& locale = std::locale()) :
    -
    385 basic_parser<T>(locale),
    -
    386 m_invert(invert)
    -
    387 {}
    -
    388
    -
    389 virtual bool match(
    -
    390 _In_reads_or_z_(end) const T* text,
    -
    391 _In_ size_t start = 0,
    -
    392 _In_ size_t end = (size_t)-1,
    -
    393 _In_ int flags = match_default)
    -
    394 {
    -
    395 assert(text || start >= end);
    -
    396 if (start < end && text[start]) {
    -
    397 bool r =
    -
    398 ((flags & match_multiline) || !islbreak(text[start])) &&
    -
    399 std::use_facet<std::ctype<T>>(m_locale).is(std::ctype_base::space, text[start]);
    -
    400 if (r && !m_invert || !r && m_invert) {
    -
    401 interval.end = (interval.start = start) + 1;
    -
    402 return true;
    -
    403 }
    -
    404 }
    -
    405 interval.start = (interval.end = start) + 1;
    -
    406 return false;
    -
    407 }
    -
    408
    -
    409 protected:
    -
    410 bool m_invert;
    -
    411 };
    +
    378
    +
    382 template <class T>
    +
    +
    383 class basic_space_cu : public basic_parser<T>
    +
    384 {
    +
    385 public:
    +
    386 basic_space_cu(bool invert = false, _In_ const std::locale& locale = std::locale()) :
    +
    387 basic_parser<T>(locale),
    +
    388 m_invert(invert)
    +
    389 {}
    +
    390
    +
    391 virtual bool match(
    +
    392 _In_reads_or_z_(end) const T* text,
    +
    393 _In_ size_t start = 0,
    +
    394 _In_ size_t end = (size_t)-1,
    +
    395 _In_ int flags = match_default)
    +
    396 {
    +
    397 assert(text || start >= end);
    +
    398 if (start < end && text[start]) {
    +
    399 bool r =
    +
    400 ((flags & match_multiline) || !islbreak(text[start])) &&
    +
    401 std::use_facet<std::ctype<T>>(this->m_locale).is(std::ctype_base::space, text[start]);
    +
    402 if ((r && !m_invert) || (!r && m_invert)) {
    +
    403 this->interval.end = (this->interval.start = start) + 1;
    +
    404 return true;
    +
    405 }
    +
    406 }
    +
    407 this->interval.start = (this->interval.end = start) + 1;
    +
    408 return false;
    +
    409 }
    +
    410
    +
    411 protected:
    +
    412 bool m_invert;
    +
    413 };
    -
    412
    - - -
    415#ifdef _UNICODE
    -
    416 using tspace_cu = wspace_cu;
    -
    417#else
    -
    418 using tspace_cu = space_cu;
    -
    419#endif
    -
    420
    -
    -
    424 class sgml_space_cp : public basic_space_cu<char>
    -
    425 {
    -
    426 public:
    -
    427 sgml_space_cp(_In_ bool invert = false, _In_ const std::locale& locale = std::locale()) :
    - -
    429 {}
    -
    430
    -
    431 virtual bool match(
    -
    432 _In_reads_or_z_(end) const char* text,
    -
    433 _In_ size_t start = 0,
    -
    434 _In_ size_t end = (size_t)-1,
    -
    435 _In_ int flags = match_default)
    -
    436 {
    -
    437 assert(text || start >= end);
    -
    438 if (start < end && text[start]) {
    -
    439 wchar_t buf[3];
    -
    440 const wchar_t* chr = next_sgml_cp(text, start, end, interval.end, buf);
    -
    441 const wchar_t* chr_end = chr + stdex::strlen(chr);
    -
    442 bool r =
    -
    443 ((flags & match_multiline) || !islbreak(chr, (size_t)-1)) &&
    -
    444 std::use_facet<std::ctype<wchar_t>>(m_locale).scan_not(std::ctype_base::space, chr, chr_end) == chr_end;
    -
    445 if (r && !m_invert || !r && m_invert) {
    -
    446 interval.start = start;
    -
    447 return true;
    -
    448 }
    -
    449 }
    -
    450
    -
    451 interval.start = (interval.end = start) + 1;
    -
    452 return false;
    -
    453 }
    -
    454 };
    +
    414
    + + +
    417#ifdef _UNICODE
    +
    418 using tspace_cu = wspace_cu;
    +
    419#else
    +
    420 using tspace_cu = space_cu;
    +
    421#endif
    +
    422
    +
    +
    426 class sgml_space_cp : public basic_space_cu<char>
    +
    427 {
    +
    428 public:
    +
    429 sgml_space_cp(_In_ bool invert = false, _In_ const std::locale& locale = std::locale()) :
    + +
    431 {}
    +
    432
    +
    433 virtual bool match(
    +
    434 _In_reads_or_z_(end) const char* text,
    +
    435 _In_ size_t start = 0,
    +
    436 _In_ size_t end = (size_t)-1,
    +
    437 _In_ int flags = match_default)
    +
    438 {
    +
    439 assert(text || start >= end);
    +
    440 if (start < end && text[start]) {
    +
    441 wchar_t buf[3];
    +
    442 const wchar_t* chr = next_sgml_cp(text, start, end, this->interval.end, buf);
    +
    443 const wchar_t* chr_end = chr + stdex::strlen(chr);
    +
    444 bool r =
    +
    445 ((flags & match_multiline) || !islbreak(chr, (size_t)-1)) &&
    +
    446 std::use_facet<std::ctype<wchar_t>>(m_locale).scan_not(std::ctype_base::space, chr, chr_end) == chr_end;
    +
    447 if ((r && !m_invert) || (!r && m_invert)) {
    +
    448 this->interval.start = start;
    +
    449 return true;
    +
    450 }
    +
    451 }
    +
    452
    +
    453 this->interval.start = (this->interval.end = start) + 1;
    +
    454 return false;
    +
    455 }
    +
    456 };
    -
    455
    -
    459 template <class T>
    -
    -
    460 class basic_punct_cu : public basic_parser<T>
    -
    461 {
    -
    462 public:
    -
    463 basic_punct_cu(bool invert = false, _In_ const std::locale& locale = std::locale()) :
    -
    464 basic_parser<T>(locale),
    -
    465 m_invert(invert)
    -
    466 {}
    -
    467
    -
    468 virtual bool match(
    -
    469 _In_reads_or_z_(end) const T* text,
    -
    470 _In_ size_t start = 0,
    -
    471 _In_ size_t end = (size_t)-1,
    -
    472 _In_ int flags = match_default)
    -
    473 {
    -
    474 assert(text || start >= end);
    -
    475 if (start < end && text[start]) {
    -
    476 bool r = std::use_facet<std::ctype<T>>(m_locale).is(std::ctype_base::punct, text[start]);
    -
    477 if (r && !m_invert || !r && m_invert) {
    -
    478 interval.end = (interval.start = start) + 1;
    -
    479 return true;
    -
    480 }
    -
    481 }
    -
    482 interval.start = (interval.end = start) + 1;
    -
    483 return false;
    -
    484 }
    -
    485
    -
    486 protected:
    -
    487 bool m_invert;
    -
    488 };
    +
    457
    +
    461 template <class T>
    +
    +
    462 class basic_punct_cu : public basic_parser<T>
    +
    463 {
    +
    464 public:
    +
    465 basic_punct_cu(bool invert = false, _In_ const std::locale& locale = std::locale()) :
    +
    466 basic_parser<T>(locale),
    +
    467 m_invert(invert)
    +
    468 {}
    +
    469
    +
    470 virtual bool match(
    +
    471 _In_reads_or_z_(end) const T* text,
    +
    472 _In_ size_t start = 0,
    +
    473 _In_ size_t end = (size_t)-1,
    +
    474 _In_ int flags = match_default)
    +
    475 {
    +
    476 assert(text || start >= end);
    +
    477 if (start < end && text[start]) {
    +
    478 bool r = std::use_facet<std::ctype<T>>(this->m_locale).is(std::ctype_base::punct, text[start]);
    +
    479 if ((r && !m_invert) || (!r && m_invert)) {
    +
    480 this->interval.end = (this->interval.start = start) + 1;
    +
    481 return true;
    +
    482 }
    +
    483 }
    +
    484 this->interval.start = (this->interval.end = start) + 1;
    +
    485 return false;
    +
    486 }
    +
    487
    +
    488 protected:
    +
    489 bool m_invert;
    +
    490 };
    -
    489
    - - -
    492#ifdef _UNICODE
    -
    493 using tpunct_cu = wpunct_cu;
    -
    494#else
    -
    495 using tpunct_cu = punct_cu;
    -
    496#endif
    -
    497
    -
    -
    501 class sgml_punct_cp : public basic_punct_cu<char>
    -
    502 {
    -
    503 public:
    -
    504 sgml_punct_cp(bool invert = false, _In_ const std::locale& locale = std::locale()) :
    - -
    506 {}
    -
    507
    -
    508 virtual bool match(
    -
    509 _In_reads_or_z_(end) const char* text,
    -
    510 _In_ size_t start = 0,
    -
    511 _In_ size_t end = (size_t)-1,
    -
    512 _In_ int flags = match_default)
    -
    513 {
    -
    514 assert(text || start >= end);
    -
    515 if (start < end && text[start]) {
    -
    516 wchar_t buf[3];
    -
    517 const wchar_t* chr = next_sgml_cp(text, start, end, interval.end, buf);
    -
    518 const wchar_t* chr_end = chr + stdex::strlen(chr);
    -
    519 bool r = std::use_facet<std::ctype<wchar_t>>(m_locale).scan_not(std::ctype_base::punct, chr, chr_end) == chr_end;
    -
    520 if (r && !m_invert || !r && m_invert) {
    -
    521 interval.start = start;
    -
    522 return true;
    -
    523 }
    -
    524 }
    -
    525 interval.start = (interval.end = start) + 1;
    -
    526 return false;
    -
    527 }
    -
    528 };
    +
    491
    + + +
    494#ifdef _UNICODE
    +
    495 using tpunct_cu = wpunct_cu;
    +
    496#else
    +
    497 using tpunct_cu = punct_cu;
    +
    498#endif
    +
    499
    +
    +
    503 class sgml_punct_cp : public basic_punct_cu<char>
    +
    504 {
    +
    505 public:
    +
    506 sgml_punct_cp(bool invert = false, _In_ const std::locale& locale = std::locale()) :
    + +
    508 {}
    +
    509
    +
    510 virtual bool match(
    +
    511 _In_reads_or_z_(end) const char* text,
    +
    512 _In_ size_t start = 0,
    +
    513 _In_ size_t end = (size_t)-1,
    +
    514 _In_ int flags = match_default)
    +
    515 {
    +
    516 assert(text || start >= end);
    +
    517 if (start < end && text[start]) {
    +
    518 wchar_t buf[3];
    +
    519 const wchar_t* chr = next_sgml_cp(text, start, end, this->interval.end, buf);
    +
    520 const wchar_t* chr_end = chr + stdex::strlen(chr);
    +
    521 bool r = std::use_facet<std::ctype<wchar_t>>(m_locale).scan_not(std::ctype_base::punct, chr, chr_end) == chr_end;
    +
    522 if ((r && !m_invert) || (!r && m_invert)) {
    +
    523 this->interval.start = start;
    +
    524 return true;
    +
    525 }
    +
    526 }
    +
    527 this->interval.start = (this->interval.end = start) + 1;
    +
    528 return false;
    +
    529 }
    +
    530 };
    -
    529
    -
    533 template <class T>
    -
    - -
    535 {
    -
    536 public:
    -
    537 basic_space_or_punct_cu(bool invert = false, _In_ const std::locale& locale = std::locale()) :
    -
    538 basic_parser<T>(locale),
    -
    539 m_invert(invert)
    -
    540 {}
    -
    541
    -
    542 virtual bool match(
    -
    543 _In_reads_or_z_(end) const T* text,
    -
    544 _In_ size_t start = 0,
    -
    545 _In_ size_t end = (size_t)-1,
    -
    546 _In_ int flags = match_default)
    -
    547 {
    -
    548 assert(text || start >= end);
    -
    549 if (start < end && text[start]) {
    -
    550 bool r =
    -
    551 ((flags & match_multiline) || !islbreak(text[start])) &&
    -
    552 std::use_facet<std::ctype<T>>(m_locale).is(std::ctype_base::space | std::ctype_base::punct, text[start]);
    -
    553 if (r && !m_invert || !r && m_invert) {
    -
    554 interval.end = (interval.start = start) + 1;
    -
    555 return true;
    -
    556 }
    -
    557 }
    -
    558 interval.start = (interval.end = start) + 1;
    -
    559 return false;
    -
    560 }
    -
    561
    -
    562 protected:
    -
    563 bool m_invert;
    -
    564 };
    +
    531
    +
    535 template <class T>
    +
    + +
    537 {
    +
    538 public:
    +
    539 basic_space_or_punct_cu(bool invert = false, _In_ const std::locale& locale = std::locale()) :
    +
    540 basic_parser<T>(locale),
    +
    541 m_invert(invert)
    +
    542 {}
    +
    543
    +
    544 virtual bool match(
    +
    545 _In_reads_or_z_(end) const T* text,
    +
    546 _In_ size_t start = 0,
    +
    547 _In_ size_t end = (size_t)-1,
    +
    548 _In_ int flags = match_default)
    +
    549 {
    +
    550 assert(text || start >= end);
    +
    551 if (start < end && text[start]) {
    +
    552 bool r =
    +
    553 ((flags & match_multiline) || !islbreak(text[start])) &&
    +
    554 std::use_facet<std::ctype<T>>(this->m_locale).is(std::ctype_base::space | std::ctype_base::punct, text[start]);
    +
    555 if ((r && !m_invert) || (!r && m_invert)) {
    +
    556 this->interval.end = (this->interval.start = start) + 1;
    +
    557 return true;
    +
    558 }
    +
    559 }
    +
    560 this->interval.start = (this->interval.end = start) + 1;
    +
    561 return false;
    +
    562 }
    +
    563
    +
    564 protected:
    +
    565 bool m_invert;
    +
    566 };
    -
    565
    - - -
    568#ifdef _UNICODE
    - -
    570#else
    - -
    572#endif
    -
    573
    -
    - -
    578 {
    -
    579 public:
    -
    580 sgml_space_or_punct_cp(bool invert = false, _In_ const std::locale& locale = std::locale()) :
    - -
    582 {}
    -
    583
    -
    584 virtual bool match(
    -
    585 _In_reads_or_z_(end) const char* text,
    -
    586 _In_ size_t start = 0,
    -
    587 _In_ size_t end = (size_t)-1,
    -
    588 _In_ int flags = match_default)
    -
    589 {
    -
    590 assert(text || start >= end);
    -
    591 if (start < end && text[start]) {
    -
    592 wchar_t buf[3];
    -
    593 const wchar_t* chr = next_sgml_cp(text, start, end, interval.end, buf);
    -
    594 const wchar_t* chr_end = chr + stdex::strlen(chr);
    -
    595 bool r =
    -
    596 ((flags & match_multiline) || !islbreak(chr, (size_t)-1)) &&
    -
    597 std::use_facet<std::ctype<wchar_t>>(m_locale).scan_not(std::ctype_base::space | std::ctype_base::punct, chr, chr_end) == chr_end;
    -
    598 if (r && !m_invert || !r && m_invert) {
    -
    599 interval.start = start;
    -
    600 return true;
    -
    601 }
    -
    602 }
    -
    603 interval.start = (interval.end = start) + 1;
    -
    604 return false;
    -
    605 }
    -
    606 };
    +
    567
    + + +
    570#ifdef _UNICODE
    + +
    572#else
    + +
    574#endif
    +
    575
    +
    + +
    580 {
    +
    581 public:
    +
    582 sgml_space_or_punct_cp(bool invert = false, _In_ const std::locale& locale = std::locale()) :
    + +
    584 {}
    +
    585
    +
    586 virtual bool match(
    +
    587 _In_reads_or_z_(end) const char* text,
    +
    588 _In_ size_t start = 0,
    +
    589 _In_ size_t end = (size_t)-1,
    +
    590 _In_ int flags = match_default)
    +
    591 {
    +
    592 assert(text || start >= end);
    +
    593 if (start < end && text[start]) {
    +
    594 wchar_t buf[3];
    +
    595 const wchar_t* chr = next_sgml_cp(text, start, end, this->interval.end, buf);
    +
    596 const wchar_t* chr_end = chr + stdex::strlen(chr);
    +
    597 bool r =
    +
    598 ((flags & match_multiline) || !islbreak(chr, (size_t)-1)) &&
    +
    599 std::use_facet<std::ctype<wchar_t>>(m_locale).scan_not(std::ctype_base::space | std::ctype_base::punct, chr, chr_end) == chr_end;
    +
    600 if ((r && !m_invert) || (!r && m_invert)) {
    +
    601 this->interval.start = start;
    +
    602 return true;
    +
    603 }
    +
    604 }
    +
    605 this->interval.start = (this->interval.end = start) + 1;
    +
    606 return false;
    +
    607 }
    +
    608 };
    -
    607
    -
    611 template <class T>
    -
    -
    612 class basic_bol : public basic_parser<T>
    -
    613 {
    -
    614 public:
    -
    615 basic_bol(bool invert = false) : m_invert(invert) {}
    -
    616
    -
    617 virtual bool match(
    -
    618 _In_reads_or_z_(end) const T* text,
    -
    619 _In_ size_t start = 0,
    -
    620 _In_ size_t end = (size_t)-1,
    -
    621 _In_ int flags = match_default)
    -
    622 {
    -
    623 assert(text || start >= end);
    -
    624 bool r = start == 0 || start <= end && islbreak(text[start - 1]);
    -
    625 if (r && !m_invert || !r && m_invert) {
    -
    626 interval.end = interval.start = start;
    -
    627 return true;
    -
    628 }
    -
    629 interval.start = (interval.end = start) + 1;
    -
    630 return false;
    -
    631 }
    -
    632
    -
    633 protected:
    -
    634 bool m_invert;
    -
    635 };
    +
    609
    +
    613 template <class T>
    +
    +
    614 class basic_bol : public basic_parser<T>
    +
    615 {
    +
    616 public:
    +
    617 basic_bol(bool invert = false) : m_invert(invert) {}
    +
    618
    +
    619 virtual bool match(
    +
    620 _In_reads_or_z_(end) const T* text,
    +
    621 _In_ size_t start = 0,
    +
    622 _In_ size_t end = (size_t)-1,
    +
    623 _In_ int flags = match_default)
    +
    624 {
    +
    625 assert(text || start >= end);
    +
    626 bool r = start == 0 || (start <= end && islbreak(text[start - 1]));
    +
    627 if ((r && !m_invert) || (!r && m_invert)) {
    +
    628 this->interval.end = this->interval.start = start;
    +
    629 return true;
    +
    630 }
    +
    631 this->interval.start = (this->interval.end = start) + 1;
    +
    632 return false;
    +
    633 }
    +
    634
    +
    635 protected:
    +
    636 bool m_invert;
    +
    637 };
    -
    636
    -
    637 using bol = basic_bol<char>;
    -
    638 using wbol = basic_bol<wchar_t>;
    -
    639#ifdef _UNICODE
    -
    640 using tbol = wbol;
    -
    641#else
    -
    642 using tbol = bol;
    -
    643#endif
    - -
    645
    -
    649 template <class T>
    -
    -
    650 class basic_eol : public basic_parser<T>
    -
    651 {
    -
    652 public:
    -
    653 basic_eol(bool invert = false) : m_invert(invert) {}
    -
    654
    -
    655 virtual bool match(
    -
    656 _In_reads_or_z_(end) const T* text,
    -
    657 _In_ size_t start = 0,
    -
    658 _In_ size_t end = (size_t)-1,
    -
    659 _In_ int flags = match_default)
    -
    660 {
    -
    661 assert(text || start >= end);
    -
    662 bool r = islbreak(text[start]);
    -
    663 if (r && !m_invert || !r && m_invert) {
    -
    664 interval.end = interval.start = start;
    -
    665 return true;
    -
    666 }
    -
    667 interval.start = (interval.end = start) + 1;
    -
    668 return false;
    -
    669 }
    -
    670
    -
    671 protected:
    -
    672 bool m_invert;
    -
    673 };
    +
    638
    +
    639 using bol = basic_bol<char>;
    +
    640 using wbol = basic_bol<wchar_t>;
    +
    641#ifdef _UNICODE
    +
    642 using tbol = wbol;
    +
    643#else
    +
    644 using tbol = bol;
    +
    645#endif
    + +
    647
    +
    651 template <class T>
    +
    +
    652 class basic_eol : public basic_parser<T>
    +
    653 {
    +
    654 public:
    +
    655 basic_eol(bool invert = false) : m_invert(invert) {}
    +
    656
    +
    657 virtual bool match(
    +
    658 _In_reads_or_z_(end) const T* text,
    +
    659 _In_ size_t start = 0,
    +
    660 _In_ size_t end = (size_t)-1,
    +
    661 _In_ int flags = match_default)
    +
    662 {
    +
    663 assert(text || start >= end);
    +
    664 bool r = islbreak(text[start]);
    +
    665 if ((r && !m_invert) || (!r && m_invert)) {
    +
    666 this->interval.end = this->interval.start = start;
    +
    667 return true;
    +
    668 }
    +
    669 this->interval.start = (this->interval.end = start) + 1;
    +
    670 return false;
    +
    671 }
    +
    672
    +
    673 protected:
    +
    674 bool m_invert;
    +
    675 };
    -
    674
    -
    675 using eol = basic_eol<char>;
    -
    676 using weol = basic_eol<wchar_t>;
    -
    677#ifdef _UNICODE
    -
    678 using teol = weol;
    -
    679#else
    -
    680 using teol = eol;
    -
    681#endif
    - -
    683
    -
    684 template <class T>
    -
    -
    685 class basic_set : public basic_parser<T>
    -
    686 {
    -
    687 public:
    -
    688 basic_set(bool invert = false, _In_ const std::locale& locale = std::locale()) :
    -
    689 basic_parser<T>(locale),
    -
    690 hit_offset((size_t)-1),
    -
    691 m_invert(invert)
    -
    692 {}
    -
    693
    -
    694 virtual bool match(
    -
    695 _In_reads_or_z_(end) const T* text,
    -
    696 _In_ size_t start = 0,
    -
    697 _In_ size_t end = (size_t)-1,
    -
    698 _In_ int flags = match_default) = 0;
    -
    699
    -
    700 virtual void invalidate()
    -
    701 {
    -
    702 hit_offset = (size_t)-1;
    - -
    704 }
    -
    705
    -
    706 public:
    -
    707 size_t hit_offset;
    -
    708
    -
    709 protected:
    -
    710 bool m_invert;
    -
    711 };
    +
    676
    +
    677 using eol = basic_eol<char>;
    +
    678 using weol = basic_eol<wchar_t>;
    +
    679#ifdef _UNICODE
    +
    680 using teol = weol;
    +
    681#else
    +
    682 using teol = eol;
    +
    683#endif
    + +
    685
    +
    686 template <class T>
    +
    +
    687 class basic_set : public basic_parser<T>
    +
    688 {
    +
    689 public:
    +
    690 basic_set(bool invert = false, _In_ const std::locale& locale = std::locale()) :
    +
    691 basic_parser<T>(locale),
    +
    692 hit_offset((size_t)-1),
    +
    693 m_invert(invert)
    +
    694 {}
    +
    695
    +
    696 virtual bool match(
    +
    697 _In_reads_or_z_(end) const T* text,
    +
    698 _In_ size_t start = 0,
    +
    699 _In_ size_t end = (size_t)-1,
    +
    700 _In_ int flags = match_default) = 0;
    +
    701
    +
    702 virtual void invalidate()
    +
    703 {
    +
    704 hit_offset = (size_t)-1;
    + +
    706 }
    +
    707
    +
    708 public:
    +
    709 size_t hit_offset;
    +
    710
    +
    711 protected:
    +
    712 bool m_invert;
    +
    713 };
    -
    712
    -
    716 template <class T>
    -
    -
    717 class basic_cu_set : public basic_set<T>
    -
    718 {
    -
    719 public:
    - -
    721 _In_reads_or_z_(count) const T* set,
    -
    722 _In_ size_t count = (size_t)-1,
    -
    723 _In_ bool invert = false,
    -
    724 _In_ const std::locale& locale = std::locale()) :
    -
    725 basic_set<T>(invert, locale)
    -
    726 {
    -
    727 if (set)
    -
    728 m_set.assign(set, set + stdex::strnlen(set, count));
    -
    729 }
    -
    730
    -
    731 virtual bool match(
    -
    732 _In_reads_or_z_(end) const T* text,
    -
    733 _In_ size_t start = 0,
    -
    734 _In_ size_t end = (size_t)-1,
    -
    735 _In_ int flags = match_default)
    -
    736 {
    -
    737 assert(text || start >= end);
    -
    738 if (start < end && text[start]) {
    -
    739 const T* set = m_set.c_str();
    -
    740 size_t r = (flags & match_case_insensitive) ?
    -
    741 stdex::strnichr(set, m_set.size(), text[start], m_locale) :
    -
    742 stdex::strnchr(set, m_set.size(), text[start]);
    -
    743 if (r != stdex::npos && !m_invert || r == stdex::npos && m_invert) {
    -
    744 hit_offset = r;
    -
    745 interval.end = (interval.start = start) + 1;
    -
    746 return true;
    -
    747 }
    -
    748 }
    -
    749 hit_offset = (size_t)-1;
    -
    750 interval.start = (interval.end = start) + 1;
    -
    751 return false;
    -
    752 }
    -
    753
    -
    754 protected:
    -
    755 std::basic_string<T> m_set;
    -
    756 };
    +
    714
    +
    718 template <class T>
    +
    +
    719 class basic_cu_set : public basic_set<T>
    +
    720 {
    +
    721 public:
    + +
    723 _In_reads_or_z_(count) const T* set,
    +
    724 _In_ size_t count = (size_t)-1,
    +
    725 _In_ bool invert = false,
    +
    726 _In_ const std::locale& locale = std::locale()) :
    +
    727 basic_set<T>(invert, locale)
    +
    728 {
    +
    729 if (set)
    +
    730 m_set.assign(set, set + stdex::strnlen(set, count));
    +
    731 }
    +
    732
    +
    733 virtual bool match(
    +
    734 _In_reads_or_z_(end) const T* text,
    +
    735 _In_ size_t start = 0,
    +
    736 _In_ size_t end = (size_t)-1,
    +
    737 _In_ int flags = match_default)
    +
    738 {
    +
    739 assert(text || start >= end);
    +
    740 if (start < end && text[start]) {
    +
    741 const T* set = m_set.c_str();
    +
    742 size_t r = (flags & match_case_insensitive) ?
    +
    743 stdex::strnichr(set, m_set.size(), text[start], this->m_locale) :
    +
    744 stdex::strnchr(set, m_set.size(), text[start]);
    +
    745 if ((r != stdex::npos && !this->m_invert) || (r == stdex::npos && this->m_invert)) {
    +
    746 this->hit_offset = r;
    +
    747 this->interval.end = (this->interval.start = start) + 1;
    +
    748 return true;
    +
    749 }
    +
    750 }
    +
    751 this->hit_offset = (size_t)-1;
    +
    752 this->interval.start = (this->interval.end = start) + 1;
    +
    753 return false;
    +
    754 }
    +
    755
    +
    756 protected:
    +
    757 std::basic_string<T> m_set;
    +
    758 };
    -
    757
    - - -
    760#ifdef _UNICODE
    -
    761 using tcu_set = wcu_set;
    -
    762#else
    -
    763 using tcu_set = cu_set;
    -
    764#endif
    -
    765
    -
    -
    769 class sgml_cp_set : public basic_set<char>
    -
    770 {
    -
    771 public:
    -
    772 sgml_cp_set(const char* set, size_t count = (size_t)-1, bool invert = false, _In_ const std::locale& locale = std::locale()) :
    -
    773 basic_set<char>(invert, locale)
    -
    774 {
    -
    775 if (set)
    -
    776 m_set = sgml2wstr(set, count);
    -
    777 }
    -
    778
    -
    779 virtual bool match(
    -
    780 _In_reads_or_z_(end) const char* text,
    -
    781 _In_ size_t start = 0,
    -
    782 _In_ size_t end = (size_t)-1,
    -
    783 _In_ int flags = match_default)
    -
    784 {
    -
    785 assert(text || start >= end);
    -
    786 if (start < end && text[start]) {
    -
    787 wchar_t buf[3];
    -
    788 const wchar_t* chr = next_sgml_cp(text, start, end, interval.end, buf);
    -
    789 const wchar_t* set = m_set.c_str();
    -
    790 size_t r = (flags & match_case_insensitive) ?
    -
    791 stdex::strnistr(set, m_set.size(), chr, m_locale) :
    -
    792 stdex::strnstr(set, m_set.size(), chr);
    -
    793 if (r != stdex::npos && !m_invert || r == stdex::npos && m_invert) {
    -
    794 hit_offset = r;
    -
    795 interval.start = start;
    -
    796 return true;
    -
    797 }
    -
    798 }
    -
    799 hit_offset = (size_t)-1;
    -
    800 interval.start = (interval.end = start) + 1;
    -
    801 return false;
    -
    802 }
    -
    803
    -
    804 protected:
    -
    805 std::wstring m_set;
    -
    806 };
    +
    759
    + + +
    762#ifdef _UNICODE
    +
    763 using tcu_set = wcu_set;
    +
    764#else
    +
    765 using tcu_set = cu_set;
    +
    766#endif
    +
    767
    +
    +
    771 class sgml_cp_set : public basic_set<char>
    +
    772 {
    +
    773 public:
    +
    774 sgml_cp_set(const char* set, size_t count = (size_t)-1, bool invert = false, _In_ const std::locale& locale = std::locale()) :
    +
    775 basic_set<char>(invert, locale)
    +
    776 {
    +
    777 if (set)
    +
    778 m_set = sgml2wstr(set, count);
    +
    779 }
    +
    780
    +
    781 virtual bool match(
    +
    782 _In_reads_or_z_(end) const char* text,
    +
    783 _In_ size_t start = 0,
    +
    784 _In_ size_t end = (size_t)-1,
    +
    785 _In_ int flags = match_default)
    +
    786 {
    +
    787 assert(text || start >= end);
    +
    788 if (start < end && text[start]) {
    +
    789 wchar_t buf[3];
    +
    790 const wchar_t* chr = next_sgml_cp(text, start, end, this->interval.end, buf);
    +
    791 const wchar_t* set = m_set.c_str();
    +
    792 size_t r = (flags & match_case_insensitive) ?
    +
    793 stdex::strnistr(set, m_set.size(), chr, m_locale) :
    +
    794 stdex::strnstr(set, m_set.size(), chr);
    +
    795 if ((r != stdex::npos && !m_invert) || (r == stdex::npos && m_invert)) {
    +
    796 hit_offset = r;
    +
    797 this->interval.start = start;
    +
    798 return true;
    +
    799 }
    +
    800 }
    +
    801 hit_offset = (size_t)-1;
    +
    802 this->interval.start = (this->interval.end = start) + 1;
    +
    803 return false;
    +
    804 }
    +
    805
    +
    806 protected:
    +
    807 std::wstring m_set;
    +
    808 };
    -
    807
    -
    811 template <class T>
    -
    -
    812 class basic_string : public basic_parser<T>
    -
    813 {
    -
    814 public:
    - -
    816 _In_reads_or_z_(count) const T* str,
    -
    817 _In_ size_t count = (size_t)-1,
    -
    818 _In_ const std::locale& locale = std::locale()) :
    -
    819 basic_parser<T>(locale),
    -
    820 m_str(str, str + stdex::strnlen(str, count))
    -
    821 {}
    -
    822
    -
    823 virtual bool match(
    -
    824 _In_reads_or_z_(end) const T* text,
    -
    825 _In_ size_t start = 0,
    -
    826 _In_ size_t end = (size_t)-1,
    -
    827 _In_ int flags = match_default)
    -
    828 {
    -
    829 assert(text || start >= end);
    -
    830 size_t
    -
    831 m = m_str.size(),
    -
    832 n = std::min<size_t>(end - start, m);
    -
    833 bool r = ((flags & match_case_insensitive) ?
    -
    834 stdex::strnicmp(text + start, n, m_str.c_str(), m, m_locale) :
    -
    835 stdex::strncmp(text + start, n, m_str.c_str(), m)) == 0;
    -
    836 if (r) {
    -
    837 interval.end = (interval.start = start) + n;
    -
    838 return true;
    -
    839 }
    -
    840 interval.start = (interval.end = start) + 1;
    -
    841 return false;
    -
    842 }
    -
    843
    -
    844 protected:
    -
    845 std::basic_string<T> m_str;
    -
    846 };
    +
    809
    +
    813 template <class T>
    +
    +
    814 class basic_string : public basic_parser<T>
    +
    815 {
    +
    816 public:
    + +
    818 _In_reads_or_z_(count) const T* str,
    +
    819 _In_ size_t count = (size_t)-1,
    +
    820 _In_ const std::locale& locale = std::locale()) :
    +
    821 basic_parser<T>(locale),
    +
    822 m_str(str, str + stdex::strnlen(str, count))
    +
    823 {}
    +
    824
    +
    825 virtual bool match(
    +
    826 _In_reads_or_z_(end) const T* text,
    +
    827 _In_ size_t start = 0,
    +
    828 _In_ size_t end = (size_t)-1,
    +
    829 _In_ int flags = match_default)
    +
    830 {
    +
    831 assert(text || start >= end);
    +
    832 size_t
    +
    833 m = m_str.size(),
    +
    834 n = std::min<size_t>(end - start, m);
    +
    835 bool r = ((flags & match_case_insensitive) ?
    +
    836 stdex::strnicmp(text + start, n, m_str.c_str(), m, this->m_locale) :
    +
    837 stdex::strncmp(text + start, n, m_str.c_str(), m)) == 0;
    +
    838 if (r) {
    +
    839 this->interval.end = (this->interval.start = start) + n;
    +
    840 return true;
    +
    841 }
    +
    842 this->interval.start = (this->interval.end = start) + 1;
    +
    843 return false;
    +
    844 }
    +
    845
    +
    846 protected:
    +
    847 std::basic_string<T> m_str;
    +
    848 };
    -
    847
    - - -
    850#ifdef _UNICODE
    -
    851 using tstring = wstring;
    -
    852#else
    -
    853 using tstring = string;
    -
    854#endif
    -
    855
    -
    - -
    860 {
    -
    861 public:
    -
    862 sgml_string(const char* str, size_t count = (size_t)-1, _In_ const std::locale& locale = std::locale()) :
    -
    863 sgml_parser(locale),
    -
    864 m_str(sgml2wstr(str, count))
    -
    865 {}
    -
    866
    -
    867 virtual bool match(
    -
    868 _In_reads_or_z_(end) const char* text,
    -
    869 _In_ size_t start = 0,
    -
    870 _In_ size_t end = (size_t)-1,
    -
    871 _In_ int flags = match_default)
    -
    872 {
    -
    873 assert(text || start >= end);
    -
    874 const wchar_t* str = m_str.c_str();
    -
    875 const bool case_insensitive = flags & match_case_insensitive ? true : false;
    -
    876 const auto& ctype = std::use_facet<std::ctype<wchar_t>>(m_locale);
    -
    877 for (interval.end = start;;) {
    -
    878 if (!*str) {
    -
    879 interval.start = start;
    -
    880 return true;
    -
    881 }
    -
    882 if (interval.end >= end || !text[interval.end]) {
    -
    883 interval.start = (interval.end = start) + 1;
    -
    884 return false;
    -
    885 }
    -
    886 wchar_t buf[3];
    -
    887 const wchar_t* chr = next_sgml_cp(text, interval.end, end, interval.end, buf);
    -
    888 for (; *chr; ++str, ++chr) {
    -
    889 if (!*str ||
    -
    890 (case_insensitive ? ctype.tolower(*str) != ctype.tolower(*chr) : *str != *chr))
    -
    891 {
    -
    892 interval.start = (interval.end = start) + 1;
    -
    893 return false;
    -
    894 }
    -
    895 }
    -
    896 }
    -
    897 }
    -
    898
    -
    899 protected:
    -
    900 std::wstring m_str;
    -
    901 };
    +
    849
    + + +
    852#ifdef _UNICODE
    +
    853 using tstring = wstring;
    +
    854#else
    +
    855 using tstring = string;
    +
    856#endif
    +
    857
    +
    + +
    862 {
    +
    863 public:
    +
    864 sgml_string(const char* str, size_t count = (size_t)-1, _In_ const std::locale& locale = std::locale()) :
    +
    865 sgml_parser(locale),
    +
    866 m_str(sgml2wstr(str, count))
    +
    867 {}
    +
    868
    +
    869 virtual bool match(
    +
    870 _In_reads_or_z_(end) const char* text,
    +
    871 _In_ size_t start = 0,
    +
    872 _In_ size_t end = (size_t)-1,
    +
    873 _In_ int flags = match_default)
    +
    874 {
    +
    875 assert(text || start >= end);
    +
    876 const wchar_t* str = m_str.c_str();
    +
    877 const bool case_insensitive = flags & match_case_insensitive ? true : false;
    +
    878 const auto& ctype = std::use_facet<std::ctype<wchar_t>>(m_locale);
    +
    879 for (this->interval.end = start;;) {
    +
    880 if (!*str) {
    +
    881 this->interval.start = start;
    +
    882 return true;
    +
    883 }
    +
    884 if (this->interval.end >= end || !text[this->interval.end]) {
    +
    885 this->interval.start = (this->interval.end = start) + 1;
    +
    886 return false;
    +
    887 }
    +
    888 wchar_t buf[3];
    +
    889 const wchar_t* chr = next_sgml_cp(text, this->interval.end, end, this->interval.end, buf);
    +
    890 for (; *chr; ++str, ++chr) {
    +
    891 if (!*str ||
    +
    892 (case_insensitive ? ctype.tolower(*str) != ctype.tolower(*chr) : *str != *chr))
    +
    893 {
    +
    894 this->interval.start = (this->interval.end = start) + 1;
    +
    895 return false;
    +
    896 }
    +
    897 }
    +
    898 }
    +
    899 }
    +
    900
    +
    901 protected:
    +
    902 std::wstring m_str;
    +
    903 };
    -
    902
    -
    906 template <class T>
    -
    - -
    908 {
    -
    909 public:
    -
    910 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) :
    -
    911 m_el(el),
    - - - -
    915 {}
    -
    916
    -
    917 virtual bool match(
    -
    918 _In_reads_or_z_(end) const T* text,
    -
    919 _In_ size_t start = 0,
    -
    920 _In_ size_t end = (size_t)-1,
    -
    921 _In_ int flags = match_default)
    -
    922 {
    -
    923 assert(text || start >= end);
    -
    924 interval.start = interval.end = start;
    -
    925 for (size_t i = 0; ; i++) {
    - -
    927 return true;
    -
    928 if (!m_el->match(text, interval.end, end, flags)) {
    -
    929 if (i >= m_min_iterations)
    -
    930 return true;
    -
    931 break;
    -
    932 }
    -
    933 if (m_el->interval.end == interval.end) {
    -
    934 // Element did match, but the matching interval was empty. Quit instead of spinning.
    -
    935 return true;
    -
    936 }
    -
    937 interval.end = m_el->interval.end;
    -
    938 }
    -
    939 interval.start = (interval.end = start) + 1;
    -
    940 return false;
    -
    941 }
    -
    942
    -
    943 protected:
    -
    944 std::shared_ptr<basic_parser<T>> m_el;
    - - -
    947 bool m_greedy;
    -
    948 };
    +
    904
    +
    908 template <class T>
    +
    + +
    910 {
    +
    911 public:
    +
    912 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) :
    +
    913 m_el(el),
    + + + +
    917 {}
    +
    918
    +
    919 virtual bool match(
    +
    920 _In_reads_or_z_(end) const T* text,
    +
    921 _In_ size_t start = 0,
    +
    922 _In_ size_t end = (size_t)-1,
    +
    923 _In_ int flags = match_default)
    +
    924 {
    +
    925 assert(text || start >= end);
    +
    926 this->interval.start = this->interval.end = start;
    +
    927 for (size_t i = 0; ; i++) {
    +
    928 if ((!m_greedy && i >= m_min_iterations) || i >= m_max_iterations)
    +
    929 return true;
    +
    930 if (!m_el->match(text, this->interval.end, end, flags)) {
    +
    931 if (i >= m_min_iterations)
    +
    932 return true;
    +
    933 break;
    +
    934 }
    +
    935 if (m_el->interval.end == this->interval.end) {
    +
    936 // Element did match, but the matching interval was empty. Quit instead of spinning.
    +
    937 return true;
    +
    938 }
    +
    939 this->interval.end = m_el->interval.end;
    +
    940 }
    +
    941 this->interval.start = (this->interval.end = start) + 1;
    +
    942 return false;
    +
    943 }
    +
    944
    +
    945 protected:
    +
    946 std::shared_ptr<basic_parser<T>> m_el;
    + + +
    949 bool m_greedy;
    +
    950 };
    -
    949
    - - -
    952#ifdef _UNICODE
    -
    953 using titerations = witerations;
    -
    954#else
    -
    955 using titerations = iterations;
    -
    956#endif
    - -
    958
    -
    962 template <class T>
    -
    - -
    964 {
    -
    965 protected:
    -
    966 parser_collection(_In_ const std::locale& locale) : basic_parser<T>(locale) {}
    -
    967
    -
    968 public:
    - -
    970 _In_count_(count) const std::shared_ptr<basic_parser<T>>* el,
    -
    971 _In_ size_t count,
    -
    972 _In_ const std::locale& locale = std::locale()) :
    -
    973 basic_parser<T>(locale)
    -
    974 {
    -
    975 assert(el || !count);
    -
    976 m_collection.reserve(count);
    -
    977 for (size_t i = 0; i < count; i++)
    -
    978 m_collection.push_back(el[i]);
    -
    979 }
    -
    980
    - -
    982 _Inout_ std::vector<std::shared_ptr<basic_parser<T>>>&& collection,
    -
    983 _In_ const std::locale& locale = std::locale()) :
    -
    984 basic_parser<T>(locale),
    -
    985 m_collection(std::move(collection))
    -
    986 {}
    -
    987
    -
    988 virtual void invalidate()
    -
    989 {
    -
    990 for (auto& el: m_collection)
    -
    991 el->invalidate();
    - -
    993 }
    -
    994
    -
    995 protected:
    -
    996 std::vector<std::shared_ptr<basic_parser<T>>> m_collection;
    -
    997 };
    +
    951
    + + +
    954#ifdef _UNICODE
    +
    955 using titerations = witerations;
    +
    956#else
    +
    957 using titerations = iterations;
    +
    958#endif
    + +
    960
    +
    964 template <class T>
    +
    + +
    966 {
    +
    967 protected:
    +
    968 parser_collection(_In_ const std::locale& locale) : basic_parser<T>(locale) {}
    +
    969
    +
    970 public:
    + +
    972 _In_count_(count) const std::shared_ptr<basic_parser<T>>* el,
    +
    973 _In_ size_t count,
    +
    974 _In_ const std::locale& locale = std::locale()) :
    +
    975 basic_parser<T>(locale)
    +
    976 {
    +
    977 assert(el || !count);
    +
    978 m_collection.reserve(count);
    +
    979 for (size_t i = 0; i < count; i++)
    +
    980 m_collection.push_back(el[i]);
    +
    981 }
    +
    982
    + +
    984 _Inout_ std::vector<std::shared_ptr<basic_parser<T>>>&& collection,
    +
    985 _In_ const std::locale& locale = std::locale()) :
    +
    986 basic_parser<T>(locale),
    +
    987 m_collection(std::move(collection))
    +
    988 {}
    +
    989
    +
    990 virtual void invalidate()
    +
    991 {
    +
    992 for (auto& el: m_collection)
    +
    993 el->invalidate();
    + +
    995 }
    +
    996
    +
    997 protected:
    +
    998 std::vector<std::shared_ptr<basic_parser<T>>> m_collection;
    +
    999 };
    -
    998
    -
    1002 template <class T>
    -
    - -
    1004 {
    -
    1005 public:
    - -
    1007 _In_count_(count) const std::shared_ptr<basic_parser<T>>* el = nullptr,
    -
    1008 _In_ size_t count = 0,
    -
    1009 _In_ const std::locale& locale = std::locale()) :
    -
    1010 parser_collection<T>(el, count, locale)
    -
    1011 {}
    -
    1012
    - -
    1014 _Inout_ std::vector<std::shared_ptr<basic_parser<T>>>&& collection,
    -
    1015 _In_ const std::locale& locale = std::locale()) :
    -
    1016 parser_collection<T>(std::move(collection), locale)
    -
    1017 {}
    -
    1018
    -
    1019 virtual bool match(
    -
    1020 _In_reads_or_z_(end) const T* text,
    -
    1021 _In_ size_t start = 0,
    -
    1022 _In_ size_t end = (size_t)-1,
    -
    1023 _In_ int flags = match_default)
    -
    1024 {
    -
    1025 assert(text || start >= end);
    -
    1026 interval.end = start;
    -
    1027 for (auto i = m_collection.begin(); i != m_collection.end(); ++i) {
    -
    1028 if (!(*i)->match(text, interval.end, end, flags)) {
    -
    1029 for (++i; i != m_collection.end(); ++i)
    -
    1030 (*i)->invalidate();
    -
    1031 interval.start = (interval.end = start) + 1;
    -
    1032 return false;
    -
    1033 }
    -
    1034 interval.end = (*i)->interval.end;
    -
    1035 }
    -
    1036 interval.start = start;
    -
    1037 return true;
    -
    1038 }
    -
    1039 };
    +
    1000
    +
    1004 template <class T>
    +
    + +
    1006 {
    +
    1007 public:
    + +
    1009 _In_count_(count) const std::shared_ptr<basic_parser<T>>* el = nullptr,
    +
    1010 _In_ size_t count = 0,
    +
    1011 _In_ const std::locale& locale = std::locale()) :
    +
    1012 parser_collection<T>(el, count, locale)
    +
    1013 {}
    +
    1014
    + +
    1016 _Inout_ std::vector<std::shared_ptr<basic_parser<T>>>&& collection,
    +
    1017 _In_ const std::locale& locale = std::locale()) :
    +
    1018 parser_collection<T>(std::move(collection), locale)
    +
    1019 {}
    +
    1020
    +
    1021 virtual bool match(
    +
    1022 _In_reads_or_z_(end) const T* text,
    +
    1023 _In_ size_t start = 0,
    +
    1024 _In_ size_t end = (size_t)-1,
    +
    1025 _In_ int flags = match_default)
    +
    1026 {
    +
    1027 assert(text || start >= end);
    +
    1028 this->interval.end = start;
    +
    1029 for (auto i = this->m_collection.begin(); i != this->m_collection.end(); ++i) {
    +
    1030 if (!(*i)->match(text, this->interval.end, end, flags)) {
    +
    1031 for (++i; i != this->m_collection.end(); ++i)
    +
    1032 (*i)->invalidate();
    +
    1033 this->interval.start = (this->interval.end = start) + 1;
    +
    1034 return false;
    +
    1035 }
    +
    1036 this->interval.end = (*i)->interval.end;
    +
    1037 }
    +
    1038 this->interval.start = start;
    +
    1039 return true;
    +
    1040 }
    +
    1041 };
    -
    1040
    - - -
    1043#ifdef _UNICODE
    -
    1044 using tsequence = wsequence;
    -
    1045#else
    -
    1046 using tsequence = sequence;
    -
    1047#endif
    - -
    1049
    -
    1053 template <class T>
    -
    - -
    1055 {
    -
    1056 protected:
    -
    1057 basic_branch(_In_ const std::locale& locale) :
    -
    1058 parser_collection<T>(locale),
    -
    1059 hit_offset((size_t)-1)
    -
    1060 {}
    -
    1061
    -
    1062 public:
    - -
    1064 _In_count_(count) const std::shared_ptr<basic_parser<T>>* el = nullptr,
    -
    1065 _In_ size_t count = 0,
    -
    1066 _In_ const std::locale& locale = std::locale()) :
    -
    1067 parser_collection<T>(el, count, locale),
    -
    1068 hit_offset((size_t)-1)
    -
    1069 {}
    -
    1070
    - -
    1072 _Inout_ std::vector<std::shared_ptr<basic_parser<T>>>&& collection,
    -
    1073 _In_ const std::locale& locale = std::locale()) :
    -
    1074 parser_collection<T>(std::move(collection), locale),
    -
    1075 hit_offset((size_t)-1)
    -
    1076 {}
    -
    1077
    -
    1078 virtual bool match(
    -
    1079 _In_reads_or_z_(end) const T* text,
    -
    1080 _In_ size_t start = 0,
    -
    1081 _In_ size_t end = (size_t)-1,
    -
    1082 _In_ int flags = match_default)
    -
    1083 {
    -
    1084 assert(text || start >= end);
    -
    1085 hit_offset = 0;
    -
    1086 for (auto i = m_collection.begin(); i != m_collection.end(); ++i, ++hit_offset) {
    -
    1087 if ((*i)->match(text, start, end, flags)) {
    -
    1088 interval = (*i)->interval;
    -
    1089 for (++i; i != m_collection.end(); ++i)
    -
    1090 (*i)->invalidate();
    -
    1091 return true;
    -
    1092 }
    -
    1093 }
    -
    1094 hit_offset = (size_t)-1;
    -
    1095 interval.start = (interval.end = start) + 1;
    -
    1096 return false;
    -
    1097 }
    -
    1098
    -
    1099 virtual void invalidate()
    -
    1100 {
    -
    1101 hit_offset = (size_t)-1;
    - -
    1103 }
    -
    1104
    -
    1105 public:
    -
    1106 size_t hit_offset;
    -
    1107 };
    +
    1042
    + + +
    1045#ifdef _UNICODE
    +
    1046 using tsequence = wsequence;
    +
    1047#else
    +
    1048 using tsequence = sequence;
    +
    1049#endif
    + +
    1051
    +
    1055 template <class T>
    +
    + +
    1057 {
    +
    1058 protected:
    +
    1059 basic_branch(_In_ const std::locale& locale) :
    +
    1060 parser_collection<T>(locale),
    +
    1061 hit_offset((size_t)-1)
    +
    1062 {}
    +
    1063
    +
    1064 public:
    + +
    1066 _In_count_(count) const std::shared_ptr<basic_parser<T>>* el = nullptr,
    +
    1067 _In_ size_t count = 0,
    +
    1068 _In_ const std::locale& locale = std::locale()) :
    +
    1069 parser_collection<T>(el, count, locale),
    +
    1070 hit_offset((size_t)-1)
    +
    1071 {}
    +
    1072
    + +
    1074 _Inout_ std::vector<std::shared_ptr<basic_parser<T>>>&& collection,
    +
    1075 _In_ const std::locale& locale = std::locale()) :
    +
    1076 parser_collection<T>(std::move(collection), locale),
    +
    1077 hit_offset((size_t)-1)
    +
    1078 {}
    +
    1079
    +
    1080 virtual bool match(
    +
    1081 _In_reads_or_z_(end) const T* text,
    +
    1082 _In_ size_t start = 0,
    +
    1083 _In_ size_t end = (size_t)-1,
    +
    1084 _In_ int flags = match_default)
    +
    1085 {
    +
    1086 assert(text || start >= end);
    +
    1087 hit_offset = 0;
    +
    1088 for (auto i = this->m_collection.begin(); i != this->m_collection.end(); ++i, ++hit_offset) {
    +
    1089 if ((*i)->match(text, start, end, flags)) {
    +
    1090 this->interval = (*i)->interval;
    +
    1091 for (++i; i != this->m_collection.end(); ++i)
    +
    1092 (*i)->invalidate();
    +
    1093 return true;
    +
    1094 }
    +
    1095 }
    +
    1096 hit_offset = (size_t)-1;
    +
    1097 this->interval.start = (this->interval.end = start) + 1;
    +
    1098 return false;
    +
    1099 }
    +
    1100
    +
    1101 virtual void invalidate()
    +
    1102 {
    +
    1103 hit_offset = (size_t)-1;
    + +
    1105 }
    +
    1106
    +
    1107 public:
    +
    1108 size_t hit_offset;
    +
    1109 };
    -
    1108
    -
    1109 using branch = basic_branch<char>;
    - -
    1111#ifdef _UNICODE
    -
    1112 using tbranch = wbranch;
    -
    1113#else
    -
    1114 using tbranch = branch;
    -
    1115#endif
    - -
    1117
    -
    1121 template <class T, class T_parser = basic_string<T>>
    -
    - -
    1123 {
    -
    1124 public:
    -
    1125 inline basic_string_branch(
    -
    1126 _In_reads_(count) const T* str_z = nullptr,
    -
    1127 _In_ size_t count = 0,
    -
    1128 _In_ const std::locale& locale = std::locale()) :
    -
    1129 basic_branch<T>(locale)
    -
    1130 {
    -
    1131 build(str_z, count);
    -
    1132 }
    -
    1133
    -
    1134 inline basic_string_branch(_In_z_ const T* str, ...) :
    -
    1135 basic_branch<T>(std::locale())
    -
    1136 {
    -
    1137 va_list params;
    -
    1138 va_start(params, str);
    -
    1139 build(str, params);
    -
    1140 va_end(params);
    -
    1141 }
    -
    1142
    -
    1143 inline basic_string_branch(_In_ const std::locale& locale, _In_z_ const T* str, ...) :
    -
    1144 basic_branch<T>(locale)
    -
    1145 {
    -
    1146 va_list params;
    -
    1147 va_start(params, str);
    -
    1148 build(str, params);
    -
    1149 va_end(params);
    -
    1150 }
    -
    1151
    -
    1152 protected:
    -
    1153 void build(_In_reads_(count) const T* str_z, _In_ size_t count)
    -
    1154 {
    -
    1155 assert(str_z || !count);
    -
    1156 if (count) {
    -
    1157 size_t offset, n;
    -
    1158 for (
    -
    1159 offset = n = 0;
    -
    1160 offset < count && str_z[offset];
    -
    1161 offset += stdex::strnlen(str_z + offset, count - offset) + 1, ++n);
    -
    1162 m_collection.reserve(n);
    -
    1163 for (
    -
    1164 offset = 0;
    -
    1165 offset < count && str_z[offset];
    -
    1166 offset += stdex::strnlen(str_z + offset, count - offset) + 1)
    -
    1167 m_collection.push_back(std::move(std::make_shared<T_parser>(str_z + offset, count - offset, m_locale)));
    -
    1168 }
    -
    1169 }
    -
    1170
    -
    1171 void build(_In_z_ const T* str, _In_ va_list params)
    -
    1172 {
    -
    1173 const T* p;
    -
    1174 for (
    -
    1175 m_collection.push_back(std::move(std::make_shared<T_parser>(str, (size_t)-1, m_locale)));
    -
    1176 (p = va_arg(params, const T*)) != nullptr;
    -
    1177 m_collection.push_back(std::move(std::make_shared<T_parser>(p, (size_t)-1, m_locale))));
    -
    1178 }
    -
    1179 };
    +
    1110
    +
    1111 using branch = basic_branch<char>;
    + +
    1113#ifdef _UNICODE
    +
    1114 using tbranch = wbranch;
    +
    1115#else
    +
    1116 using tbranch = branch;
    +
    1117#endif
    + +
    1119
    +
    1123 template <class T, class T_parser = basic_string<T>>
    +
    + +
    1125 {
    +
    1126 public:
    +
    1127 inline basic_string_branch(
    +
    1128 _In_reads_(count) const T* str_z = nullptr,
    +
    1129 _In_ size_t count = 0,
    +
    1130 _In_ const std::locale& locale = std::locale()) :
    +
    1131 basic_branch<T>(locale)
    +
    1132 {
    +
    1133 build(str_z, count);
    +
    1134 }
    +
    1135
    +
    1136 inline basic_string_branch(_In_z_ const T* str, ...) :
    +
    1137 basic_branch<T>(std::locale())
    +
    1138 {
    +
    1139 va_list params;
    +
    1140 va_start(params, str);
    +
    1141 build(str, params);
    +
    1142 va_end(params);
    +
    1143 }
    +
    1144
    +
    1145 inline basic_string_branch(_In_ const std::locale& locale, _In_z_ const T* str, ...) :
    +
    1146 basic_branch<T>(locale)
    +
    1147 {
    +
    1148 va_list params;
    +
    1149 va_start(params, str);
    +
    1150 build(str, params);
    +
    1151 va_end(params);
    +
    1152 }
    +
    1153
    +
    1154 protected:
    +
    1155 void build(_In_reads_(count) const T* str_z, _In_ size_t count)
    +
    1156 {
    +
    1157 assert(str_z || !count);
    +
    1158 if (count) {
    +
    1159 size_t offset, n;
    +
    1160 for (
    +
    1161 offset = n = 0;
    +
    1162 offset < count && str_z[offset];
    +
    1163 offset += stdex::strnlen(str_z + offset, count - offset) + 1, ++n);
    +
    1164 this->m_collection.reserve(n);
    +
    1165 for (
    +
    1166 offset = 0;
    +
    1167 offset < count && str_z[offset];
    +
    1168 offset += stdex::strnlen(str_z + offset, count - offset) + 1)
    +
    1169 this->m_collection.push_back(std::move(std::make_shared<T_parser>(str_z + offset, count - offset, this->m_locale)));
    +
    1170 }
    +
    1171 }
    +
    1172
    +
    1173 void build(_In_z_ const T* str, _In_ va_list params)
    +
    1174 {
    +
    1175 const T* p;
    +
    1176 for (
    +
    1177 this->m_collection.push_back(std::move(std::make_shared<T_parser>(str, (size_t)-1, this->m_locale)));
    +
    1178 (p = va_arg(params, const T*)) != nullptr;
    +
    1179 this->m_collection.push_back(std::move(std::make_shared<T_parser>(p, (size_t)-1, this->m_locale))));
    +
    1180 }
    +
    1181 };
    -
    1180
    - - -
    1183#ifdef _UNICODE
    - -
    1185#else
    - -
    1187#endif
    - -
    1189
    -
    1193 template <class T>
    -
    - -
    1195 {
    -
    1196 public:
    - -
    1198 _In_count_(count) const std::shared_ptr<basic_parser<T>>* el = nullptr,
    -
    1199 _In_ size_t count = 0,
    -
    1200 _In_ const std::locale& locale = std::locale()) :
    -
    1201 parser_collection<T>(el, count, locale)
    -
    1202 {}
    -
    1203
    - -
    1205 _Inout_ std::vector<std::shared_ptr<basic_parser<T>>>&& collection,
    -
    1206 _In_ const std::locale& locale = std::locale()) :
    -
    1207 parser_collection<T>(std::move(collection), locale)
    -
    1208 {}
    -
    1209
    -
    1210 virtual bool match(
    -
    1211 _In_reads_or_z_(end) const T* text,
    -
    1212 _In_ size_t start = 0,
    -
    1213 _In_ size_t end = (size_t)-1,
    -
    1214 _In_ int flags = match_default)
    -
    1215 {
    -
    1216 assert(text || start >= end);
    -
    1217 for (auto& el: m_collection)
    -
    1218 el->invalidate();
    -
    1219 if (match_recursively(text, start, end, flags)) {
    -
    1220 interval.start = start;
    -
    1221 return true;
    -
    1222 }
    -
    1223 interval.start = (interval.end = start) + 1;
    -
    1224 return false;
    -
    1225 }
    -
    1226
    -
    1227 protected:
    -
    1228 bool match_recursively(
    -
    1229 _In_reads_or_z_(end) const T* text,
    -
    1230 _In_ size_t start = 0,
    -
    1231 _In_ size_t end = (size_t)-1,
    -
    1232 _In_ int flags = match_default)
    -
    1233 {
    -
    1234 bool all_matched = true;
    -
    1235 for (auto& el: m_collection) {
    -
    1236 if (!el->interval) {
    -
    1237 // Element was not matched in permutatuion yet.
    -
    1238 all_matched = false;
    -
    1239 if (el->match(text, start, end, flags)) {
    -
    1240 // Element matched for the first time.
    -
    1241 if (match_recursively(text, el->interval.end, end, flags)) {
    -
    1242 // Rest of the elements matched too.
    -
    1243 return true;
    -
    1244 }
    -
    1245 el->invalidate();
    -
    1246 }
    -
    1247 }
    -
    1248 }
    -
    1249 if (all_matched) {
    -
    1250 interval.end = start;
    -
    1251 return true;
    -
    1252 }
    -
    1253 return false;
    -
    1254 }
    -
    1255 };
    +
    1182
    + + +
    1185#ifdef _UNICODE
    + +
    1187#else
    + +
    1189#endif
    + +
    1191
    +
    1195 template <class T>
    +
    + +
    1197 {
    +
    1198 public:
    + +
    1200 _In_count_(count) const std::shared_ptr<basic_parser<T>>* el = nullptr,
    +
    1201 _In_ size_t count = 0,
    +
    1202 _In_ const std::locale& locale = std::locale()) :
    +
    1203 parser_collection<T>(el, count, locale)
    +
    1204 {}
    +
    1205
    + +
    1207 _Inout_ std::vector<std::shared_ptr<basic_parser<T>>>&& collection,
    +
    1208 _In_ const std::locale& locale = std::locale()) :
    +
    1209 parser_collection<T>(std::move(collection), locale)
    +
    1210 {}
    +
    1211
    +
    1212 virtual bool match(
    +
    1213 _In_reads_or_z_(end) const T* text,
    +
    1214 _In_ size_t start = 0,
    +
    1215 _In_ size_t end = (size_t)-1,
    +
    1216 _In_ int flags = match_default)
    +
    1217 {
    +
    1218 assert(text || start >= end);
    +
    1219 for (auto& el: this->m_collection)
    +
    1220 el->invalidate();
    +
    1221 if (match_recursively(text, start, end, flags)) {
    +
    1222 this->interval.start = start;
    +
    1223 return true;
    +
    1224 }
    +
    1225 this->interval.start = (this->interval.end = start) + 1;
    +
    1226 return false;
    +
    1227 }
    +
    1228
    +
    1229 protected:
    +
    1230 bool match_recursively(
    +
    1231 _In_reads_or_z_(end) const T* text,
    +
    1232 _In_ size_t start = 0,
    +
    1233 _In_ size_t end = (size_t)-1,
    +
    1234 _In_ int flags = match_default)
    +
    1235 {
    +
    1236 bool all_matched = true;
    +
    1237 for (auto& el: this->m_collection) {
    +
    1238 if (!el->interval) {
    +
    1239 // Element was not matched in permutatuion yet.
    +
    1240 all_matched = false;
    +
    1241 if (el->match(text, start, end, flags)) {
    +
    1242 // Element matched for the first time.
    +
    1243 if (match_recursively(text, el->interval.end, end, flags)) {
    +
    1244 // Rest of the elements matched too.
    +
    1245 return true;
    +
    1246 }
    +
    1247 el->invalidate();
    +
    1248 }
    +
    1249 }
    +
    1250 }
    +
    1251 if (all_matched) {
    +
    1252 this->interval.end = start;
    +
    1253 return true;
    +
    1254 }
    +
    1255 return false;
    +
    1256 }
    +
    1257 };
    -
    1256
    - - -
    1259#ifdef _UNICODE
    -
    1260 using tpermutation = wpermutation;
    -
    1261#else
    -
    1262 using tpermutation = permutation;
    -
    1263#endif
    - -
    1265
    -
    1269 template <class T>
    -
    -
    1270 class basic_integer : public basic_parser<T>
    -
    1271 {
    -
    1272 public:
    -
    1273 basic_integer(_In_ const std::locale& locale = std::locale()) :
    -
    1274 basic_parser<T>(locale),
    -
    1275 value(0)
    -
    1276 {}
    -
    1277
    -
    1278 virtual void invalidate()
    -
    1279 {
    -
    1280 value = 0;
    - -
    1282 }
    -
    1283
    -
    1284 public:
    -
    1285 size_t value;
    -
    1286 };
    +
    1258
    + + +
    1261#ifdef _UNICODE
    +
    1262 using tpermutation = wpermutation;
    +
    1263#else
    +
    1264 using tpermutation = permutation;
    +
    1265#endif
    + +
    1267
    +
    1271 template <class T>
    +
    +
    1272 class basic_integer : public basic_parser<T>
    +
    1273 {
    +
    1274 public:
    +
    1275 basic_integer(_In_ const std::locale& locale = std::locale()) :
    +
    1276 basic_parser<T>(locale),
    +
    1277 value(0)
    +
    1278 {}
    +
    1279
    +
    1280 virtual void invalidate()
    +
    1281 {
    +
    1282 value = 0;
    + +
    1284 }
    +
    1285
    +
    1286 public:
    +
    1287 size_t value;
    +
    1288 };
    -
    1287
    -
    1291 template <class T>
    -
    - -
    1293 {
    -
    1294 public:
    - -
    1296 _In_ const std::shared_ptr<basic_parser<T>>& digit_0,
    -
    1297 _In_ const std::shared_ptr<basic_parser<T>>& digit_1,
    -
    1298 _In_ const std::shared_ptr<basic_parser<T>>& digit_2,
    -
    1299 _In_ const std::shared_ptr<basic_parser<T>>& digit_3,
    -
    1300 _In_ const std::shared_ptr<basic_parser<T>>& digit_4,
    -
    1301 _In_ const std::shared_ptr<basic_parser<T>>& digit_5,
    -
    1302 _In_ const std::shared_ptr<basic_parser<T>>& digit_6,
    -
    1303 _In_ const std::shared_ptr<basic_parser<T>>& digit_7,
    -
    1304 _In_ const std::shared_ptr<basic_parser<T>>& digit_8,
    -
    1305 _In_ const std::shared_ptr<basic_parser<T>>& digit_9,
    -
    1306 _In_ const std::locale& locale = std::locale()) :
    -
    1307 basic_integer<T>(locale),
    -
    1308 m_digit_0(digit_0),
    -
    1309 m_digit_1(digit_1),
    -
    1310 m_digit_2(digit_2),
    -
    1311 m_digit_3(digit_3),
    -
    1312 m_digit_4(digit_4),
    -
    1313 m_digit_5(digit_5),
    -
    1314 m_digit_6(digit_6),
    -
    1315 m_digit_7(digit_7),
    -
    1316 m_digit_8(digit_8),
    -
    1317 m_digit_9(digit_9)
    -
    1318 {}
    -
    1319
    -
    1320 virtual bool match(
    -
    1321 _In_reads_or_z_(end) const T* text,
    -
    1322 _In_ size_t start = 0,
    -
    1323 _In_ size_t end = (size_t)-1,
    -
    1324 _In_ int flags = match_default)
    -
    1325 {
    -
    1326 assert(text || start >= end);
    -
    1327 for (interval.end = start, value = 0; interval.end < end && text[interval.end];) {
    -
    1328 size_t dig;
    -
    1329 if (m_digit_0->match(text, interval.end, end, flags)) { dig = 0; interval.end = m_digit_0->interval.end; }
    -
    1330 else if (m_digit_1->match(text, interval.end, end, flags)) { dig = 1; interval.end = m_digit_1->interval.end; }
    -
    1331 else if (m_digit_2->match(text, interval.end, end, flags)) { dig = 2; interval.end = m_digit_2->interval.end; }
    -
    1332 else if (m_digit_3->match(text, interval.end, end, flags)) { dig = 3; interval.end = m_digit_3->interval.end; }
    -
    1333 else if (m_digit_4->match(text, interval.end, end, flags)) { dig = 4; interval.end = m_digit_4->interval.end; }
    -
    1334 else if (m_digit_5->match(text, interval.end, end, flags)) { dig = 5; interval.end = m_digit_5->interval.end; }
    -
    1335 else if (m_digit_6->match(text, interval.end, end, flags)) { dig = 6; interval.end = m_digit_6->interval.end; }
    -
    1336 else if (m_digit_7->match(text, interval.end, end, flags)) { dig = 7; interval.end = m_digit_7->interval.end; }
    -
    1337 else if (m_digit_8->match(text, interval.end, end, flags)) { dig = 8; interval.end = m_digit_8->interval.end; }
    -
    1338 else if (m_digit_9->match(text, interval.end, end, flags)) { dig = 9; interval.end = m_digit_9->interval.end; }
    -
    1339 else break;
    -
    1340 value = value * 10 + dig;
    -
    1341 }
    -
    1342 if (start < interval.end) {
    -
    1343 interval.start = start;
    -
    1344 return true;
    -
    1345 }
    -
    1346 interval.start = (interval.end = start) + 1;
    -
    1347 return false;
    -
    1348 }
    -
    1349
    -
    1350 protected:
    -
    1351 std::shared_ptr<basic_parser<T>>
    -
    1352 m_digit_0,
    -
    1353 m_digit_1,
    -
    1354 m_digit_2,
    -
    1355 m_digit_3,
    -
    1356 m_digit_4,
    -
    1357 m_digit_5,
    -
    1358 m_digit_6,
    -
    1359 m_digit_7,
    -
    1360 m_digit_8,
    -
    1361 m_digit_9;
    -
    1362 };
    +
    1289
    +
    1293 template <class T>
    +
    + +
    1295 {
    +
    1296 public:
    + +
    1298 _In_ const std::shared_ptr<basic_parser<T>>& digit_0,
    +
    1299 _In_ const std::shared_ptr<basic_parser<T>>& digit_1,
    +
    1300 _In_ const std::shared_ptr<basic_parser<T>>& digit_2,
    +
    1301 _In_ const std::shared_ptr<basic_parser<T>>& digit_3,
    +
    1302 _In_ const std::shared_ptr<basic_parser<T>>& digit_4,
    +
    1303 _In_ const std::shared_ptr<basic_parser<T>>& digit_5,
    +
    1304 _In_ const std::shared_ptr<basic_parser<T>>& digit_6,
    +
    1305 _In_ const std::shared_ptr<basic_parser<T>>& digit_7,
    +
    1306 _In_ const std::shared_ptr<basic_parser<T>>& digit_8,
    +
    1307 _In_ const std::shared_ptr<basic_parser<T>>& digit_9,
    +
    1308 _In_ const std::locale& locale = std::locale()) :
    +
    1309 basic_integer<T>(locale),
    +
    1310 m_digit_0(digit_0),
    +
    1311 m_digit_1(digit_1),
    +
    1312 m_digit_2(digit_2),
    +
    1313 m_digit_3(digit_3),
    +
    1314 m_digit_4(digit_4),
    +
    1315 m_digit_5(digit_5),
    +
    1316 m_digit_6(digit_6),
    +
    1317 m_digit_7(digit_7),
    +
    1318 m_digit_8(digit_8),
    +
    1319 m_digit_9(digit_9)
    +
    1320 {}
    +
    1321
    +
    1322 virtual bool match(
    +
    1323 _In_reads_or_z_(end) const T* text,
    +
    1324 _In_ size_t start = 0,
    +
    1325 _In_ size_t end = (size_t)-1,
    +
    1326 _In_ int flags = match_default)
    +
    1327 {
    +
    1328 assert(text || start >= end);
    +
    1329 for (this->interval.end = start, this->value = 0; this->interval.end < end && text[this->interval.end];) {
    +
    1330 size_t dig;
    +
    1331 if (m_digit_0->match(text, this->interval.end, end, flags)) { dig = 0; this->interval.end = m_digit_0->interval.end; }
    +
    1332 else if (m_digit_1->match(text, this->interval.end, end, flags)) { dig = 1; this->interval.end = m_digit_1->interval.end; }
    +
    1333 else if (m_digit_2->match(text, this->interval.end, end, flags)) { dig = 2; this->interval.end = m_digit_2->interval.end; }
    +
    1334 else if (m_digit_3->match(text, this->interval.end, end, flags)) { dig = 3; this->interval.end = m_digit_3->interval.end; }
    +
    1335 else if (m_digit_4->match(text, this->interval.end, end, flags)) { dig = 4; this->interval.end = m_digit_4->interval.end; }
    +
    1336 else if (m_digit_5->match(text, this->interval.end, end, flags)) { dig = 5; this->interval.end = m_digit_5->interval.end; }
    +
    1337 else if (m_digit_6->match(text, this->interval.end, end, flags)) { dig = 6; this->interval.end = m_digit_6->interval.end; }
    +
    1338 else if (m_digit_7->match(text, this->interval.end, end, flags)) { dig = 7; this->interval.end = m_digit_7->interval.end; }
    +
    1339 else if (m_digit_8->match(text, this->interval.end, end, flags)) { dig = 8; this->interval.end = m_digit_8->interval.end; }
    +
    1340 else if (m_digit_9->match(text, this->interval.end, end, flags)) { dig = 9; this->interval.end = m_digit_9->interval.end; }
    +
    1341 else break;
    +
    1342 this->value = this->value * 10 + dig;
    +
    1343 }
    + +
    1345 this->interval.start = start;
    +
    1346 return true;
    +
    1347 }
    +
    1348 this->interval.start = (this->interval.end = start) + 1;
    +
    1349 return false;
    +
    1350 }
    +
    1351
    +
    1352 protected:
    +
    1353 std::shared_ptr<basic_parser<T>>
    +
    1354 m_digit_0,
    +
    1355 m_digit_1,
    +
    1356 m_digit_2,
    +
    1357 m_digit_3,
    +
    1358 m_digit_4,
    +
    1359 m_digit_5,
    +
    1360 m_digit_6,
    +
    1361 m_digit_7,
    +
    1362 m_digit_8,
    +
    1363 m_digit_9;
    +
    1364 };
    -
    1363
    - - -
    1366#ifdef _UNICODE
    -
    1367 using tinteger10 = winteger10;
    -
    1368#else
    -
    1369 using tinteger10 = integer10;
    -
    1370#endif
    - -
    1372
    -
    1376 template <class T>
    -
    - -
    1378 {
    -
    1379 public:
    - -
    1381 _In_ const std::shared_ptr<basic_integer10<T>>& digits,
    -
    1382 _In_ const std::shared_ptr<basic_set<T>>& separator,
    -
    1383 _In_ const std::locale& locale = std::locale()) :
    -
    1384 basic_integer<T>(locale),
    -
    1385 digit_count(0),
    -
    1386 has_separators(false),
    -
    1387 m_digits(digits),
    -
    1388 m_separator(separator)
    -
    1389 {}
    -
    1390
    -
    1391 virtual bool match(
    -
    1392 _In_reads_or_z_(end) const T* text,
    -
    1393 _In_ size_t start = 0,
    -
    1394 _In_ size_t end = (size_t)-1,
    -
    1395 _In_ int flags = match_default)
    -
    1396 {
    -
    1397 assert(text || start >= end);
    -
    1398 if (m_digits->match(text, start, end, flags)) {
    -
    1399 // Leading part match.
    -
    1400 value = m_digits->value;
    -
    1401 digit_count = m_digits->interval.size();
    -
    1402 has_separators = false;
    -
    1403 interval.start = start;
    -
    1404 interval.end = m_digits->interval.end;
    -
    1405 if (m_digits->interval.size() <= 3) {
    -
    1406 // Maybe separated with thousand separators?
    -
    1407 size_t hit_offset = (size_t)-1;
    -
    1408 while (m_separator->match(text, interval.end, end, flags) &&
    -
    1409 (hit_offset == (size_t)-1 || hit_offset == m_separator->hit_offset) && // All separators must be the same, no mixing.
    -
    1410 m_digits->match(text, m_separator->interval.end, end, flags) &&
    -
    1411 m_digits->interval.size() == 3)
    -
    1412 {
    -
    1413 // Thousand separator and three-digit integer followed.
    -
    1414 value = value * 1000 + m_digits->value;
    -
    1415 digit_count += 3;
    -
    1416 has_separators = true;
    -
    1417 interval.end = m_digits->interval.end;
    -
    1418 hit_offset = m_separator->hit_offset;
    -
    1419 }
    -
    1420 }
    -
    1421
    -
    1422 return true;
    -
    1423 }
    -
    1424 value = 0;
    -
    1425 interval.start = (interval.end = start) + 1;
    -
    1426 return false;
    -
    1427 }
    -
    1428
    -
    1429 virtual void invalidate()
    -
    1430 {
    -
    1431 digit_count = 0;
    -
    1432 has_separators = false;
    - -
    1434 }
    -
    1435
    -
    1436 public:
    - - -
    1439
    -
    1440 protected:
    -
    1441 std::shared_ptr<basic_integer10<T>> m_digits;
    -
    1442 std::shared_ptr<basic_set<T>> m_separator;
    -
    1443 };
    +
    1365
    + + +
    1368#ifdef _UNICODE
    +
    1369 using tinteger10 = winteger10;
    +
    1370#else
    +
    1371 using tinteger10 = integer10;
    +
    1372#endif
    + +
    1374
    +
    1378 template <class T>
    +
    + +
    1380 {
    +
    1381 public:
    + +
    1383 _In_ const std::shared_ptr<basic_integer10<T>>& digits,
    +
    1384 _In_ const std::shared_ptr<basic_set<T>>& separator,
    +
    1385 _In_ const std::locale& locale = std::locale()) :
    +
    1386 basic_integer<T>(locale),
    +
    1387 digit_count(0),
    +
    1388 has_separators(false),
    +
    1389 m_digits(digits),
    +
    1390 m_separator(separator)
    +
    1391 {}
    +
    1392
    +
    1393 virtual bool match(
    +
    1394 _In_reads_or_z_(end) const T* text,
    +
    1395 _In_ size_t start = 0,
    +
    1396 _In_ size_t end = (size_t)-1,
    +
    1397 _In_ int flags = match_default)
    +
    1398 {
    +
    1399 assert(text || start >= end);
    +
    1400 if (m_digits->match(text, start, end, flags)) {
    +
    1401 // Leading part match.
    +
    1402 this->value = m_digits->value;
    +
    1403 digit_count = m_digits->interval.size();
    +
    1404 has_separators = false;
    +
    1405 this->interval.start = start;
    +
    1406 this->interval.end = m_digits->interval.end;
    +
    1407 if (m_digits->interval.size() <= 3) {
    +
    1408 // Maybe separated with thousand separators?
    +
    1409 size_t hit_offset = (size_t)-1;
    +
    1410 while (m_separator->match(text, this->interval.end, end, flags) &&
    +
    1411 (hit_offset == (size_t)-1 || hit_offset == m_separator->hit_offset) && // All separators must be the same, no mixing.
    +
    1412 m_digits->match(text, m_separator->interval.end, end, flags) &&
    +
    1413 m_digits->interval.size() == 3)
    +
    1414 {
    +
    1415 // Thousand separator and three-digit integer followed.
    +
    1416 this->value = this->value * 1000 + m_digits->value;
    +
    1417 digit_count += 3;
    +
    1418 has_separators = true;
    +
    1419 this->interval.end = m_digits->interval.end;
    +
    1420 hit_offset = m_separator->hit_offset;
    +
    1421 }
    +
    1422 }
    +
    1423
    +
    1424 return true;
    +
    1425 }
    +
    1426 this->value = 0;
    +
    1427 this->interval.start = (this->interval.end = start) + 1;
    +
    1428 return false;
    +
    1429 }
    +
    1430
    +
    1431 virtual void invalidate()
    +
    1432 {
    +
    1433 digit_count = 0;
    +
    1434 has_separators = false;
    + +
    1436 }
    +
    1437
    +
    1438 public:
    + + +
    1441
    +
    1442 protected:
    +
    1443 std::shared_ptr<basic_integer10<T>> m_digits;
    +
    1444 std::shared_ptr<basic_set<T>> m_separator;
    +
    1445 };
    -
    1444
    - - -
    1447#ifdef _UNICODE
    -
    1448 using tinteger10ts = winteger10ts;
    -
    1449#else
    -
    1450 using tinteger10ts = integer10ts;
    -
    1451#endif
    - -
    1453
    -
    1457 template <class T>
    -
    - -
    1459 {
    -
    1460 public:
    - -
    1462 _In_ const std::shared_ptr<basic_parser<T>>& digit_0,
    -
    1463 _In_ const std::shared_ptr<basic_parser<T>>& digit_1,
    -
    1464 _In_ const std::shared_ptr<basic_parser<T>>& digit_2,
    -
    1465 _In_ const std::shared_ptr<basic_parser<T>>& digit_3,
    -
    1466 _In_ const std::shared_ptr<basic_parser<T>>& digit_4,
    -
    1467 _In_ const std::shared_ptr<basic_parser<T>>& digit_5,
    -
    1468 _In_ const std::shared_ptr<basic_parser<T>>& digit_6,
    -
    1469 _In_ const std::shared_ptr<basic_parser<T>>& digit_7,
    -
    1470 _In_ const std::shared_ptr<basic_parser<T>>& digit_8,
    -
    1471 _In_ const std::shared_ptr<basic_parser<T>>& digit_9,
    -
    1472 _In_ const std::shared_ptr<basic_parser<T>>& digit_10,
    -
    1473 _In_ const std::shared_ptr<basic_parser<T>>& digit_11,
    -
    1474 _In_ const std::shared_ptr<basic_parser<T>>& digit_12,
    -
    1475 _In_ const std::shared_ptr<basic_parser<T>>& digit_13,
    -
    1476 _In_ const std::shared_ptr<basic_parser<T>>& digit_14,
    -
    1477 _In_ const std::shared_ptr<basic_parser<T>>& digit_15,
    -
    1478 _In_ const std::locale& locale = std::locale()) :
    -
    1479 basic_integer<T>(locale),
    -
    1480 m_digit_0(digit_0),
    -
    1481 m_digit_1(digit_1),
    -
    1482 m_digit_2(digit_2),
    -
    1483 m_digit_3(digit_3),
    -
    1484 m_digit_4(digit_4),
    -
    1485 m_digit_5(digit_5),
    -
    1486 m_digit_6(digit_6),
    -
    1487 m_digit_7(digit_7),
    -
    1488 m_digit_8(digit_8),
    -
    1489 m_digit_9(digit_9),
    -
    1490 m_digit_10(digit_10),
    -
    1491 m_digit_11(digit_11),
    -
    1492 m_digit_12(digit_12),
    -
    1493 m_digit_13(digit_13),
    -
    1494 m_digit_14(digit_14),
    -
    1495 m_digit_15(digit_15)
    -
    1496 {}
    -
    1497
    -
    1498 virtual bool match(
    -
    1499 _In_reads_or_z_(end) const T* text,
    -
    1500 _In_ size_t start = 0,
    -
    1501 _In_ size_t end = (size_t)-1,
    -
    1502 _In_ int flags = match_default)
    -
    1503 {
    -
    1504 assert(text || start >= end);
    -
    1505 for (interval.end = start, value = 0; interval.end < end && text[interval.end];) {
    -
    1506 size_t dig;
    -
    1507 if (m_digit_0->match(text, interval.end, end, flags)) { dig = 0; interval.end = m_digit_0->interval.end; }
    -
    1508 else if (m_digit_1->match(text, interval.end, end, flags)) { dig = 1; interval.end = m_digit_1->interval.end; }
    -
    1509 else if (m_digit_2->match(text, interval.end, end, flags)) { dig = 2; interval.end = m_digit_2->interval.end; }
    -
    1510 else if (m_digit_3->match(text, interval.end, end, flags)) { dig = 3; interval.end = m_digit_3->interval.end; }
    -
    1511 else if (m_digit_4->match(text, interval.end, end, flags)) { dig = 4; interval.end = m_digit_4->interval.end; }
    -
    1512 else if (m_digit_5->match(text, interval.end, end, flags)) { dig = 5; interval.end = m_digit_5->interval.end; }
    -
    1513 else if (m_digit_6->match(text, interval.end, end, flags)) { dig = 6; interval.end = m_digit_6->interval.end; }
    -
    1514 else if (m_digit_7->match(text, interval.end, end, flags)) { dig = 7; interval.end = m_digit_7->interval.end; }
    -
    1515 else if (m_digit_8->match(text, interval.end, end, flags)) { dig = 8; interval.end = m_digit_8->interval.end; }
    -
    1516 else if (m_digit_9->match(text, interval.end, end, flags)) { dig = 9; interval.end = m_digit_9->interval.end; }
    -
    1517 else if (m_digit_10->match(text, interval.end, end, flags)) { dig = 10; interval.end = m_digit_10->interval.end; }
    -
    1518 else if (m_digit_11->match(text, interval.end, end, flags)) { dig = 11; interval.end = m_digit_11->interval.end; }
    -
    1519 else if (m_digit_12->match(text, interval.end, end, flags)) { dig = 12; interval.end = m_digit_12->interval.end; }
    -
    1520 else if (m_digit_13->match(text, interval.end, end, flags)) { dig = 13; interval.end = m_digit_13->interval.end; }
    -
    1521 else if (m_digit_14->match(text, interval.end, end, flags)) { dig = 14; interval.end = m_digit_14->interval.end; }
    -
    1522 else if (m_digit_15->match(text, interval.end, end, flags)) { dig = 15; interval.end = m_digit_15->interval.end; }
    -
    1523 else break;
    -
    1524 value = value * 16 + dig;
    -
    1525 }
    -
    1526 if (start < interval.end) {
    -
    1527 interval.start = start;
    -
    1528 return true;
    -
    1529 }
    -
    1530 interval.start = (interval.end = start) + 1;
    -
    1531 return false;
    -
    1532 }
    -
    1533
    -
    1534 protected:
    -
    1535 std::shared_ptr<basic_parser<T>>
    -
    1536 m_digit_0,
    -
    1537 m_digit_1,
    -
    1538 m_digit_2,
    -
    1539 m_digit_3,
    -
    1540 m_digit_4,
    -
    1541 m_digit_5,
    -
    1542 m_digit_6,
    -
    1543 m_digit_7,
    -
    1544 m_digit_8,
    -
    1545 m_digit_9,
    -
    1546 m_digit_10,
    -
    1547 m_digit_11,
    -
    1548 m_digit_12,
    -
    1549 m_digit_13,
    -
    1550 m_digit_14,
    -
    1551 m_digit_15;
    -
    1552 };
    +
    1446
    + + +
    1449#ifdef _UNICODE
    +
    1450 using tinteger10ts = winteger10ts;
    +
    1451#else
    +
    1452 using tinteger10ts = integer10ts;
    +
    1453#endif
    + +
    1455
    +
    1459 template <class T>
    +
    + +
    1461 {
    +
    1462 public:
    + +
    1464 _In_ const std::shared_ptr<basic_parser<T>>& digit_0,
    +
    1465 _In_ const std::shared_ptr<basic_parser<T>>& digit_1,
    +
    1466 _In_ const std::shared_ptr<basic_parser<T>>& digit_2,
    +
    1467 _In_ const std::shared_ptr<basic_parser<T>>& digit_3,
    +
    1468 _In_ const std::shared_ptr<basic_parser<T>>& digit_4,
    +
    1469 _In_ const std::shared_ptr<basic_parser<T>>& digit_5,
    +
    1470 _In_ const std::shared_ptr<basic_parser<T>>& digit_6,
    +
    1471 _In_ const std::shared_ptr<basic_parser<T>>& digit_7,
    +
    1472 _In_ const std::shared_ptr<basic_parser<T>>& digit_8,
    +
    1473 _In_ const std::shared_ptr<basic_parser<T>>& digit_9,
    +
    1474 _In_ const std::shared_ptr<basic_parser<T>>& digit_10,
    +
    1475 _In_ const std::shared_ptr<basic_parser<T>>& digit_11,
    +
    1476 _In_ const std::shared_ptr<basic_parser<T>>& digit_12,
    +
    1477 _In_ const std::shared_ptr<basic_parser<T>>& digit_13,
    +
    1478 _In_ const std::shared_ptr<basic_parser<T>>& digit_14,
    +
    1479 _In_ const std::shared_ptr<basic_parser<T>>& digit_15,
    +
    1480 _In_ const std::locale& locale = std::locale()) :
    +
    1481 basic_integer<T>(locale),
    +
    1482 m_digit_0(digit_0),
    +
    1483 m_digit_1(digit_1),
    +
    1484 m_digit_2(digit_2),
    +
    1485 m_digit_3(digit_3),
    +
    1486 m_digit_4(digit_4),
    +
    1487 m_digit_5(digit_5),
    +
    1488 m_digit_6(digit_6),
    +
    1489 m_digit_7(digit_7),
    +
    1490 m_digit_8(digit_8),
    +
    1491 m_digit_9(digit_9),
    +
    1492 m_digit_10(digit_10),
    +
    1493 m_digit_11(digit_11),
    +
    1494 m_digit_12(digit_12),
    +
    1495 m_digit_13(digit_13),
    +
    1496 m_digit_14(digit_14),
    +
    1497 m_digit_15(digit_15)
    +
    1498 {}
    +
    1499
    +
    1500 virtual bool match(
    +
    1501 _In_reads_or_z_(end) const T* text,
    +
    1502 _In_ size_t start = 0,
    +
    1503 _In_ size_t end = (size_t)-1,
    +
    1504 _In_ int flags = match_default)
    +
    1505 {
    +
    1506 assert(text || start >= end);
    +
    1507 for (this->interval.end = start, this->value = 0; this->interval.end < end && text[this->interval.end];) {
    +
    1508 size_t dig;
    +
    1509 if (m_digit_0->match(text, this->interval.end, end, flags)) { dig = 0; this->interval.end = m_digit_0->interval.end; }
    +
    1510 else if (m_digit_1->match(text, this->interval.end, end, flags)) { dig = 1; this->interval.end = m_digit_1->interval.end; }
    +
    1511 else if (m_digit_2->match(text, this->interval.end, end, flags)) { dig = 2; this->interval.end = m_digit_2->interval.end; }
    +
    1512 else if (m_digit_3->match(text, this->interval.end, end, flags)) { dig = 3; this->interval.end = m_digit_3->interval.end; }
    +
    1513 else if (m_digit_4->match(text, this->interval.end, end, flags)) { dig = 4; this->interval.end = m_digit_4->interval.end; }
    +
    1514 else if (m_digit_5->match(text, this->interval.end, end, flags)) { dig = 5; this->interval.end = m_digit_5->interval.end; }
    +
    1515 else if (m_digit_6->match(text, this->interval.end, end, flags)) { dig = 6; this->interval.end = m_digit_6->interval.end; }
    +
    1516 else if (m_digit_7->match(text, this->interval.end, end, flags)) { dig = 7; this->interval.end = m_digit_7->interval.end; }
    +
    1517 else if (m_digit_8->match(text, this->interval.end, end, flags)) { dig = 8; this->interval.end = m_digit_8->interval.end; }
    +
    1518 else if (m_digit_9->match(text, this->interval.end, end, flags)) { dig = 9; this->interval.end = m_digit_9->interval.end; }
    +
    1519 else if (m_digit_10->match(text, this->interval.end, end, flags)) { dig = 10; this->interval.end = m_digit_10->interval.end; }
    +
    1520 else if (m_digit_11->match(text, this->interval.end, end, flags)) { dig = 11; this->interval.end = m_digit_11->interval.end; }
    +
    1521 else if (m_digit_12->match(text, this->interval.end, end, flags)) { dig = 12; this->interval.end = m_digit_12->interval.end; }
    +
    1522 else if (m_digit_13->match(text, this->interval.end, end, flags)) { dig = 13; this->interval.end = m_digit_13->interval.end; }
    +
    1523 else if (m_digit_14->match(text, this->interval.end, end, flags)) { dig = 14; this->interval.end = m_digit_14->interval.end; }
    +
    1524 else if (m_digit_15->match(text, this->interval.end, end, flags)) { dig = 15; this->interval.end = m_digit_15->interval.end; }
    +
    1525 else break;
    +
    1526 this->value = this->value * 16 + dig;
    +
    1527 }
    + +
    1529 this->interval.start = start;
    +
    1530 return true;
    +
    1531 }
    +
    1532 this->interval.start = (this->interval.end = start) + 1;
    +
    1533 return false;
    +
    1534 }
    +
    1535
    +
    1536 protected:
    +
    1537 std::shared_ptr<basic_parser<T>>
    +
    1538 m_digit_0,
    +
    1539 m_digit_1,
    +
    1540 m_digit_2,
    +
    1541 m_digit_3,
    +
    1542 m_digit_4,
    +
    1543 m_digit_5,
    +
    1544 m_digit_6,
    +
    1545 m_digit_7,
    +
    1546 m_digit_8,
    +
    1547 m_digit_9,
    +
    1548 m_digit_10,
    +
    1549 m_digit_11,
    +
    1550 m_digit_12,
    +
    1551 m_digit_13,
    +
    1552 m_digit_14,
    +
    1553 m_digit_15;
    +
    1554 };
    -
    1553
    - - -
    1556#ifdef _UNICODE
    -
    1557 using tinteger16 = winteger16;
    -
    1558#else
    -
    1559 using tinteger16 = integer16;
    -
    1560#endif
    - -
    1562
    -
    1566 template <class T>
    -
    - -
    1568 {
    -
    1569 public:
    - -
    1571 _In_ const std::shared_ptr<basic_parser<T>>& digit_1,
    -
    1572 _In_ const std::shared_ptr<basic_parser<T>>& digit_5,
    -
    1573 _In_ const std::shared_ptr<basic_parser<T>>& digit_10,
    -
    1574 _In_ const std::shared_ptr<basic_parser<T>>& digit_50,
    -
    1575 _In_ const std::shared_ptr<basic_parser<T>>& digit_100,
    -
    1576 _In_ const std::shared_ptr<basic_parser<T>>& digit_500,
    -
    1577 _In_ const std::shared_ptr<basic_parser<T>>& digit_1000,
    -
    1578 _In_ const std::shared_ptr<basic_parser<T>>& digit_5000,
    -
    1579 _In_ const std::shared_ptr<basic_parser<T>>& digit_10000,
    -
    1580 _In_ const std::locale& locale = std::locale()) :
    -
    1581 basic_integer<T>(locale),
    -
    1582 m_digit_1(digit_1),
    -
    1583 m_digit_5(digit_5),
    -
    1584 m_digit_10(digit_10),
    -
    1585 m_digit_50(digit_50),
    -
    1586 m_digit_100(digit_100),
    -
    1587 m_digit_500(digit_500),
    -
    1588 m_digit_1000(digit_1000),
    -
    1589 m_digit_5000(digit_5000),
    -
    1590 m_digit_10000(digit_10000)
    -
    1591 {}
    -
    1592
    -
    1593 virtual bool match(
    -
    1594 _In_reads_or_z_(end) const T* text,
    -
    1595 _In_ size_t start = 0,
    -
    1596 _In_ size_t end = (size_t)-1,
    -
    1597 _In_ int flags = match_default)
    -
    1598 {
    -
    1599 assert(text || start >= end);
    -
    1600 size_t
    -
    1601 dig[5] = { (size_t)-1, (size_t)-1, (size_t)-1, (size_t)-1, (size_t)-1 },
    -
    1602 end2;
    -
    1603
    -
    1604 for (interval.end = start, value = 0; interval.end < end && text[interval.end]; dig[3] = dig[2], dig[2] = dig[1], dig[1] = dig[0], interval.end = end2) {
    -
    1605 if (m_digit_1 && m_digit_1->match(text, interval.end, end, flags)) { dig[0] = 1; end2 = m_digit_1->interval.end; }
    -
    1606 else if (m_digit_5 && m_digit_5->match(text, interval.end, end, flags)) { dig[0] = 5; end2 = m_digit_5->interval.end; }
    -
    1607 else if (m_digit_10 && m_digit_10->match(text, interval.end, end, flags)) { dig[0] = 10; end2 = m_digit_10->interval.end; }
    -
    1608 else if (m_digit_50 && m_digit_50->match(text, interval.end, end, flags)) { dig[0] = 50; end2 = m_digit_50->interval.end; }
    -
    1609 else if (m_digit_100 && m_digit_100->match(text, interval.end, end, flags)) { dig[0] = 100; end2 = m_digit_100->interval.end; }
    -
    1610 else if (m_digit_500 && m_digit_500->match(text, interval.end, end, flags)) { dig[0] = 500; end2 = m_digit_500->interval.end; }
    -
    1611 else if (m_digit_1000 && m_digit_1000->match(text, interval.end, end, flags)) { dig[0] = 1000; end2 = m_digit_1000->interval.end; }
    -
    1612 else if (m_digit_5000 && m_digit_5000->match(text, interval.end, end, flags)) { dig[0] = 5000; end2 = m_digit_5000->interval.end; }
    -
    1613 else if (m_digit_10000 && m_digit_10000->match(text, interval.end, end, flags)) { dig[0] = 10000; end2 = m_digit_10000->interval.end; }
    -
    1614 else break;
    -
    1615
    -
    1616 // Store first digit.
    -
    1617 if (dig[4] == (size_t)-1) dig[4] = dig[0];
    -
    1618
    -
    1619 if (dig[3] == dig[2] && dig[2] == dig[1] && dig[1] == dig[0] && dig[0] != dig[4]) {
    -
    1620 // Same digit repeated four times. No-go, unless first digit. E.g. XIIII vs. XIV. MMMMMCD allowed, IIII also...
    -
    1621 break;
    -
    1622 }
    -
    1623 if (dig[0] <= dig[1]) {
    -
    1624 // Digit is less or equal previous one: add.
    -
    1625 value += dig[0];
    -
    1626 }
    -
    1627 else if (
    -
    1628 dig[1] == 1 && (dig[0] == 5 || dig[0] == 10) ||
    -
    1629 dig[1] == 10 && (dig[0] == 50 || dig[0] == 100) ||
    -
    1630 dig[1] == 100 && (dig[0] == 500 || dig[0] == 1000) ||
    -
    1631 dig[1] == 1000 && (dig[0] == 5000 || dig[0] == 10000))
    -
    1632 {
    -
    1633 // Digit is up to two orders bigger than previous one: subtract. But...
    -
    1634 if (dig[2] < dig[0]) {
    -
    1635 // Digit is also bigger than pre-previous one. E.g. VIX (V < X => invalid)
    -
    1636 break;
    -
    1637 }
    -
    1638 value -= dig[1]; // Cancel addition in the previous step.
    -
    1639 dig[0] -= dig[1]; // Combine last two digits.
    -
    1640 dig[1] = dig[2]; // The true previous digit is now pre-previous one. :)
    -
    1641 dig[2] = dig[3]; // The true pre-previous digit is now pre-pre-previous one. :)
    -
    1642 value += dig[0]; // Add combined value.
    -
    1643 }
    -
    1644 else {
    -
    1645 // New digit is too big than the previous one. E.g. VX (V < X => invalid)
    -
    1646 break;
    -
    1647 }
    -
    1648 }
    -
    1649 if (value) {
    -
    1650 interval.start = start;
    -
    1651 return true;
    -
    1652 }
    -
    1653 interval.start = (interval.end = start) + 1;
    -
    1654 return false;
    -
    1655 }
    -
    1656
    -
    1657 protected:
    -
    1658 std::shared_ptr<basic_parser<T>>
    -
    1659 m_digit_1,
    -
    1660 m_digit_5,
    -
    1661 m_digit_10,
    -
    1662 m_digit_50,
    -
    1663 m_digit_100,
    -
    1664 m_digit_500,
    -
    1665 m_digit_1000,
    -
    1666 m_digit_5000,
    -
    1667 m_digit_10000;
    -
    1668 };
    +
    1555
    + + +
    1558#ifdef _UNICODE
    +
    1559 using tinteger16 = winteger16;
    +
    1560#else
    +
    1561 using tinteger16 = integer16;
    +
    1562#endif
    + +
    1564
    +
    1568 template <class T>
    +
    + +
    1570 {
    +
    1571 public:
    + +
    1573 _In_ const std::shared_ptr<basic_parser<T>>& digit_1,
    +
    1574 _In_ const std::shared_ptr<basic_parser<T>>& digit_5,
    +
    1575 _In_ const std::shared_ptr<basic_parser<T>>& digit_10,
    +
    1576 _In_ const std::shared_ptr<basic_parser<T>>& digit_50,
    +
    1577 _In_ const std::shared_ptr<basic_parser<T>>& digit_100,
    +
    1578 _In_ const std::shared_ptr<basic_parser<T>>& digit_500,
    +
    1579 _In_ const std::shared_ptr<basic_parser<T>>& digit_1000,
    +
    1580 _In_ const std::shared_ptr<basic_parser<T>>& digit_5000,
    +
    1581 _In_ const std::shared_ptr<basic_parser<T>>& digit_10000,
    +
    1582 _In_ const std::locale& locale = std::locale()) :
    +
    1583 basic_integer<T>(locale),
    +
    1584 m_digit_1(digit_1),
    +
    1585 m_digit_5(digit_5),
    +
    1586 m_digit_10(digit_10),
    +
    1587 m_digit_50(digit_50),
    +
    1588 m_digit_100(digit_100),
    +
    1589 m_digit_500(digit_500),
    +
    1590 m_digit_1000(digit_1000),
    +
    1591 m_digit_5000(digit_5000),
    +
    1592 m_digit_10000(digit_10000)
    +
    1593 {}
    +
    1594
    +
    1595 virtual bool match(
    +
    1596 _In_reads_or_z_(end) const T* text,
    +
    1597 _In_ size_t start = 0,
    +
    1598 _In_ size_t end = (size_t)-1,
    +
    1599 _In_ int flags = match_default)
    +
    1600 {
    +
    1601 assert(text || start >= end);
    +
    1602 size_t
    +
    1603 dig[5] = { (size_t)-1, (size_t)-1, (size_t)-1, (size_t)-1, (size_t)-1 },
    +
    1604 end2;
    +
    1605
    +
    1606 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) {
    +
    1607 if (m_digit_1 && m_digit_1->match(text, this->interval.end, end, flags)) { dig[0] = 1; end2 = m_digit_1->interval.end; }
    +
    1608 else if (m_digit_5 && m_digit_5->match(text, this->interval.end, end, flags)) { dig[0] = 5; end2 = m_digit_5->interval.end; }
    +
    1609 else if (m_digit_10 && m_digit_10->match(text, this->interval.end, end, flags)) { dig[0] = 10; end2 = m_digit_10->interval.end; }
    +
    1610 else if (m_digit_50 && m_digit_50->match(text, this->interval.end, end, flags)) { dig[0] = 50; end2 = m_digit_50->interval.end; }
    +
    1611 else if (m_digit_100 && m_digit_100->match(text, this->interval.end, end, flags)) { dig[0] = 100; end2 = m_digit_100->interval.end; }
    +
    1612 else if (m_digit_500 && m_digit_500->match(text, this->interval.end, end, flags)) { dig[0] = 500; end2 = m_digit_500->interval.end; }
    +
    1613 else if (m_digit_1000 && m_digit_1000->match(text, this->interval.end, end, flags)) { dig[0] = 1000; end2 = m_digit_1000->interval.end; }
    +
    1614 else if (m_digit_5000 && m_digit_5000->match(text, this->interval.end, end, flags)) { dig[0] = 5000; end2 = m_digit_5000->interval.end; }
    +
    1615 else if (m_digit_10000 && m_digit_10000->match(text, this->interval.end, end, flags)) { dig[0] = 10000; end2 = m_digit_10000->interval.end; }
    +
    1616 else break;
    +
    1617
    +
    1618 // Store first digit.
    +
    1619 if (dig[4] == (size_t)-1) dig[4] = dig[0];
    +
    1620
    +
    1621 if (dig[3] == dig[2] && dig[2] == dig[1] && dig[1] == dig[0] && dig[0] != dig[4]) {
    +
    1622 // Same digit repeated four times. No-go, unless first digit. E.g. XIIII vs. XIV. MMMMMCD allowed, IIII also...
    +
    1623 break;
    +
    1624 }
    +
    1625 if (dig[0] <= dig[1]) {
    +
    1626 // Digit is less or equal previous one: add.
    +
    1627 this->value += dig[0];
    +
    1628 }
    +
    1629 else if (
    +
    1630 (dig[1] == 1 && (dig[0] == 5 || dig[0] == 10)) ||
    +
    1631 (dig[1] == 10 && (dig[0] == 50 || dig[0] == 100)) ||
    +
    1632 (dig[1] == 100 && (dig[0] == 500 || dig[0] == 1000)) ||
    +
    1633 (dig[1] == 1000 && (dig[0] == 5000 || dig[0] == 10000)))
    +
    1634 {
    +
    1635 // Digit is up to two orders bigger than previous one: subtract. But...
    +
    1636 if (dig[2] < dig[0]) {
    +
    1637 // Digit is also bigger than pre-previous one. E.g. VIX (V < X => invalid)
    +
    1638 break;
    +
    1639 }
    +
    1640 this->value -= dig[1]; // Cancel addition in the previous step.
    +
    1641 dig[0] -= dig[1]; // Combine last two digits.
    +
    1642 dig[1] = dig[2]; // The true previous digit is now pre-previous one. :)
    +
    1643 dig[2] = dig[3]; // The true pre-previous digit is now pre-pre-previous one. :)
    +
    1644 this->value += dig[0]; // Add combined value.
    +
    1645 }
    +
    1646 else {
    +
    1647 // New digit is too big than the previous one. E.g. VX (V < X => invalid)
    +
    1648 break;
    +
    1649 }
    +
    1650 }
    +
    1651 if (this->value) {
    +
    1652 this->interval.start = start;
    +
    1653 return true;
    +
    1654 }
    +
    1655 this->interval.start = (this->interval.end = start) + 1;
    +
    1656 return false;
    +
    1657 }
    +
    1658
    +
    1659 protected:
    +
    1660 std::shared_ptr<basic_parser<T>>
    +
    1661 m_digit_1,
    +
    1662 m_digit_5,
    +
    1663 m_digit_10,
    +
    1664 m_digit_50,
    +
    1665 m_digit_100,
    +
    1666 m_digit_500,
    +
    1667 m_digit_1000,
    +
    1668 m_digit_5000,
    +
    1669 m_digit_10000;
    +
    1670 };
    -
    1669
    - - -
    1672#ifdef _UNICODE
    - -
    1674#else
    - -
    1676#endif
    - -
    1678
    -
    1682 template <class T>
    -
    - -
    1684 {
    -
    1685 public:
    - -
    1687 _In_ const std::shared_ptr<basic_parser<T>>& _numerator,
    -
    1688 _In_ const std::shared_ptr<basic_parser<T>>& _fraction_line,
    -
    1689 _In_ const std::shared_ptr<basic_parser<T>>& _denominator,
    -
    1690 _In_ const std::locale& locale = std::locale()) :
    -
    1691 basic_parser<T>(locale),
    -
    1692 numerator(_numerator),
    -
    1693 fraction_line(_fraction_line),
    -
    1694 denominator(_denominator)
    -
    1695 {}
    -
    1696
    -
    1697 virtual bool match(
    -
    1698 _In_reads_or_z_(end) const T* text,
    -
    1699 _In_ size_t start = 0,
    -
    1700 _In_ size_t end = (size_t)-1,
    -
    1701 _In_ int flags = match_default)
    -
    1702 {
    -
    1703 assert(text || start >= end);
    -
    1704 if (numerator->match(text, start, end, flags) &&
    -
    1705 fraction_line->match(text, numerator->interval.end, end, flags) &&
    -
    1706 denominator->match(text, fraction_line->interval.end, end, flags))
    -
    1707 {
    -
    1708 interval.start = start;
    -
    1709 interval.end = denominator->interval.end;
    -
    1710 return true;
    -
    1711 }
    -
    1712 numerator->invalidate();
    -
    1713 fraction_line->invalidate();
    -
    1714 denominator->invalidate();
    -
    1715 interval.start = (interval.end = start) + 1;
    -
    1716 return false;
    -
    1717 }
    -
    1718
    -
    1719 virtual void invalidate()
    -
    1720 {
    -
    1721 numerator->invalidate();
    -
    1722 fraction_line->invalidate();
    -
    1723 denominator->invalidate();
    - -
    1725 }
    -
    1726
    -
    1727 public:
    -
    1728 std::shared_ptr<basic_parser<T>> numerator;
    -
    1729 std::shared_ptr<basic_parser<T>> fraction_line;
    -
    1730 std::shared_ptr<basic_parser<T>> denominator;
    -
    1731 };
    +
    1671
    + + +
    1674#ifdef _UNICODE
    + +
    1676#else
    + +
    1678#endif
    + +
    1680
    +
    1684 template <class T>
    +
    + +
    1686 {
    +
    1687 public:
    + +
    1689 _In_ const std::shared_ptr<basic_parser<T>>& _numerator,
    +
    1690 _In_ const std::shared_ptr<basic_parser<T>>& _fraction_line,
    +
    1691 _In_ const std::shared_ptr<basic_parser<T>>& _denominator,
    +
    1692 _In_ const std::locale& locale = std::locale()) :
    +
    1693 basic_parser<T>(locale),
    +
    1694 numerator(_numerator),
    +
    1695 fraction_line(_fraction_line),
    +
    1696 denominator(_denominator)
    +
    1697 {}
    +
    1698
    +
    1699 virtual bool match(
    +
    1700 _In_reads_or_z_(end) const T* text,
    +
    1701 _In_ size_t start = 0,
    +
    1702 _In_ size_t end = (size_t)-1,
    +
    1703 _In_ int flags = match_default)
    +
    1704 {
    +
    1705 assert(text || start >= end);
    +
    1706 if (numerator->match(text, start, end, flags) &&
    +
    1707 fraction_line->match(text, numerator->interval.end, end, flags) &&
    +
    1708 denominator->match(text, fraction_line->interval.end, end, flags))
    +
    1709 {
    +
    1710 this->interval.start = start;
    +
    1711 this->interval.end = denominator->interval.end;
    +
    1712 return true;
    +
    1713 }
    +
    1714 numerator->invalidate();
    +
    1715 fraction_line->invalidate();
    +
    1716 denominator->invalidate();
    +
    1717 this->interval.start = (this->interval.end = start) + 1;
    +
    1718 return false;
    +
    1719 }
    +
    1720
    +
    1721 virtual void invalidate()
    +
    1722 {
    +
    1723 numerator->invalidate();
    +
    1724 fraction_line->invalidate();
    +
    1725 denominator->invalidate();
    + +
    1727 }
    +
    1728
    +
    1729 public:
    +
    1730 std::shared_ptr<basic_parser<T>> numerator;
    +
    1731 std::shared_ptr<basic_parser<T>> fraction_line;
    +
    1732 std::shared_ptr<basic_parser<T>> denominator;
    +
    1733 };
    -
    1732
    - - -
    1735#ifdef _UNICODE
    -
    1736 using tfraction = wfraction;
    -
    1737#else
    -
    1738 using tfraction = fraction;
    -
    1739#endif
    - -
    1741
    -
    1745 template <class T>
    -
    -
    1746 class basic_score : public basic_parser<T>
    -
    1747 {
    -
    1748 public:
    - -
    1750 _In_ const std::shared_ptr<basic_parser<T>>& _home,
    -
    1751 _In_ const std::shared_ptr<basic_parser<T>>& _separator,
    -
    1752 _In_ const std::shared_ptr<basic_parser<T>>& _guest,
    -
    1753 _In_ const std::shared_ptr<basic_parser<T>>& space,
    -
    1754 _In_ const std::locale& locale = std::locale()) :
    -
    1755 basic_parser<T>(locale),
    -
    1756 home(_home),
    -
    1757 separator(_separator),
    -
    1758 guest(_guest),
    -
    1759 m_space(space)
    -
    1760 {}
    -
    1761
    -
    1762 virtual bool match(
    -
    1763 _In_reads_or_z_(end) const T* text,
    -
    1764 _In_ size_t start = 0,
    -
    1765 _In_ size_t end = (size_t)-1,
    -
    1766 _In_ int flags = match_default)
    -
    1767 {
    -
    1768 assert(text || start >= end);
    -
    1769 interval.end = start;
    -
    1770
    -
    1771 if (home->match(text, interval.end, end, flags))
    -
    1772 interval.end = home->interval.end;
    -
    1773 else
    -
    1774 goto end;
    -
    1775
    -
    1776 const int space_match_flags = flags & ~match_multiline; // Spaces in score must never be broken in new line.
    -
    1777 for (; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
    -
    1778
    -
    1779 if (separator->match(text, interval.end, end, flags))
    -
    1780 interval.end = separator->interval.end;
    -
    1781 else
    -
    1782 goto end;
    -
    1783
    -
    1784 for (; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
    -
    1785
    -
    1786 if (guest->match(text, interval.end, end, flags))
    -
    1787 interval.end = guest->interval.end;
    -
    1788 else
    -
    1789 goto end;
    -
    1790
    -
    1791 interval.start = start;
    -
    1792 return true;
    +
    1734
    + + +
    1737#ifdef _UNICODE
    +
    1738 using tfraction = wfraction;
    +
    1739#else
    +
    1740 using tfraction = fraction;
    +
    1741#endif
    + +
    1743
    +
    1747 template <class T>
    +
    +
    1748 class basic_score : public basic_parser<T>
    +
    1749 {
    +
    1750 public:
    + +
    1752 _In_ const std::shared_ptr<basic_parser<T>>& _home,
    +
    1753 _In_ const std::shared_ptr<basic_parser<T>>& _separator,
    +
    1754 _In_ const std::shared_ptr<basic_parser<T>>& _guest,
    +
    1755 _In_ const std::shared_ptr<basic_parser<T>>& space,
    +
    1756 _In_ const std::locale& locale = std::locale()) :
    +
    1757 basic_parser<T>(locale),
    +
    1758 home(_home),
    +
    1759 separator(_separator),
    +
    1760 guest(_guest),
    +
    1761 m_space(space)
    +
    1762 {}
    +
    1763
    +
    1764 virtual bool match(
    +
    1765 _In_reads_or_z_(end) const T* text,
    +
    1766 _In_ size_t start = 0,
    +
    1767 _In_ size_t end = (size_t)-1,
    +
    1768 _In_ int flags = match_default)
    +
    1769 {
    +
    1770 assert(text || start >= end);
    +
    1771 this->interval.end = start;
    +
    1772
    +
    1773 const int space_match_flags = flags & ~match_multiline; // Spaces in score must never be broken in new line.
    +
    1774
    +
    1775 if (home->match(text, this->interval.end, end, flags))
    +
    1776 this->interval.end = home->interval.end;
    +
    1777 else
    +
    1778 goto end;
    +
    1779
    +
    1780 for (; m_space->match(text, this->interval.end, end, space_match_flags); this->interval.end = m_space->interval.end);
    +
    1781
    +
    1782 if (separator->match(text, this->interval.end, end, flags))
    +
    1783 this->interval.end = separator->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 (guest->match(text, this->interval.end, end, flags))
    +
    1790 this->interval.end = guest->interval.end;
    +
    1791 else
    +
    1792 goto end;
    1793
    -
    1794 end:
    -
    1795 home->invalidate();
    -
    1796 separator->invalidate();
    -
    1797 guest->invalidate();
    -
    1798 interval.start = (interval.end = start) + 1;
    -
    1799 return false;
    -
    1800 }
    -
    1801
    -
    1802 virtual void invalidate()
    -
    1803 {
    -
    1804 home->invalidate();
    -
    1805 separator->invalidate();
    -
    1806 guest->invalidate();
    - -
    1808 }
    -
    1809
    -
    1810 public:
    -
    1811 std::shared_ptr<basic_parser<T>> home;
    -
    1812 std::shared_ptr<basic_parser<T>> separator;
    -
    1813 std::shared_ptr<basic_parser<T>> guest;
    -
    1814
    -
    1815 protected:
    -
    1816 std::shared_ptr<basic_parser<T>> m_space;
    -
    1817 };
    +
    1794 this->interval.start = start;
    +
    1795 return true;
    +
    1796
    +
    1797 end:
    +
    1798 home->invalidate();
    +
    1799 separator->invalidate();
    +
    1800 guest->invalidate();
    +
    1801 this->interval.start = (this->interval.end = start) + 1;
    +
    1802 return false;
    +
    1803 }
    +
    1804
    +
    1805 virtual void invalidate()
    +
    1806 {
    +
    1807 home->invalidate();
    +
    1808 separator->invalidate();
    +
    1809 guest->invalidate();
    + +
    1811 }
    +
    1812
    +
    1813 public:
    +
    1814 std::shared_ptr<basic_parser<T>> home;
    +
    1815 std::shared_ptr<basic_parser<T>> separator;
    +
    1816 std::shared_ptr<basic_parser<T>> guest;
    +
    1817
    +
    1818 protected:
    +
    1819 std::shared_ptr<basic_parser<T>> m_space;
    +
    1820 };
    -
    1818
    -
    1819 using score = basic_score<char>;
    - -
    1821#ifdef _UNICODE
    -
    1822 using tscore = wscore;
    -
    1823#else
    -
    1824 using tscore = score;
    -
    1825#endif
    - -
    1827
    -
    1831 template <class T>
    -
    - -
    1833 {
    -
    1834 public:
    - -
    1836 _In_ const std::shared_ptr<basic_parser<T>>& _positive_sign,
    -
    1837 _In_ const std::shared_ptr<basic_parser<T>>& _negative_sign,
    -
    1838 _In_ const std::shared_ptr<basic_parser<T>>& _special_sign,
    -
    1839 _In_ const std::shared_ptr<basic_parser<T>>& _number,
    -
    1840 _In_ const std::locale& locale = std::locale()) :
    -
    1841 basic_parser<T>(locale),
    - - - - -
    1846 {}
    -
    1847
    -
    1848 virtual bool match(
    -
    1849 _In_reads_or_z_(end) const T* text,
    -
    1850 _In_ size_t start = 0,
    -
    1851 _In_ size_t end = (size_t)-1,
    -
    1852 _In_ int flags = match_default)
    -
    1853 {
    -
    1854 assert(text || start >= end);
    -
    1855 interval.end = start;
    -
    1856 if (positive_sign && positive_sign->match(text, interval.end, end, flags)) {
    -
    1857 interval.end = positive_sign->interval.end;
    -
    1858 if (negative_sign) negative_sign->invalidate();
    -
    1859 if (special_sign) special_sign->invalidate();
    -
    1860 }
    -
    1861 else if (negative_sign && negative_sign->match(text, interval.end, end, flags)) {
    -
    1862 interval.end = negative_sign->interval.end;
    -
    1863 if (positive_sign) positive_sign->invalidate();
    -
    1864 if (special_sign) special_sign->invalidate();
    -
    1865 }
    -
    1866 else if (special_sign && special_sign->match(text, interval.end, end, flags)) {
    -
    1867 interval.end = special_sign->interval.end;
    -
    1868 if (positive_sign) positive_sign->invalidate();
    -
    1869 if (negative_sign) negative_sign->invalidate();
    -
    1870 }
    -
    1871 else {
    -
    1872 if (positive_sign) positive_sign->invalidate();
    -
    1873 if (negative_sign) negative_sign->invalidate();
    -
    1874 if (special_sign) special_sign->invalidate();
    -
    1875 }
    -
    1876 if (number->match(text, interval.end, end, flags)) {
    -
    1877 interval.start = start;
    -
    1878 interval.end = number->interval.end;
    -
    1879 return true;
    -
    1880 }
    -
    1881 if (positive_sign) positive_sign->invalidate();
    -
    1882 if (negative_sign) negative_sign->invalidate();
    -
    1883 if (special_sign) special_sign->invalidate();
    -
    1884 number->invalidate();
    -
    1885 interval.start = (interval.end = start) + 1;
    -
    1886 return false;
    -
    1887 }
    -
    1888
    -
    1889 virtual void invalidate()
    -
    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();
    - -
    1896 }
    -
    1897
    -
    1898 public:
    -
    1899 std::shared_ptr<basic_parser<T>> positive_sign;
    -
    1900 std::shared_ptr<basic_parser<T>> negative_sign;
    -
    1901 std::shared_ptr<basic_parser<T>> special_sign;
    -
    1902 std::shared_ptr<basic_parser<T>> number;
    -
    1903 };
    +
    1821
    +
    1822 using score = basic_score<char>;
    + +
    1824#ifdef _UNICODE
    +
    1825 using tscore = wscore;
    +
    1826#else
    +
    1827 using tscore = score;
    +
    1828#endif
    + +
    1830
    +
    1834 template <class T>
    +
    + +
    1836 {
    +
    1837 public:
    + +
    1839 _In_ const std::shared_ptr<basic_parser<T>>& _positive_sign,
    +
    1840 _In_ const std::shared_ptr<basic_parser<T>>& _negative_sign,
    +
    1841 _In_ const std::shared_ptr<basic_parser<T>>& _special_sign,
    +
    1842 _In_ const std::shared_ptr<basic_parser<T>>& _number,
    +
    1843 _In_ const std::locale& locale = std::locale()) :
    +
    1844 basic_parser<T>(locale),
    + + + + +
    1849 {}
    +
    1850
    +
    1851 virtual bool match(
    +
    1852 _In_reads_or_z_(end) const T* text,
    +
    1853 _In_ size_t start = 0,
    +
    1854 _In_ size_t end = (size_t)-1,
    +
    1855 _In_ int flags = match_default)
    +
    1856 {
    +
    1857 assert(text || start >= end);
    +
    1858 this->interval.end = start;
    +
    1859 if (positive_sign && positive_sign->match(text, this->interval.end, end, flags)) {
    +
    1860 this->interval.end = positive_sign->interval.end;
    +
    1861 if (negative_sign) negative_sign->invalidate();
    +
    1862 if (special_sign) special_sign->invalidate();
    +
    1863 }
    +
    1864 else if (negative_sign && negative_sign->match(text, this->interval.end, end, flags)) {
    +
    1865 this->interval.end = negative_sign->interval.end;
    +
    1866 if (positive_sign) positive_sign->invalidate();
    +
    1867 if (special_sign) special_sign->invalidate();
    +
    1868 }
    +
    1869 else if (special_sign && special_sign->match(text, this->interval.end, end, flags)) {
    +
    1870 this->interval.end = special_sign->interval.end;
    +
    1871 if (positive_sign) positive_sign->invalidate();
    +
    1872 if (negative_sign) negative_sign->invalidate();
    +
    1873 }
    +
    1874 else {
    +
    1875 if (positive_sign) positive_sign->invalidate();
    +
    1876 if (negative_sign) negative_sign->invalidate();
    +
    1877 if (special_sign) special_sign->invalidate();
    +
    1878 }
    +
    1879 if (number->match(text, this->interval.end, end, flags)) {
    +
    1880 this->interval.start = start;
    +
    1881 this->interval.end = number->interval.end;
    +
    1882 return true;
    +
    1883 }
    +
    1884 if (positive_sign) positive_sign->invalidate();
    +
    1885 if (negative_sign) negative_sign->invalidate();
    +
    1886 if (special_sign) special_sign->invalidate();
    +
    1887 number->invalidate();
    +
    1888 this->interval.start = (this->interval.end = start) + 1;
    +
    1889 return false;
    +
    1890 }
    +
    1891
    +
    1892 virtual void invalidate()
    +
    1893 {
    +
    1894 if (positive_sign) positive_sign->invalidate();
    +
    1895 if (negative_sign) negative_sign->invalidate();
    +
    1896 if (special_sign) special_sign->invalidate();
    +
    1897 number->invalidate();
    + +
    1899 }
    +
    1900
    +
    1901 public:
    +
    1902 std::shared_ptr<basic_parser<T>> positive_sign;
    +
    1903 std::shared_ptr<basic_parser<T>> negative_sign;
    +
    1904 std::shared_ptr<basic_parser<T>> special_sign;
    +
    1905 std::shared_ptr<basic_parser<T>> number;
    +
    1906 };
    -
    1904
    - - -
    1907#ifdef _UNICODE
    - -
    1909#else
    - -
    1911#endif
    - -
    1913
    -
    1917 template <class T>
    -
    - -
    1919 {
    -
    1920 public:
    - -
    1922 _In_ const std::shared_ptr<basic_parser<T>>& _positive_sign,
    -
    1923 _In_ const std::shared_ptr<basic_parser<T>>& _negative_sign,
    -
    1924 _In_ const std::shared_ptr<basic_parser<T>>& _special_sign,
    -
    1925 _In_ const std::shared_ptr<basic_parser<T>>& _integer,
    -
    1926 _In_ const std::shared_ptr<basic_parser<T>>& space,
    -
    1927 _In_ const std::shared_ptr<basic_parser<T>>& _fraction,
    -
    1928 _In_ const std::locale& locale = std::locale()) :
    -
    1929 basic_parser<T>(locale),
    - - - - - -
    1935 m_space(space)
    -
    1936 {}
    -
    1937
    -
    1938 virtual bool match(
    -
    1939 _In_reads_or_z_(end) const T* text,
    -
    1940 _In_ size_t start = 0,
    -
    1941 _In_ size_t end = (size_t)-1,
    -
    1942 _In_ int flags = match_default)
    -
    1943 {
    -
    1944 assert(text || start >= end);
    -
    1945 interval.end = start;
    -
    1946
    -
    1947 if (positive_sign && positive_sign->match(text, interval.end, end, flags)) {
    -
    1948 interval.end = positive_sign->interval.end;
    -
    1949 if (negative_sign) negative_sign->invalidate();
    -
    1950 if (special_sign) special_sign->invalidate();
    -
    1951 }
    -
    1952 else if (negative_sign && negative_sign->match(text, interval.end, end, flags)) {
    -
    1953 interval.end = negative_sign->interval.end;
    -
    1954 if (positive_sign) positive_sign->invalidate();
    -
    1955 if (special_sign) special_sign->invalidate();
    -
    1956 }
    -
    1957 else if (special_sign && special_sign->match(text, interval.end, end, flags)) {
    -
    1958 interval.end = special_sign->interval.end;
    -
    1959 if (positive_sign) positive_sign->invalidate();
    -
    1960 if (negative_sign) negative_sign->invalidate();
    -
    1961 }
    -
    1962 else {
    -
    1963 if (positive_sign) positive_sign->invalidate();
    -
    1964 if (negative_sign) negative_sign->invalidate();
    -
    1965 if (special_sign) special_sign->invalidate();
    -
    1966 }
    -
    1967
    -
    1968 // Check for <integer> <fraction>
    -
    1969 const int space_match_flags = flags & ~match_multiline; // Spaces in fractions must never be broken in new line.
    -
    1970 if (integer->match(text, interval.end, end, flags) &&
    -
    1971 m_space->match(text, integer->interval.end, end, space_match_flags))
    -
    1972 {
    -
    1973 for (interval.end = m_space->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
    -
    1974 if (fraction->match(text, interval.end, end, flags)) {
    -
    1975 interval.start = start;
    - -
    1977 return true;
    -
    1978 }
    -
    1979 fraction->invalidate();
    -
    1980 interval.start = start;
    -
    1981 interval.end = integer->interval.end;
    -
    1982 return true;
    -
    1983 }
    -
    1984
    -
    1985 // Check for <fraction>
    -
    1986 if (fraction->match(text, interval.end, end, flags)) {
    -
    1987 integer->invalidate();
    -
    1988 interval.start = start;
    - -
    1990 return true;
    -
    1991 }
    -
    1992
    -
    1993 // Check for <integer>
    -
    1994 if (integer->match(text, interval.end, end, flags)) {
    -
    1995 fraction->invalidate();
    -
    1996 interval.start = start;
    -
    1997 interval.end = integer->interval.end;
    -
    1998 return true;
    -
    1999 }
    -
    2000
    -
    2001 if (positive_sign) positive_sign->invalidate();
    -
    2002 if (negative_sign) negative_sign->invalidate();
    -
    2003 if (special_sign) special_sign->invalidate();
    -
    2004 integer->invalidate();
    -
    2005 fraction->invalidate();
    -
    2006 interval.start = (interval.end = start) + 1;
    -
    2007 return false;
    -
    2008 }
    -
    2009
    -
    2010 virtual void invalidate()
    -
    2011 {
    -
    2012 if (positive_sign) positive_sign->invalidate();
    -
    2013 if (negative_sign) negative_sign->invalidate();
    -
    2014 if (special_sign) special_sign->invalidate();
    -
    2015 integer->invalidate();
    -
    2016 fraction->invalidate();
    - -
    2018 }
    -
    2019
    -
    2020 public:
    -
    2021 std::shared_ptr<basic_parser<T>> positive_sign;
    -
    2022 std::shared_ptr<basic_parser<T>> negative_sign;
    -
    2023 std::shared_ptr<basic_parser<T>> special_sign;
    -
    2024 std::shared_ptr<basic_parser<T>> integer;
    -
    2025 std::shared_ptr<basic_parser<T>> fraction;
    -
    2026
    -
    2027 protected:
    -
    2028 std::shared_ptr<basic_parser<T>> m_space;
    -
    2029 };
    +
    1907
    + + +
    1910#ifdef _UNICODE
    + +
    1912#else
    + +
    1914#endif
    + +
    1916
    +
    1920 template <class T>
    +
    + +
    1922 {
    +
    1923 public:
    + +
    1925 _In_ const std::shared_ptr<basic_parser<T>>& _positive_sign,
    +
    1926 _In_ const std::shared_ptr<basic_parser<T>>& _negative_sign,
    +
    1927 _In_ const std::shared_ptr<basic_parser<T>>& _special_sign,
    +
    1928 _In_ const std::shared_ptr<basic_parser<T>>& _integer,
    +
    1929 _In_ const std::shared_ptr<basic_parser<T>>& space,
    +
    1930 _In_ const std::shared_ptr<basic_parser<T>>& _fraction,
    +
    1931 _In_ const std::locale& locale = std::locale()) :
    +
    1932 basic_parser<T>(locale),
    + + + + + +
    1938 m_space(space)
    +
    1939 {}
    +
    1940
    +
    1941 virtual bool match(
    +
    1942 _In_reads_or_z_(end) const T* text,
    +
    1943 _In_ size_t start = 0,
    +
    1944 _In_ size_t end = (size_t)-1,
    +
    1945 _In_ int flags = match_default)
    +
    1946 {
    +
    1947 assert(text || start >= end);
    +
    1948 this->interval.end = start;
    +
    1949
    +
    1950 if (positive_sign && positive_sign->match(text, this->interval.end, end, flags)) {
    +
    1951 this->interval.end = positive_sign->interval.end;
    +
    1952 if (negative_sign) negative_sign->invalidate();
    +
    1953 if (special_sign) special_sign->invalidate();
    +
    1954 }
    +
    1955 else if (negative_sign && negative_sign->match(text, this->interval.end, end, flags)) {
    +
    1956 this->interval.end = negative_sign->interval.end;
    +
    1957 if (positive_sign) positive_sign->invalidate();
    +
    1958 if (special_sign) special_sign->invalidate();
    +
    1959 }
    +
    1960 else if (special_sign && special_sign->match(text, this->interval.end, end, flags)) {
    +
    1961 this->interval.end = special_sign->interval.end;
    +
    1962 if (positive_sign) positive_sign->invalidate();
    +
    1963 if (negative_sign) negative_sign->invalidate();
    +
    1964 }
    +
    1965 else {
    +
    1966 if (positive_sign) positive_sign->invalidate();
    +
    1967 if (negative_sign) negative_sign->invalidate();
    +
    1968 if (special_sign) special_sign->invalidate();
    +
    1969 }
    +
    1970
    +
    1971 // Check for <integer> <fraction>
    +
    1972 const int space_match_flags = flags & ~match_multiline; // Spaces in fractions must never be broken in new line.
    +
    1973 if (integer->match(text, this->interval.end, end, flags) &&
    +
    1974 m_space->match(text, integer->interval.end, end, space_match_flags))
    +
    1975 {
    +
    1976 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);
    +
    1977 if (fraction->match(text, this->interval.end, end, flags)) {
    +
    1978 this->interval.start = start;
    +
    1979 this->interval.end = fraction->interval.end;
    +
    1980 return true;
    +
    1981 }
    +
    1982 fraction->invalidate();
    +
    1983 this->interval.start = start;
    +
    1984 this->interval.end = integer->interval.end;
    +
    1985 return true;
    +
    1986 }
    +
    1987
    +
    1988 // Check for <fraction>
    +
    1989 if (fraction->match(text, this->interval.end, end, flags)) {
    +
    1990 integer->invalidate();
    +
    1991 this->interval.start = start;
    +
    1992 this->interval.end = fraction->interval.end;
    +
    1993 return true;
    +
    1994 }
    +
    1995
    +
    1996 // Check for <integer>
    +
    1997 if (integer->match(text, this->interval.end, end, flags)) {
    +
    1998 fraction->invalidate();
    +
    1999 this->interval.start = start;
    +
    2000 this->interval.end = integer->interval.end;
    +
    2001 return true;
    +
    2002 }
    +
    2003
    +
    2004 if (positive_sign) positive_sign->invalidate();
    +
    2005 if (negative_sign) negative_sign->invalidate();
    +
    2006 if (special_sign) special_sign->invalidate();
    +
    2007 integer->invalidate();
    +
    2008 fraction->invalidate();
    +
    2009 this->interval.start = (this->interval.end = start) + 1;
    +
    2010 return false;
    +
    2011 }
    +
    2012
    +
    2013 virtual void invalidate()
    +
    2014 {
    +
    2015 if (positive_sign) positive_sign->invalidate();
    +
    2016 if (negative_sign) negative_sign->invalidate();
    +
    2017 if (special_sign) special_sign->invalidate();
    +
    2018 integer->invalidate();
    +
    2019 fraction->invalidate();
    + +
    2021 }
    +
    2022
    +
    2023 public:
    +
    2024 std::shared_ptr<basic_parser<T>> positive_sign;
    +
    2025 std::shared_ptr<basic_parser<T>> negative_sign;
    +
    2026 std::shared_ptr<basic_parser<T>> special_sign;
    +
    2027 std::shared_ptr<basic_parser<T>> integer;
    +
    2028 std::shared_ptr<basic_parser<T>> fraction;
    +
    2029
    +
    2030 protected:
    +
    2031 std::shared_ptr<basic_parser<T>> m_space;
    +
    2032 };
    -
    2030
    - - -
    2033#ifdef _UNICODE
    - -
    2035#else
    - -
    2037#endif
    - -
    2039
    -
    2043 template <class T>
    -
    - -
    2045 {
    -
    2046 public:
    - -
    2048 _In_ const std::shared_ptr<basic_parser<T>>& _positive_sign,
    -
    2049 _In_ const std::shared_ptr<basic_parser<T>>& _negative_sign,
    -
    2050 _In_ const std::shared_ptr<basic_parser<T>>& _special_sign,
    -
    2051 _In_ const std::shared_ptr<basic_integer<T>>& _integer,
    -
    2052 _In_ const std::shared_ptr<basic_parser<T>>& _decimal_separator,
    -
    2053 _In_ const std::shared_ptr<basic_integer<T>>& _decimal,
    -
    2054 _In_ const std::shared_ptr<basic_parser<T>>& _exponent_symbol,
    -
    2055 _In_ const std::shared_ptr<basic_parser<T>>& _positive_exp_sign,
    -
    2056 _In_ const std::shared_ptr<basic_parser<T>>& _negative_exp_sign,
    -
    2057 _In_ const std::shared_ptr<basic_integer<T>>& _exponent,
    -
    2058 _In_ const std::locale& locale = std::locale()) :
    -
    2059 basic_parser<T>(locale),
    - - - - - - - - - - -
    2070 value(std::numeric_limits<double>::quiet_NaN())
    -
    2071 {}
    -
    2072
    -
    2073 virtual bool match(
    -
    2074 _In_reads_or_z_(end) const T* text,
    -
    2075 _In_ size_t start = 0,
    -
    2076 _In_ size_t end = (size_t)-1,
    -
    2077 _In_ int flags = match_default)
    -
    2078 {
    -
    2079 assert(text || start >= end);
    -
    2080 interval.end = start;
    -
    2081
    -
    2082 if (positive_sign && positive_sign->match(text, interval.end, end, flags)) {
    -
    2083 interval.end = positive_sign->interval.end;
    -
    2084 if (negative_sign) negative_sign->invalidate();
    -
    2085 if (special_sign) special_sign->invalidate();
    -
    2086 }
    -
    2087 else if (negative_sign && negative_sign->match(text, interval.end, end, flags)) {
    -
    2088 interval.end = negative_sign->interval.end;
    -
    2089 if (positive_sign) positive_sign->invalidate();
    -
    2090 if (special_sign) special_sign->invalidate();
    -
    2091 }
    -
    2092 else if (special_sign && special_sign->match(text, interval.end, end, flags)) {
    -
    2093 interval.end = special_sign->interval.end;
    -
    2094 if (positive_sign) positive_sign->invalidate();
    -
    2095 if (negative_sign) negative_sign->invalidate();
    -
    2096 }
    -
    2097 else {
    -
    2098 if (positive_sign) positive_sign->invalidate();
    -
    2099 if (negative_sign) negative_sign->invalidate();
    -
    2100 if (special_sign) special_sign->invalidate();
    -
    2101 }
    -
    2102
    -
    2103 if (integer->match(text, interval.end, end, flags))
    -
    2104 interval.end = integer->interval.end;
    +
    2033
    + + +
    2036#ifdef _UNICODE
    + +
    2038#else
    + +
    2040#endif
    + +
    2042
    +
    2046 template <class T>
    +
    + +
    2048 {
    +
    2049 public:
    + +
    2051 _In_ const std::shared_ptr<basic_parser<T>>& _positive_sign,
    +
    2052 _In_ const std::shared_ptr<basic_parser<T>>& _negative_sign,
    +
    2053 _In_ const std::shared_ptr<basic_parser<T>>& _special_sign,
    +
    2054 _In_ const std::shared_ptr<basic_integer<T>>& _integer,
    +
    2055 _In_ const std::shared_ptr<basic_parser<T>>& _decimal_separator,
    +
    2056 _In_ const std::shared_ptr<basic_integer<T>>& _decimal,
    +
    2057 _In_ const std::shared_ptr<basic_parser<T>>& _exponent_symbol,
    +
    2058 _In_ const std::shared_ptr<basic_parser<T>>& _positive_exp_sign,
    +
    2059 _In_ const std::shared_ptr<basic_parser<T>>& _negative_exp_sign,
    +
    2060 _In_ const std::shared_ptr<basic_integer<T>>& _exponent,
    +
    2061 _In_ const std::locale& locale = std::locale()) :
    +
    2062 basic_parser<T>(locale),
    + + + + + + + + + + +
    2073 value(std::numeric_limits<double>::quiet_NaN())
    +
    2074 {}
    +
    2075
    +
    2076 virtual bool match(
    +
    2077 _In_reads_or_z_(end) const T* text,
    +
    2078 _In_ size_t start = 0,
    +
    2079 _In_ size_t end = (size_t)-1,
    +
    2080 _In_ int flags = match_default)
    +
    2081 {
    +
    2082 assert(text || start >= end);
    +
    2083 this->interval.end = start;
    +
    2084
    +
    2085 if (positive_sign && positive_sign->match(text, this->interval.end, end, flags)) {
    +
    2086 this->interval.end = positive_sign->interval.end;
    +
    2087 if (negative_sign) negative_sign->invalidate();
    +
    2088 if (special_sign) special_sign->invalidate();
    +
    2089 }
    +
    2090 else if (negative_sign && negative_sign->match(text, this->interval.end, end, flags)) {
    +
    2091 this->interval.end = negative_sign->interval.end;
    +
    2092 if (positive_sign) positive_sign->invalidate();
    +
    2093 if (special_sign) special_sign->invalidate();
    +
    2094 }
    +
    2095 else if (special_sign && special_sign->match(text, this->interval.end, end, flags)) {
    +
    2096 this->interval.end = special_sign->interval.end;
    +
    2097 if (positive_sign) positive_sign->invalidate();
    +
    2098 if (negative_sign) negative_sign->invalidate();
    +
    2099 }
    +
    2100 else {
    +
    2101 if (positive_sign) positive_sign->invalidate();
    +
    2102 if (negative_sign) negative_sign->invalidate();
    +
    2103 if (special_sign) special_sign->invalidate();
    +
    2104 }
    2105
    -
    2106 if (decimal_separator->match(text, interval.end, end, flags) &&
    - -
    2108 interval.end = decimal->interval.end;
    -
    2109 else {
    -
    2110 decimal_separator->invalidate();
    -
    2111 decimal->invalidate();
    -
    2112 }
    -
    2113
    -
    2114 if (integer->interval.empty() &&
    -
    2115 decimal->interval.empty())
    -
    2116 {
    -
    2117 // No integer part, no decimal part.
    -
    2118 if (positive_sign) positive_sign->invalidate();
    -
    2119 if (negative_sign) negative_sign->invalidate();
    -
    2120 if (special_sign) special_sign->invalidate();
    -
    2121 integer->invalidate();
    -
    2122 decimal_separator->invalidate();
    -
    2123 decimal->invalidate();
    -
    2124 if (exponent_symbol) exponent_symbol->invalidate();
    -
    2125 if (positive_exp_sign) positive_exp_sign->invalidate();
    -
    2126 if (negative_exp_sign) negative_exp_sign->invalidate();
    -
    2127 if (exponent) exponent->invalidate();
    -
    2128 interval.start = (interval.end = start) + 1;
    -
    2129 return false;
    -
    2130 }
    -
    2131
    -
    2132 if (exponent_symbol && exponent_symbol->match(text, interval.end, end, flags) &&
    - - - -
    2136 {
    -
    2137 interval.end = exponent->interval.end;
    -
    2138 if (negative_exp_sign) negative_exp_sign->invalidate();
    -
    2139 }
    -
    2140 else if (exponent_symbol && exponent_symbol->match(text, interval.end, end, flags) &&
    - - -
    2143 {
    -
    2144 interval.end = exponent->interval.end;
    -
    2145 if (positive_exp_sign) positive_exp_sign->invalidate();
    -
    2146 }
    -
    2147 else {
    -
    2148 if (exponent_symbol) exponent_symbol->invalidate();
    -
    2149 if (positive_exp_sign) positive_exp_sign->invalidate();
    -
    2150 if (negative_exp_sign) negative_exp_sign->invalidate();
    -
    2151 if (exponent) exponent->invalidate();
    -
    2152 }
    -
    2153
    -
    2154 value = (double)integer->value;
    -
    2155 if (decimal->interval)
    -
    2156 value += (double)decimal->value * pow(10.0, -(double)decimal->interval.size());
    -
    2157 if (negative_sign && negative_sign->interval)
    -
    2158 value = -value;
    -
    2159 if (exponent && exponent->interval) {
    -
    2160 double e = (double)exponent->value;
    -
    2161 if (negative_exp_sign && negative_exp_sign->interval)
    -
    2162 e = -e;
    -
    2163 value *= pow(10.0, e);
    -
    2164 }
    -
    2165
    -
    2166 interval.start = start;
    -
    2167 return true;
    -
    2168 }
    -
    2169
    -
    2170 virtual void invalidate()
    -
    2171 {
    -
    2172 if (positive_sign) positive_sign->invalidate();
    -
    2173 if (negative_sign) negative_sign->invalidate();
    -
    2174 if (special_sign) special_sign->invalidate();
    -
    2175 integer->invalidate();
    -
    2176 decimal_separator->invalidate();
    -
    2177 decimal->invalidate();
    -
    2178 if (exponent_symbol) exponent_symbol->invalidate();
    -
    2179 if (positive_exp_sign) positive_exp_sign->invalidate();
    -
    2180 if (negative_exp_sign) negative_exp_sign->invalidate();
    -
    2181 if (exponent) exponent->invalidate();
    -
    2182 value = std::numeric_limits<double>::quiet_NaN();
    - -
    2184 }
    -
    2185
    -
    2186 public:
    -
    2187 std::shared_ptr<basic_parser<T>> positive_sign;
    -
    2188 std::shared_ptr<basic_parser<T>> negative_sign;
    -
    2189 std::shared_ptr<basic_parser<T>> special_sign;
    -
    2190 std::shared_ptr<basic_integer<T>> integer;
    -
    2191 std::shared_ptr<basic_parser<T>> decimal_separator;
    -
    2192 std::shared_ptr<basic_integer<T>> decimal;
    -
    2193 std::shared_ptr<basic_parser<T>> exponent_symbol;
    -
    2194 std::shared_ptr<basic_parser<T>> positive_exp_sign;
    -
    2195 std::shared_ptr<basic_parser<T>> negative_exp_sign;
    -
    2196 std::shared_ptr<basic_integer<T>> exponent;
    -
    2197 double value;
    -
    2198 };
    +
    2106 if (integer->match(text, this->interval.end, end, flags))
    +
    2107 this->interval.end = integer->interval.end;
    +
    2108
    +
    2109 if (decimal_separator->match(text, this->interval.end, end, flags) &&
    + +
    2111 this->interval.end = decimal->interval.end;
    +
    2112 else {
    +
    2113 decimal_separator->invalidate();
    +
    2114 decimal->invalidate();
    +
    2115 }
    +
    2116
    +
    2117 if (integer->interval.empty() &&
    +
    2118 decimal->interval.empty())
    +
    2119 {
    +
    2120 // No integer part, no decimal part.
    +
    2121 if (positive_sign) positive_sign->invalidate();
    +
    2122 if (negative_sign) negative_sign->invalidate();
    +
    2123 if (special_sign) special_sign->invalidate();
    +
    2124 integer->invalidate();
    +
    2125 decimal_separator->invalidate();
    +
    2126 decimal->invalidate();
    +
    2127 if (exponent_symbol) exponent_symbol->invalidate();
    +
    2128 if (positive_exp_sign) positive_exp_sign->invalidate();
    +
    2129 if (negative_exp_sign) negative_exp_sign->invalidate();
    +
    2130 if (exponent) exponent->invalidate();
    +
    2131 this->interval.start = (this->interval.end = start) + 1;
    +
    2132 return false;
    +
    2133 }
    +
    2134
    +
    2135 if (exponent_symbol && exponent_symbol->match(text, this->interval.end, end, flags) &&
    + + +
    2138 (exponent && exponent->match(text, exponent_symbol->interval.end, end, flags))))
    +
    2139 {
    +
    2140 this->interval.end = exponent->interval.end;
    +
    2141 if (negative_exp_sign) negative_exp_sign->invalidate();
    +
    2142 }
    +
    2143 else if (exponent_symbol && exponent_symbol->match(text, this->interval.end, end, flags) &&
    + + +
    2146 {
    +
    2147 this->interval.end = exponent->interval.end;
    +
    2148 if (positive_exp_sign) positive_exp_sign->invalidate();
    +
    2149 }
    +
    2150 else {
    +
    2151 if (exponent_symbol) exponent_symbol->invalidate();
    +
    2152 if (positive_exp_sign) positive_exp_sign->invalidate();
    +
    2153 if (negative_exp_sign) negative_exp_sign->invalidate();
    +
    2154 if (exponent) exponent->invalidate();
    +
    2155 }
    +
    2156
    +
    2157 value = (double)integer->value;
    +
    2158 if (decimal->interval)
    +
    2159 value += (double)decimal->value * pow(10.0, -(double)decimal->interval.size());
    +
    2160 if (negative_sign && negative_sign->interval)
    +
    2161 value = -value;
    +
    2162 if (exponent && exponent->interval) {
    +
    2163 double e = (double)exponent->value;
    +
    2164 if (negative_exp_sign && negative_exp_sign->interval)
    +
    2165 e = -e;
    +
    2166 value *= pow(10.0, e);
    +
    2167 }
    +
    2168
    +
    2169 this->interval.start = start;
    +
    2170 return true;
    +
    2171 }
    +
    2172
    +
    2173 virtual void invalidate()
    +
    2174 {
    +
    2175 if (positive_sign) positive_sign->invalidate();
    +
    2176 if (negative_sign) negative_sign->invalidate();
    +
    2177 if (special_sign) special_sign->invalidate();
    +
    2178 integer->invalidate();
    +
    2179 decimal_separator->invalidate();
    +
    2180 decimal->invalidate();
    +
    2181 if (exponent_symbol) exponent_symbol->invalidate();
    +
    2182 if (positive_exp_sign) positive_exp_sign->invalidate();
    +
    2183 if (negative_exp_sign) negative_exp_sign->invalidate();
    +
    2184 if (exponent) exponent->invalidate();
    +
    2185 value = std::numeric_limits<double>::quiet_NaN();
    + +
    2187 }
    +
    2188
    +
    2189 public:
    +
    2190 std::shared_ptr<basic_parser<T>> positive_sign;
    +
    2191 std::shared_ptr<basic_parser<T>> negative_sign;
    +
    2192 std::shared_ptr<basic_parser<T>> special_sign;
    +
    2193 std::shared_ptr<basic_integer<T>> integer;
    +
    2194 std::shared_ptr<basic_parser<T>> decimal_separator;
    +
    2195 std::shared_ptr<basic_integer<T>> decimal;
    +
    2196 std::shared_ptr<basic_parser<T>> exponent_symbol;
    +
    2197 std::shared_ptr<basic_parser<T>> positive_exp_sign;
    +
    2198 std::shared_ptr<basic_parser<T>> negative_exp_sign;
    +
    2199 std::shared_ptr<basic_integer<T>> exponent;
    +
    2200 double value;
    +
    2201 };
    -
    2199
    - - -
    2202#ifdef _UNICODE
    - -
    2204#else
    - -
    2206#endif
    - -
    2208
    -
    2212 template <class T>
    -
    - -
    2214 {
    -
    2215 public:
    - -
    2217 _In_ const std::shared_ptr<basic_parser<T>>& _positive_sign,
    -
    2218 _In_ const std::shared_ptr<basic_parser<T>>& _negative_sign,
    -
    2219 _In_ const std::shared_ptr<basic_parser<T>>& _special_sign,
    -
    2220 _In_ const std::shared_ptr<basic_parser<T>>& _currency,
    -
    2221 _In_ const std::shared_ptr<basic_parser<T>>& _integer,
    -
    2222 _In_ const std::shared_ptr<basic_parser<T>>& _decimal_separator,
    -
    2223 _In_ const std::shared_ptr<basic_parser<T>>& _decimal,
    -
    2224 _In_ const std::locale& locale = std::locale()) :
    -
    2225 basic_parser<T>(locale),
    - - - - - - - -
    2233 {}
    -
    2234
    -
    2235 virtual bool match(
    -
    2236 _In_reads_or_z_(end) const T* text,
    -
    2237 _In_ size_t start = 0,
    -
    2238 _In_ size_t end = (size_t)-1,
    -
    2239 _In_ int flags = match_default)
    -
    2240 {
    -
    2241 assert(text || start >= end);
    -
    2242 interval.end = start;
    -
    2243
    -
    2244 if (positive_sign->match(text, interval.end, end, flags)) {
    -
    2245 interval.end = positive_sign->interval.end;
    -
    2246 if (negative_sign) negative_sign->invalidate();
    -
    2247 if (special_sign) special_sign->invalidate();
    -
    2248 }
    -
    2249 else if (negative_sign->match(text, interval.end, end, flags)) {
    -
    2250 interval.end = negative_sign->interval.end;
    -
    2251 if (positive_sign) positive_sign->invalidate();
    -
    2252 if (special_sign) special_sign->invalidate();
    -
    2253 }
    -
    2254 else if (special_sign->match(text, interval.end, end, flags)) {
    -
    2255 interval.end = special_sign->interval.end;
    -
    2256 if (positive_sign) positive_sign->invalidate();
    -
    2257 if (negative_sign) negative_sign->invalidate();
    -
    2258 }
    -
    2259 else {
    -
    2260 if (positive_sign) positive_sign->invalidate();
    -
    2261 if (negative_sign) negative_sign->invalidate();
    -
    2262 if (special_sign) special_sign->invalidate();
    -
    2263 }
    -
    2264
    -
    2265 if (currency->match(text, interval.end, end, flags))
    -
    2266 interval.end = currency->interval.end;
    -
    2267 else {
    -
    2268 if (positive_sign) positive_sign->invalidate();
    -
    2269 if (negative_sign) negative_sign->invalidate();
    -
    2270 if (special_sign) special_sign->invalidate();
    -
    2271 integer->invalidate();
    -
    2272 decimal_separator->invalidate();
    -
    2273 decimal->invalidate();
    -
    2274 interval.start = (interval.end = start) + 1;
    -
    2275 return false;
    -
    2276 }
    -
    2277
    -
    2278 if (integer->match(text, interval.end, end, flags))
    -
    2279 interval.end = integer->interval.end;
    -
    2280 if (decimal_separator->match(text, interval.end, end, flags) &&
    - -
    2282 interval.end = decimal->interval.end;
    -
    2283 else {
    -
    2284 decimal_separator->invalidate();
    -
    2285 decimal->invalidate();
    -
    2286 }
    -
    2287
    -
    2288 if (integer->interval.empty() &&
    -
    2289 decimal->interval.empty())
    -
    2290 {
    -
    2291 // No integer part, no decimal part.
    -
    2292 if (positive_sign) positive_sign->invalidate();
    -
    2293 if (negative_sign) negative_sign->invalidate();
    -
    2294 if (special_sign) special_sign->invalidate();
    -
    2295 currency->invalidate();
    -
    2296 integer->invalidate();
    -
    2297 decimal_separator->invalidate();
    -
    2298 decimal->invalidate();
    -
    2299 interval.start = (interval.end = start) + 1;
    -
    2300 return false;
    -
    2301 }
    -
    2302
    -
    2303 interval.start = start;
    -
    2304 return true;
    -
    2305 }
    -
    2306
    -
    2307 virtual void invalidate()
    -
    2308 {
    -
    2309 if (positive_sign) positive_sign->invalidate();
    -
    2310 if (negative_sign) negative_sign->invalidate();
    -
    2311 if (special_sign) special_sign->invalidate();
    -
    2312 currency->invalidate();
    -
    2313 integer->invalidate();
    -
    2314 decimal_separator->invalidate();
    -
    2315 decimal->invalidate();
    - -
    2317 }
    -
    2318
    -
    2319 public:
    -
    2320 std::shared_ptr<basic_parser<T>> positive_sign;
    -
    2321 std::shared_ptr<basic_parser<T>> negative_sign;
    -
    2322 std::shared_ptr<basic_parser<T>> special_sign;
    -
    2323 std::shared_ptr<basic_parser<T>> currency;
    -
    2324 std::shared_ptr<basic_parser<T>> integer;
    -
    2325 std::shared_ptr<basic_parser<T>> decimal_separator;
    -
    2326 std::shared_ptr<basic_parser<T>> decimal;
    -
    2327 };
    +
    2202
    + + +
    2205#ifdef _UNICODE
    + +
    2207#else
    + +
    2209#endif
    + +
    2211
    +
    2215 template <class T>
    +
    + +
    2217 {
    +
    2218 public:
    + +
    2220 _In_ const std::shared_ptr<basic_parser<T>>& _positive_sign,
    +
    2221 _In_ const std::shared_ptr<basic_parser<T>>& _negative_sign,
    +
    2222 _In_ const std::shared_ptr<basic_parser<T>>& _special_sign,
    +
    2223 _In_ const std::shared_ptr<basic_parser<T>>& _currency,
    +
    2224 _In_ const std::shared_ptr<basic_parser<T>>& _integer,
    +
    2225 _In_ const std::shared_ptr<basic_parser<T>>& _decimal_separator,
    +
    2226 _In_ const std::shared_ptr<basic_parser<T>>& _decimal,
    +
    2227 _In_ const std::locale& locale = std::locale()) :
    +
    2228 basic_parser<T>(locale),
    + + + + + + + +
    2236 {}
    +
    2237
    +
    2238 virtual bool match(
    +
    2239 _In_reads_or_z_(end) const T* text,
    +
    2240 _In_ size_t start = 0,
    +
    2241 _In_ size_t end = (size_t)-1,
    +
    2242 _In_ int flags = match_default)
    +
    2243 {
    +
    2244 assert(text || start >= end);
    +
    2245 this->interval.end = start;
    +
    2246
    +
    2247 if (positive_sign->match(text, this->interval.end, end, flags)) {
    +
    2248 this->interval.end = positive_sign->interval.end;
    +
    2249 if (negative_sign) negative_sign->invalidate();
    +
    2250 if (special_sign) special_sign->invalidate();
    +
    2251 }
    +
    2252 else if (negative_sign->match(text, this->interval.end, end, flags)) {
    +
    2253 this->interval.end = negative_sign->interval.end;
    +
    2254 if (positive_sign) positive_sign->invalidate();
    +
    2255 if (special_sign) special_sign->invalidate();
    +
    2256 }
    +
    2257 else if (special_sign->match(text, this->interval.end, end, flags)) {
    +
    2258 this->interval.end = special_sign->interval.end;
    +
    2259 if (positive_sign) positive_sign->invalidate();
    +
    2260 if (negative_sign) negative_sign->invalidate();
    +
    2261 }
    +
    2262 else {
    +
    2263 if (positive_sign) positive_sign->invalidate();
    +
    2264 if (negative_sign) negative_sign->invalidate();
    +
    2265 if (special_sign) special_sign->invalidate();
    +
    2266 }
    +
    2267
    +
    2268 if (currency->match(text, this->interval.end, end, flags))
    +
    2269 this->interval.end = currency->interval.end;
    +
    2270 else {
    +
    2271 if (positive_sign) positive_sign->invalidate();
    +
    2272 if (negative_sign) negative_sign->invalidate();
    +
    2273 if (special_sign) special_sign->invalidate();
    +
    2274 integer->invalidate();
    +
    2275 decimal_separator->invalidate();
    +
    2276 decimal->invalidate();
    +
    2277 this->interval.start = (this->interval.end = start) + 1;
    +
    2278 return false;
    +
    2279 }
    +
    2280
    +
    2281 if (integer->match(text, this->interval.end, end, flags))
    +
    2282 this->interval.end = integer->interval.end;
    +
    2283 if (decimal_separator->match(text, this->interval.end, end, flags) &&
    + +
    2285 this->interval.end = decimal->interval.end;
    +
    2286 else {
    +
    2287 decimal_separator->invalidate();
    +
    2288 decimal->invalidate();
    +
    2289 }
    +
    2290
    +
    2291 if (integer->interval.empty() &&
    +
    2292 decimal->interval.empty())
    +
    2293 {
    +
    2294 // No integer part, no decimal part.
    +
    2295 if (positive_sign) positive_sign->invalidate();
    +
    2296 if (negative_sign) negative_sign->invalidate();
    +
    2297 if (special_sign) special_sign->invalidate();
    +
    2298 currency->invalidate();
    +
    2299 integer->invalidate();
    +
    2300 decimal_separator->invalidate();
    +
    2301 decimal->invalidate();
    +
    2302 this->interval.start = (this->interval.end = start) + 1;
    +
    2303 return false;
    +
    2304 }
    +
    2305
    +
    2306 this->interval.start = start;
    +
    2307 return true;
    +
    2308 }
    +
    2309
    +
    2310 virtual void invalidate()
    +
    2311 {
    +
    2312 if (positive_sign) positive_sign->invalidate();
    +
    2313 if (negative_sign) negative_sign->invalidate();
    +
    2314 if (special_sign) special_sign->invalidate();
    +
    2315 currency->invalidate();
    +
    2316 integer->invalidate();
    +
    2317 decimal_separator->invalidate();
    +
    2318 decimal->invalidate();
    + +
    2320 }
    +
    2321
    +
    2322 public:
    +
    2323 std::shared_ptr<basic_parser<T>> positive_sign;
    +
    2324 std::shared_ptr<basic_parser<T>> negative_sign;
    +
    2325 std::shared_ptr<basic_parser<T>> special_sign;
    +
    2326 std::shared_ptr<basic_parser<T>> currency;
    +
    2327 std::shared_ptr<basic_parser<T>> integer;
    +
    2328 std::shared_ptr<basic_parser<T>> decimal_separator;
    +
    2329 std::shared_ptr<basic_parser<T>> decimal;
    +
    2330 };
    -
    2328
    - - -
    2331#ifdef _UNICODE
    - -
    2333#else
    - -
    2335#endif
    - -
    2337
    -
    2341 template <class T>
    -
    - -
    2343 {
    -
    2344 public:
    - -
    2346 _In_ const std::shared_ptr<basic_parser<T>>& digit_0,
    -
    2347 _In_ const std::shared_ptr<basic_parser<T>>& digit_1,
    -
    2348 _In_ const std::shared_ptr<basic_parser<T>>& digit_2,
    -
    2349 _In_ const std::shared_ptr<basic_parser<T>>& digit_3,
    -
    2350 _In_ const std::shared_ptr<basic_parser<T>>& digit_4,
    -
    2351 _In_ const std::shared_ptr<basic_parser<T>>& digit_5,
    -
    2352 _In_ const std::shared_ptr<basic_parser<T>>& digit_6,
    -
    2353 _In_ const std::shared_ptr<basic_parser<T>>& digit_7,
    -
    2354 _In_ const std::shared_ptr<basic_parser<T>>& digit_8,
    -
    2355 _In_ const std::shared_ptr<basic_parser<T>>& digit_9,
    -
    2356 _In_ const std::shared_ptr<basic_parser<T>>& separator,
    -
    2357 _In_ const std::locale& locale = std::locale()) :
    -
    2358 basic_parser<T>(locale),
    -
    2359 m_digit_0(digit_0),
    -
    2360 m_digit_1(digit_1),
    -
    2361 m_digit_2(digit_2),
    -
    2362 m_digit_3(digit_3),
    -
    2363 m_digit_4(digit_4),
    -
    2364 m_digit_5(digit_5),
    -
    2365 m_digit_6(digit_6),
    -
    2366 m_digit_7(digit_7),
    -
    2367 m_digit_8(digit_8),
    -
    2368 m_digit_9(digit_9),
    -
    2369 m_separator(separator)
    -
    2370 {
    -
    2371 value.s_addr = 0;
    -
    2372 }
    -
    2373
    -
    2374 virtual bool match(
    -
    2375 _In_reads_or_z_(end) const T* text,
    -
    2376 _In_ size_t start = 0,
    -
    2377 _In_ size_t end = (size_t)-1,
    -
    2378 _In_ int flags = match_default)
    -
    2379 {
    -
    2380 assert(text || start >= end);
    -
    2381 interval.end = start;
    -
    2382 value.s_addr = 0;
    -
    2383
    -
    2384 size_t i;
    -
    2385 for (i = 0; i < 4; i++) {
    -
    2386 if (i) {
    -
    2387 if (m_separator->match(text, interval.end, end, flags))
    -
    2388 interval.end = m_separator->interval.end;
    -
    2389 else
    -
    2390 goto error;
    -
    2391 }
    -
    2392
    - -
    2394 bool is_empty = true;
    -
    2395 size_t x;
    -
    2396 for (x = 0; interval.end < end && text[interval.end];) {
    -
    2397 size_t dig, digit_end;
    -
    2398 if (m_digit_0->match(text, interval.end, end, flags)) { dig = 0; digit_end = m_digit_0->interval.end; }
    -
    2399 else if (m_digit_1->match(text, interval.end, end, flags)) { dig = 1; digit_end = m_digit_1->interval.end; }
    -
    2400 else if (m_digit_2->match(text, interval.end, end, flags)) { dig = 2; digit_end = m_digit_2->interval.end; }
    -
    2401 else if (m_digit_3->match(text, interval.end, end, flags)) { dig = 3; digit_end = m_digit_3->interval.end; }
    -
    2402 else if (m_digit_4->match(text, interval.end, end, flags)) { dig = 4; digit_end = m_digit_4->interval.end; }
    -
    2403 else if (m_digit_5->match(text, interval.end, end, flags)) { dig = 5; digit_end = m_digit_5->interval.end; }
    -
    2404 else if (m_digit_6->match(text, interval.end, end, flags)) { dig = 6; digit_end = m_digit_6->interval.end; }
    -
    2405 else if (m_digit_7->match(text, interval.end, end, flags)) { dig = 7; digit_end = m_digit_7->interval.end; }
    -
    2406 else if (m_digit_8->match(text, interval.end, end, flags)) { dig = 8; digit_end = m_digit_8->interval.end; }
    -
    2407 else if (m_digit_9->match(text, interval.end, end, flags)) { dig = 9; digit_end = m_digit_9->interval.end; }
    -
    2408 else break;
    -
    2409 size_t x_n = x * 10 + dig;
    -
    2410 if (x_n <= 255) {
    -
    2411 x = x_n;
    - -
    2413 is_empty = false;
    -
    2414 }
    -
    2415 else
    -
    2416 break;
    -
    2417 }
    -
    2418 if (is_empty)
    -
    2419 goto error;
    - -
    2421 value.s_addr = (value.s_addr << 8) | (uint8_t)x;
    -
    2422 }
    -
    2423 if (i < 4)
    -
    2424 goto error;
    -
    2425
    -
    2426 interval.start = start;
    -
    2427 return true;
    +
    2331
    + + +
    2334#ifdef _UNICODE
    + +
    2336#else
    + +
    2338#endif
    + +
    2340
    +
    2344 template <class T>
    +
    + +
    2346 {
    +
    2347 public:
    + +
    2349 _In_ const std::shared_ptr<basic_parser<T>>& digit_0,
    +
    2350 _In_ const std::shared_ptr<basic_parser<T>>& digit_1,
    +
    2351 _In_ const std::shared_ptr<basic_parser<T>>& digit_2,
    +
    2352 _In_ const std::shared_ptr<basic_parser<T>>& digit_3,
    +
    2353 _In_ const std::shared_ptr<basic_parser<T>>& digit_4,
    +
    2354 _In_ const std::shared_ptr<basic_parser<T>>& digit_5,
    +
    2355 _In_ const std::shared_ptr<basic_parser<T>>& digit_6,
    +
    2356 _In_ const std::shared_ptr<basic_parser<T>>& digit_7,
    +
    2357 _In_ const std::shared_ptr<basic_parser<T>>& digit_8,
    +
    2358 _In_ const std::shared_ptr<basic_parser<T>>& digit_9,
    +
    2359 _In_ const std::shared_ptr<basic_parser<T>>& separator,
    +
    2360 _In_ const std::locale& locale = std::locale()) :
    +
    2361 basic_parser<T>(locale),
    +
    2362 m_digit_0(digit_0),
    +
    2363 m_digit_1(digit_1),
    +
    2364 m_digit_2(digit_2),
    +
    2365 m_digit_3(digit_3),
    +
    2366 m_digit_4(digit_4),
    +
    2367 m_digit_5(digit_5),
    +
    2368 m_digit_6(digit_6),
    +
    2369 m_digit_7(digit_7),
    +
    2370 m_digit_8(digit_8),
    +
    2371 m_digit_9(digit_9),
    +
    2372 m_separator(separator)
    +
    2373 {
    +
    2374 value.s_addr = 0;
    +
    2375 }
    +
    2376
    +
    2377 virtual bool match(
    +
    2378 _In_reads_or_z_(end) const T* text,
    +
    2379 _In_ size_t start = 0,
    +
    2380 _In_ size_t end = (size_t)-1,
    +
    2381 _In_ int flags = match_default)
    +
    2382 {
    +
    2383 assert(text || start >= end);
    +
    2384 this->interval.end = start;
    +
    2385 value.s_addr = 0;
    +
    2386
    +
    2387 size_t i;
    +
    2388 for (i = 0; i < 4; i++) {
    +
    2389 if (i) {
    +
    2390 if (m_separator->match(text, this->interval.end, end, flags))
    +
    2391 this->interval.end = m_separator->interval.end;
    +
    2392 else
    +
    2393 goto error;
    +
    2394 }
    +
    2395
    +
    2396 components[i].start = this->interval.end;
    +
    2397 bool is_empty = true;
    +
    2398 size_t x;
    +
    2399 for (x = 0; this->interval.end < end && text[this->interval.end];) {
    +
    2400 size_t dig, digit_end;
    +
    2401 if (m_digit_0->match(text, this->interval.end, end, flags)) { dig = 0; digit_end = m_digit_0->interval.end; }
    +
    2402 else if (m_digit_1->match(text, this->interval.end, end, flags)) { dig = 1; digit_end = m_digit_1->interval.end; }
    +
    2403 else if (m_digit_2->match(text, this->interval.end, end, flags)) { dig = 2; digit_end = m_digit_2->interval.end; }
    +
    2404 else if (m_digit_3->match(text, this->interval.end, end, flags)) { dig = 3; digit_end = m_digit_3->interval.end; }
    +
    2405 else if (m_digit_4->match(text, this->interval.end, end, flags)) { dig = 4; digit_end = m_digit_4->interval.end; }
    +
    2406 else if (m_digit_5->match(text, this->interval.end, end, flags)) { dig = 5; digit_end = m_digit_5->interval.end; }
    +
    2407 else if (m_digit_6->match(text, this->interval.end, end, flags)) { dig = 6; digit_end = m_digit_6->interval.end; }
    +
    2408 else if (m_digit_7->match(text, this->interval.end, end, flags)) { dig = 7; digit_end = m_digit_7->interval.end; }
    +
    2409 else if (m_digit_8->match(text, this->interval.end, end, flags)) { dig = 8; digit_end = m_digit_8->interval.end; }
    +
    2410 else if (m_digit_9->match(text, this->interval.end, end, flags)) { dig = 9; digit_end = m_digit_9->interval.end; }
    +
    2411 else break;
    +
    2412 size_t x_n = x * 10 + dig;
    +
    2413 if (x_n <= 255) {
    +
    2414 x = x_n;
    +
    2415 this->interval.end = digit_end;
    +
    2416 is_empty = false;
    +
    2417 }
    +
    2418 else
    +
    2419 break;
    +
    2420 }
    +
    2421 if (is_empty)
    +
    2422 goto error;
    +
    2423 components[i].end = this->interval.end;
    +
    2424 value.s_addr = (value.s_addr << 8) | (uint8_t)x;
    +
    2425 }
    +
    2426 if (i < 4)
    +
    2427 goto error;
    2428
    -
    2429 error:
    -
    2430 components[0].start = 1;
    -
    2431 components[0].end = 0;
    -
    2432 components[1].start = 1;
    -
    2433 components[1].end = 0;
    -
    2434 components[2].start = 1;
    -
    2435 components[2].end = 0;
    -
    2436 components[3].start = 1;
    -
    2437 components[3].end = 0;
    -
    2438 value.s_addr = 0;
    -
    2439 interval.start = (interval.end = start) + 1;
    -
    2440 return false;
    -
    2441 }
    -
    2442
    -
    2443 virtual void invalidate()
    -
    2444 {
    -
    2445 components[0].start = 1;
    -
    2446 components[0].end = 0;
    -
    2447 components[1].start = 1;
    -
    2448 components[1].end = 0;
    -
    2449 components[2].start = 1;
    -
    2450 components[2].end = 0;
    -
    2451 components[3].start = 1;
    -
    2452 components[3].end = 0;
    -
    2453 value.s_addr = 0;
    - -
    2455 }
    -
    2456
    -
    2457 public:
    - - -
    2460
    -
    2461 protected:
    -
    2462 std::shared_ptr<basic_parser<T>>
    -
    2463 m_digit_0,
    -
    2464 m_digit_1,
    -
    2465 m_digit_2,
    -
    2466 m_digit_3,
    -
    2467 m_digit_4,
    -
    2468 m_digit_5,
    -
    2469 m_digit_6,
    -
    2470 m_digit_7,
    -
    2471 m_digit_8,
    -
    2472 m_digit_9;
    -
    2473 std::shared_ptr<basic_parser<T>> m_separator;
    -
    2474 };
    +
    2429 this->interval.start = start;
    +
    2430 return true;
    +
    2431
    +
    2432 error:
    +
    2433 components[0].start = 1;
    +
    2434 components[0].end = 0;
    +
    2435 components[1].start = 1;
    +
    2436 components[1].end = 0;
    +
    2437 components[2].start = 1;
    +
    2438 components[2].end = 0;
    +
    2439 components[3].start = 1;
    +
    2440 components[3].end = 0;
    +
    2441 value.s_addr = 0;
    +
    2442 this->interval.start = (this->interval.end = start) + 1;
    +
    2443 return false;
    +
    2444 }
    +
    2445
    +
    2446 virtual void invalidate()
    +
    2447 {
    +
    2448 components[0].start = 1;
    +
    2449 components[0].end = 0;
    +
    2450 components[1].start = 1;
    +
    2451 components[1].end = 0;
    +
    2452 components[2].start = 1;
    +
    2453 components[2].end = 0;
    +
    2454 components[3].start = 1;
    +
    2455 components[3].end = 0;
    +
    2456 value.s_addr = 0;
    + +
    2458 }
    +
    2459
    +
    2460 public:
    + + +
    2463
    +
    2464 protected:
    +
    2465 std::shared_ptr<basic_parser<T>>
    +
    2466 m_digit_0,
    +
    2467 m_digit_1,
    +
    2468 m_digit_2,
    +
    2469 m_digit_3,
    +
    2470 m_digit_4,
    +
    2471 m_digit_5,
    +
    2472 m_digit_6,
    +
    2473 m_digit_7,
    +
    2474 m_digit_8,
    +
    2475 m_digit_9;
    +
    2476 std::shared_ptr<basic_parser<T>> m_separator;
    +
    2477 };
    -
    2475
    - - -
    2478#ifdef _UNICODE
    - -
    2480#else
    - -
    2482#endif
    - -
    2484
    -
    2488 template <class T>
    -
    - -
    2490 {
    -
    2491 public:
    -
    2492 basic_ipv6_scope_id_char(_In_ const std::locale& locale = std::locale()) : basic_parser<T>(locale) {}
    -
    2493
    -
    2494 virtual bool match(
    -
    2495 _In_reads_or_z_(end) const T* text,
    -
    2496 _In_ size_t start = 0,
    -
    2497 _In_ size_t end = (size_t)-1,
    -
    2498 _In_ int flags = match_default)
    -
    2499 {
    -
    2500 assert(text || start >= end);
    -
    2501 if (start < end && text[start]) {
    -
    2502 if (text[start] == '-' ||
    -
    2503 text[start] == '_' ||
    -
    2504 text[start] == ':' ||
    -
    2505 std::use_facet<std::ctype<T>>(m_locale).is(std::ctype_base::alnum, text[start]))
    -
    2506 {
    -
    2507 interval.end = (interval.start = start) + 1;
    -
    2508 return true;
    -
    2509 }
    -
    2510 }
    -
    2511 interval.start = (interval.end = start) + 1;
    -
    2512 return false;
    -
    2513 }
    -
    2514 };
    +
    2478
    + + +
    2481#ifdef _UNICODE
    + +
    2483#else
    + +
    2485#endif
    + +
    2487
    +
    2491 template <class T>
    +
    + +
    2493 {
    +
    2494 public:
    +
    2495 basic_ipv6_scope_id_char(_In_ const std::locale& locale = std::locale()) : basic_parser<T>(locale) {}
    +
    2496
    +
    2497 virtual bool match(
    +
    2498 _In_reads_or_z_(end) const T* text,
    +
    2499 _In_ size_t start = 0,
    +
    2500 _In_ size_t end = (size_t)-1,
    +
    2501 _In_ int flags = match_default)
    +
    2502 {
    +
    2503 assert(text || start >= end);
    +
    2504 if (start < end && text[start]) {
    +
    2505 if (text[start] == '-' ||
    +
    2506 text[start] == '_' ||
    +
    2507 text[start] == ':' ||
    +
    2508 std::use_facet<std::ctype<T>>(this->m_locale).is(std::ctype_base::alnum, text[start]))
    +
    2509 {
    +
    2510 this->interval.end = (this->interval.start = start) + 1;
    +
    2511 return true;
    +
    2512 }
    +
    2513 }
    +
    2514 this->interval.start = (this->interval.end = start) + 1;
    +
    2515 return false;
    +
    2516 }
    +
    2517 };
    -
    2515
    - - -
    2518#ifdef _UNICODE
    - -
    2520#else
    - -
    2522#endif
    -
    2523
    -
    - -
    2528 {
    -
    2529 public:
    -
    2530 sgml_ipv6_scope_id_char(_In_ const std::locale& locale = std::locale()) : sgml_parser(locale) {}
    -
    2531
    -
    2532 virtual bool match(
    -
    2533 _In_reads_or_z_(end) const char* text,
    -
    2534 _In_ size_t start = 0,
    -
    2535 _In_ size_t end = (size_t)-1,
    -
    2536 _In_ int flags = match_default)
    -
    2537 {
    -
    2538 assert(text || start >= end);
    -
    2539 if (start < end && text[start]) {
    -
    2540 wchar_t buf[3];
    -
    2541 const wchar_t* chr = next_sgml_cp(text, start, end, interval.end, buf);
    -
    2542 const wchar_t* chr_end = chr + stdex::strlen(chr);
    -
    2543 if ((chr[0] == L'-' ||
    -
    2544 chr[0] == L'_' ||
    -
    2545 chr[0] == L':') && chr[1] == 0 ||
    -
    2546 std::use_facet<std::ctype<wchar_t>>(m_locale).scan_not(std::ctype_base::alnum, chr, chr_end) == chr_end)
    -
    2547 {
    -
    2548 interval.start = start;
    -
    2549 return true;
    -
    2550 }
    -
    2551 }
    -
    2552 interval.start = (interval.end = start) + 1;
    -
    2553 return false;
    -
    2554 }
    -
    2555 };
    +
    2518
    + + +
    2521#ifdef _UNICODE
    + +
    2523#else
    + +
    2525#endif
    +
    2526
    +
    + +
    2531 {
    +
    2532 public:
    +
    2533 sgml_ipv6_scope_id_char(_In_ const std::locale& locale = std::locale()) : sgml_parser(locale) {}
    +
    2534
    +
    2535 virtual bool match(
    +
    2536 _In_reads_or_z_(end) const char* text,
    +
    2537 _In_ size_t start = 0,
    +
    2538 _In_ size_t end = (size_t)-1,
    +
    2539 _In_ int flags = match_default)
    +
    2540 {
    +
    2541 assert(text || start >= end);
    +
    2542 if (start < end && text[start]) {
    +
    2543 wchar_t buf[3];
    +
    2544 const wchar_t* chr = next_sgml_cp(text, start, end, this->interval.end, buf);
    +
    2545 const wchar_t* chr_end = chr + stdex::strlen(chr);
    +
    2546 if (((chr[0] == L'-' ||
    +
    2547 chr[0] == L'_' ||
    +
    2548 chr[0] == L':') && chr[1] == 0) ||
    +
    2549 std::use_facet<std::ctype<wchar_t>>(m_locale).scan_not(std::ctype_base::alnum, chr, chr_end) == chr_end)
    +
    2550 {
    +
    2551 this->interval.start = start;
    +
    2552 return true;
    +
    2553 }
    +
    2554 }
    +
    2555 this->interval.start = (this->interval.end = start) + 1;
    +
    2556 return false;
    +
    2557 }
    +
    2558 };
    -
    2556
    -
    2560 template <class T>
    -
    - -
    2562 {
    -
    2563 public:
    - -
    2565 _In_ const std::shared_ptr<basic_parser<T>>& digit_0,
    -
    2566 _In_ const std::shared_ptr<basic_parser<T>>& digit_1,
    -
    2567 _In_ const std::shared_ptr<basic_parser<T>>& digit_2,
    -
    2568 _In_ const std::shared_ptr<basic_parser<T>>& digit_3,
    -
    2569 _In_ const std::shared_ptr<basic_parser<T>>& digit_4,
    -
    2570 _In_ const std::shared_ptr<basic_parser<T>>& digit_5,
    -
    2571 _In_ const std::shared_ptr<basic_parser<T>>& digit_6,
    -
    2572 _In_ const std::shared_ptr<basic_parser<T>>& digit_7,
    -
    2573 _In_ const std::shared_ptr<basic_parser<T>>& digit_8,
    -
    2574 _In_ const std::shared_ptr<basic_parser<T>>& digit_9,
    -
    2575 _In_ const std::shared_ptr<basic_parser<T>>& digit_10,
    -
    2576 _In_ const std::shared_ptr<basic_parser<T>>& digit_11,
    -
    2577 _In_ const std::shared_ptr<basic_parser<T>>& digit_12,
    -
    2578 _In_ const std::shared_ptr<basic_parser<T>>& digit_13,
    -
    2579 _In_ const std::shared_ptr<basic_parser<T>>& digit_14,
    -
    2580 _In_ const std::shared_ptr<basic_parser<T>>& digit_15,
    -
    2581 _In_ const std::shared_ptr<basic_parser<T>>& separator,
    -
    2582 _In_ const std::shared_ptr<basic_parser<T>>& scope_id_separator = nullptr,
    -
    2583 _In_ const std::shared_ptr<basic_parser<T>>& _scope_id = nullptr,
    -
    2584 _In_ const std::locale& locale = std::locale()) :
    -
    2585 basic_parser<T>(locale),
    -
    2586 m_digit_0(digit_0),
    -
    2587 m_digit_1(digit_1),
    -
    2588 m_digit_2(digit_2),
    -
    2589 m_digit_3(digit_3),
    -
    2590 m_digit_4(digit_4),
    -
    2591 m_digit_5(digit_5),
    -
    2592 m_digit_6(digit_6),
    -
    2593 m_digit_7(digit_7),
    -
    2594 m_digit_8(digit_8),
    -
    2595 m_digit_9(digit_9),
    -
    2596 m_digit_10(digit_10),
    -
    2597 m_digit_11(digit_11),
    -
    2598 m_digit_12(digit_12),
    -
    2599 m_digit_13(digit_13),
    -
    2600 m_digit_14(digit_14),
    -
    2601 m_digit_15(digit_15),
    -
    2602 m_separator(separator),
    -
    2603 m_scope_id_separator(scope_id_separator),
    - -
    2605 {
    -
    2606 memset(&value, 0, sizeof(value));
    -
    2607 }
    -
    2608
    -
    2609 virtual bool match(
    -
    2610 _In_reads_or_z_(end) const T* text,
    -
    2611 _In_ size_t start = 0,
    -
    2612 _In_ size_t end = (size_t)-1,
    -
    2613 _In_ int flags = match_default)
    -
    2614 {
    -
    2615 assert(text || start >= end);
    -
    2616 interval.end = start;
    -
    2617 memset(&value, 0, sizeof(value));
    -
    2618
    -
    2619 size_t i, compaction_i = (size_t)-1, compaction_start = start;
    -
    2620 for (i = 0; i < 8; i++) {
    -
    2621 bool is_empty = true;
    -
    2622
    -
    2623 if (m_separator->match(text, interval.end, end, flags)) {
    -
    2624 if (m_separator->match(text, m_separator->interval.end, end, flags)) {
    -
    2625 // :: found
    -
    2626 if (compaction_i == (size_t)-1) {
    -
    2627 // Zero compaction start
    -
    2628 compaction_i = i;
    -
    2629 compaction_start = m_separator->interval.start;
    -
    2630 interval.end = m_separator->interval.end;
    -
    2631 }
    -
    2632 else {
    -
    2633 // More than one zero compaction
    -
    2634 break;
    -
    2635 }
    -
    2636 }
    -
    2637 else if (i) {
    -
    2638 // Inner : found
    -
    2639 interval.end = m_separator->interval.end;
    -
    2640 }
    -
    2641 else {
    -
    2642 // Leading : found
    -
    2643 goto error;
    -
    2644 }
    -
    2645 }
    -
    2646 else if (i) {
    -
    2647 // : missing
    -
    2648 break;
    -
    2649 }
    -
    2650
    - -
    2652 size_t x;
    -
    2653 for (x = 0; interval.end < end && text[interval.end];) {
    -
    2654 size_t dig, digit_end;
    -
    2655 if (m_digit_0->match(text, interval.end, end, flags)) { dig = 0; digit_end = m_digit_0->interval.end; }
    -
    2656 else if (m_digit_1->match(text, interval.end, end, flags)) { dig = 1; digit_end = m_digit_1->interval.end; }
    -
    2657 else if (m_digit_2->match(text, interval.end, end, flags)) { dig = 2; digit_end = m_digit_2->interval.end; }
    -
    2658 else if (m_digit_3->match(text, interval.end, end, flags)) { dig = 3; digit_end = m_digit_3->interval.end; }
    -
    2659 else if (m_digit_4->match(text, interval.end, end, flags)) { dig = 4; digit_end = m_digit_4->interval.end; }
    -
    2660 else if (m_digit_5->match(text, interval.end, end, flags)) { dig = 5; digit_end = m_digit_5->interval.end; }
    -
    2661 else if (m_digit_6->match(text, interval.end, end, flags)) { dig = 6; digit_end = m_digit_6->interval.end; }
    -
    2662 else if (m_digit_7->match(text, interval.end, end, flags)) { dig = 7; digit_end = m_digit_7->interval.end; }
    -
    2663 else if (m_digit_8->match(text, interval.end, end, flags)) { dig = 8; digit_end = m_digit_8->interval.end; }
    -
    2664 else if (m_digit_9->match(text, interval.end, end, flags)) { dig = 9; digit_end = m_digit_9->interval.end; }
    -
    2665 else if (m_digit_10->match(text, interval.end, end, flags)) { dig = 10; digit_end = m_digit_10->interval.end; }
    -
    2666 else if (m_digit_11->match(text, interval.end, end, flags)) { dig = 11; digit_end = m_digit_11->interval.end; }
    -
    2667 else if (m_digit_12->match(text, interval.end, end, flags)) { dig = 12; digit_end = m_digit_12->interval.end; }
    -
    2668 else if (m_digit_13->match(text, interval.end, end, flags)) { dig = 13; digit_end = m_digit_13->interval.end; }
    -
    2669 else if (m_digit_14->match(text, interval.end, end, flags)) { dig = 14; digit_end = m_digit_14->interval.end; }
    -
    2670 else if (m_digit_15->match(text, interval.end, end, flags)) { dig = 15; digit_end = m_digit_15->interval.end; }
    -
    2671 else break;
    -
    2672 size_t x_n = x * 16 + dig;
    -
    2673 if (x_n <= 0xffff) {
    -
    2674 x = x_n;
    - -
    2676 is_empty = false;
    -
    2677 }
    -
    2678 else
    -
    2679 break;
    -
    2680 }
    -
    2681 if (is_empty) {
    -
    2682 if (compaction_i != (size_t)-1) {
    -
    2683 // Zero compaction active: no sweat.
    -
    2684 break;
    -
    2685 }
    -
    2686 goto error;
    -
    2687 }
    - -
    2689 value.s6_words[i] = (uint16_t)x;
    -
    2690 }
    -
    2691
    -
    2692 if (compaction_i != (size_t)-1) {
    -
    2693 // Align components right due to zero compaction.
    -
    2694 size_t j, k;
    -
    2695 for (j = 8, k = i; k > compaction_i;) {
    -
    2696 value.s6_words[--j] = value.s6_words[--k];
    - -
    2698 }
    -
    2699 for (; j > compaction_i;) {
    -
    2700 value.s6_words[--j] = 0;
    -
    2701 components[j].start =
    - -
    2703 }
    -
    2704 }
    -
    2705 else if (i < 8)
    -
    2706 goto error;
    -
    2707
    -
    2708 if (m_scope_id_separator && m_scope_id_separator->match(text, interval.end, end, flags) &&
    -
    2709 scope_id && scope_id->match(text, m_scope_id_separator->interval.end, end, flags))
    -
    2710 interval.end = scope_id->interval.end;
    -
    2711 else if (scope_id)
    -
    2712 scope_id->invalidate();
    -
    2713
    -
    2714 interval.start = start;
    -
    2715 return true;
    +
    2559
    +
    2563 template <class T>
    +
    + +
    2565 {
    +
    2566 public:
    + +
    2568 _In_ const std::shared_ptr<basic_parser<T>>& digit_0,
    +
    2569 _In_ const std::shared_ptr<basic_parser<T>>& digit_1,
    +
    2570 _In_ const std::shared_ptr<basic_parser<T>>& digit_2,
    +
    2571 _In_ const std::shared_ptr<basic_parser<T>>& digit_3,
    +
    2572 _In_ const std::shared_ptr<basic_parser<T>>& digit_4,
    +
    2573 _In_ const std::shared_ptr<basic_parser<T>>& digit_5,
    +
    2574 _In_ const std::shared_ptr<basic_parser<T>>& digit_6,
    +
    2575 _In_ const std::shared_ptr<basic_parser<T>>& digit_7,
    +
    2576 _In_ const std::shared_ptr<basic_parser<T>>& digit_8,
    +
    2577 _In_ const std::shared_ptr<basic_parser<T>>& digit_9,
    +
    2578 _In_ const std::shared_ptr<basic_parser<T>>& digit_10,
    +
    2579 _In_ const std::shared_ptr<basic_parser<T>>& digit_11,
    +
    2580 _In_ const std::shared_ptr<basic_parser<T>>& digit_12,
    +
    2581 _In_ const std::shared_ptr<basic_parser<T>>& digit_13,
    +
    2582 _In_ const std::shared_ptr<basic_parser<T>>& digit_14,
    +
    2583 _In_ const std::shared_ptr<basic_parser<T>>& digit_15,
    +
    2584 _In_ const std::shared_ptr<basic_parser<T>>& separator,
    +
    2585 _In_ const std::shared_ptr<basic_parser<T>>& scope_id_separator = nullptr,
    +
    2586 _In_ const std::shared_ptr<basic_parser<T>>& _scope_id = nullptr,
    +
    2587 _In_ const std::locale& locale = std::locale()) :
    +
    2588 basic_parser<T>(locale),
    +
    2589 m_digit_0(digit_0),
    +
    2590 m_digit_1(digit_1),
    +
    2591 m_digit_2(digit_2),
    +
    2592 m_digit_3(digit_3),
    +
    2593 m_digit_4(digit_4),
    +
    2594 m_digit_5(digit_5),
    +
    2595 m_digit_6(digit_6),
    +
    2596 m_digit_7(digit_7),
    +
    2597 m_digit_8(digit_8),
    +
    2598 m_digit_9(digit_9),
    +
    2599 m_digit_10(digit_10),
    +
    2600 m_digit_11(digit_11),
    +
    2601 m_digit_12(digit_12),
    +
    2602 m_digit_13(digit_13),
    +
    2603 m_digit_14(digit_14),
    +
    2604 m_digit_15(digit_15),
    +
    2605 m_separator(separator),
    +
    2606 m_scope_id_separator(scope_id_separator),
    + +
    2608 {
    +
    2609 memset(&value, 0, sizeof(value));
    +
    2610 }
    +
    2611
    +
    2612 virtual bool match(
    +
    2613 _In_reads_or_z_(end) const T* text,
    +
    2614 _In_ size_t start = 0,
    +
    2615 _In_ size_t end = (size_t)-1,
    +
    2616 _In_ int flags = match_default)
    +
    2617 {
    +
    2618 assert(text || start >= end);
    +
    2619 this->interval.end = start;
    +
    2620 memset(&value, 0, sizeof(value));
    +
    2621
    +
    2622 size_t i, compaction_i = (size_t)-1, compaction_start = start;
    +
    2623 for (i = 0; i < 8; i++) {
    +
    2624 bool is_empty = true;
    +
    2625
    +
    2626 if (m_separator->match(text, this->interval.end, end, flags)) {
    +
    2627 if (m_separator->match(text, m_separator->interval.end, end, flags)) {
    +
    2628 // :: found
    +
    2629 if (compaction_i == (size_t)-1) {
    +
    2630 // Zero compaction start
    +
    2631 compaction_i = i;
    +
    2632 compaction_start = m_separator->interval.start;
    +
    2633 this->interval.end = m_separator->interval.end;
    +
    2634 }
    +
    2635 else {
    +
    2636 // More than one zero compaction
    +
    2637 break;
    +
    2638 }
    +
    2639 }
    +
    2640 else if (i) {
    +
    2641 // Inner : found
    +
    2642 this->interval.end = m_separator->interval.end;
    +
    2643 }
    +
    2644 else {
    +
    2645 // Leading : found
    +
    2646 goto error;
    +
    2647 }
    +
    2648 }
    +
    2649 else if (i) {
    +
    2650 // : missing
    +
    2651 break;
    +
    2652 }
    +
    2653
    +
    2654 components[i].start = this->interval.end;
    +
    2655 size_t x;
    +
    2656 for (x = 0; this->interval.end < end && text[this->interval.end];) {
    +
    2657 size_t dig, digit_end;
    +
    2658 if (m_digit_0->match(text, this->interval.end, end, flags)) { dig = 0; digit_end = m_digit_0->interval.end; }
    +
    2659 else if (m_digit_1->match(text, this->interval.end, end, flags)) { dig = 1; digit_end = m_digit_1->interval.end; }
    +
    2660 else if (m_digit_2->match(text, this->interval.end, end, flags)) { dig = 2; digit_end = m_digit_2->interval.end; }
    +
    2661 else if (m_digit_3->match(text, this->interval.end, end, flags)) { dig = 3; digit_end = m_digit_3->interval.end; }
    +
    2662 else if (m_digit_4->match(text, this->interval.end, end, flags)) { dig = 4; digit_end = m_digit_4->interval.end; }
    +
    2663 else if (m_digit_5->match(text, this->interval.end, end, flags)) { dig = 5; digit_end = m_digit_5->interval.end; }
    +
    2664 else if (m_digit_6->match(text, this->interval.end, end, flags)) { dig = 6; digit_end = m_digit_6->interval.end; }
    +
    2665 else if (m_digit_7->match(text, this->interval.end, end, flags)) { dig = 7; digit_end = m_digit_7->interval.end; }
    +
    2666 else if (m_digit_8->match(text, this->interval.end, end, flags)) { dig = 8; digit_end = m_digit_8->interval.end; }
    +
    2667 else if (m_digit_9->match(text, this->interval.end, end, flags)) { dig = 9; digit_end = m_digit_9->interval.end; }
    +
    2668 else if (m_digit_10->match(text, this->interval.end, end, flags)) { dig = 10; digit_end = m_digit_10->interval.end; }
    +
    2669 else if (m_digit_11->match(text, this->interval.end, end, flags)) { dig = 11; digit_end = m_digit_11->interval.end; }
    +
    2670 else if (m_digit_12->match(text, this->interval.end, end, flags)) { dig = 12; digit_end = m_digit_12->interval.end; }
    +
    2671 else if (m_digit_13->match(text, this->interval.end, end, flags)) { dig = 13; digit_end = m_digit_13->interval.end; }
    +
    2672 else if (m_digit_14->match(text, this->interval.end, end, flags)) { dig = 14; digit_end = m_digit_14->interval.end; }
    +
    2673 else if (m_digit_15->match(text, this->interval.end, end, flags)) { dig = 15; digit_end = m_digit_15->interval.end; }
    +
    2674 else break;
    +
    2675 size_t x_n = x * 16 + dig;
    +
    2676 if (x_n <= 0xffff) {
    +
    2677 x = x_n;
    +
    2678 this->interval.end = digit_end;
    +
    2679 is_empty = false;
    +
    2680 }
    +
    2681 else
    +
    2682 break;
    +
    2683 }
    +
    2684 if (is_empty) {
    +
    2685 if (compaction_i != (size_t)-1) {
    +
    2686 // Zero compaction active: no sweat.
    +
    2687 break;
    +
    2688 }
    +
    2689 goto error;
    +
    2690 }
    +
    2691 components[i].end = this->interval.end;
    +
    2692 this->value.s6_words[i] = (uint16_t)x;
    +
    2693 }
    +
    2694
    +
    2695 if (compaction_i != (size_t)-1) {
    +
    2696 // Align components right due to zero compaction.
    +
    2697 size_t j, k;
    +
    2698 for (j = 8, k = i; k > compaction_i;) {
    +
    2699 this->value.s6_words[--j] = this->value.s6_words[--k];
    + +
    2701 }
    +
    2702 for (; j > compaction_i;) {
    +
    2703 this->value.s6_words[--j] = 0;
    +
    2704 components[j].start =
    + +
    2706 }
    +
    2707 }
    +
    2708 else if (i < 8)
    +
    2709 goto error;
    +
    2710
    +
    2711 if (m_scope_id_separator && m_scope_id_separator->match(text, this->interval.end, end, flags) &&
    +
    2712 scope_id && scope_id->match(text, m_scope_id_separator->interval.end, end, flags))
    +
    2713 this->interval.end = scope_id->interval.end;
    +
    2714 else if (scope_id)
    +
    2715 scope_id->invalidate();
    2716
    -
    2717 error:
    -
    2718 components[0].start = 1;
    -
    2719 components[0].end = 0;
    -
    2720 components[1].start = 1;
    -
    2721 components[1].end = 0;
    -
    2722 components[2].start = 1;
    -
    2723 components[2].end = 0;
    -
    2724 components[3].start = 1;
    -
    2725 components[3].end = 0;
    -
    2726 components[4].start = 1;
    -
    2727 components[4].end = 0;
    -
    2728 components[5].start = 1;
    -
    2729 components[5].end = 0;
    -
    2730 components[6].start = 1;
    -
    2731 components[6].end = 0;
    -
    2732 components[7].start = 1;
    -
    2733 components[7].end = 0;
    -
    2734 memset(&value, 0, sizeof(value));
    -
    2735 if (scope_id) scope_id->invalidate();
    -
    2736 interval.start = (interval.end = start) + 1;
    -
    2737 return false;
    -
    2738 }
    -
    2739
    -
    2740 virtual void invalidate()
    -
    2741 {
    -
    2742 components[0].start = 1;
    -
    2743 components[0].end = 0;
    -
    2744 components[1].start = 1;
    -
    2745 components[1].end = 0;
    -
    2746 components[2].start = 1;
    -
    2747 components[2].end = 0;
    -
    2748 components[3].start = 1;
    -
    2749 components[3].end = 0;
    -
    2750 components[4].start = 1;
    -
    2751 components[4].end = 0;
    -
    2752 components[5].start = 1;
    -
    2753 components[5].end = 0;
    -
    2754 components[6].start = 1;
    -
    2755 components[6].end = 0;
    -
    2756 components[7].start = 1;
    -
    2757 components[7].end = 0;
    -
    2758 memset(&value, 0, sizeof(value));
    -
    2759 if (scope_id) scope_id->invalidate();
    - -
    2761 }
    -
    2762
    -
    2763 public:
    - - -
    2766 std::shared_ptr<basic_parser<T>> scope_id;
    -
    2767
    -
    2768 protected:
    -
    2769 std::shared_ptr<basic_parser<T>>
    -
    2770 m_digit_0,
    -
    2771 m_digit_1,
    -
    2772 m_digit_2,
    -
    2773 m_digit_3,
    -
    2774 m_digit_4,
    -
    2775 m_digit_5,
    -
    2776 m_digit_6,
    -
    2777 m_digit_7,
    -
    2778 m_digit_8,
    -
    2779 m_digit_9,
    -
    2780 m_digit_10,
    -
    2781 m_digit_11,
    -
    2782 m_digit_12,
    -
    2783 m_digit_13,
    -
    2784 m_digit_14,
    -
    2785 m_digit_15;
    -
    2786 std::shared_ptr<basic_parser<T>> m_separator, m_scope_id_separator;
    -
    2787 };
    +
    2717 this->interval.start = start;
    +
    2718 return true;
    +
    2719
    +
    2720 error:
    +
    2721 components[0].start = 1;
    +
    2722 components[0].end = 0;
    +
    2723 components[1].start = 1;
    +
    2724 components[1].end = 0;
    +
    2725 components[2].start = 1;
    +
    2726 components[2].end = 0;
    +
    2727 components[3].start = 1;
    +
    2728 components[3].end = 0;
    +
    2729 components[4].start = 1;
    +
    2730 components[4].end = 0;
    +
    2731 components[5].start = 1;
    +
    2732 components[5].end = 0;
    +
    2733 components[6].start = 1;
    +
    2734 components[6].end = 0;
    +
    2735 components[7].start = 1;
    +
    2736 components[7].end = 0;
    +
    2737 memset(&value, 0, sizeof(value));
    +
    2738 if (scope_id) scope_id->invalidate();
    +
    2739 this->interval.start = (this->interval.end = start) + 1;
    +
    2740 return false;
    +
    2741 }
    +
    2742
    +
    2743 virtual void invalidate()
    +
    2744 {
    +
    2745 components[0].start = 1;
    +
    2746 components[0].end = 0;
    +
    2747 components[1].start = 1;
    +
    2748 components[1].end = 0;
    +
    2749 components[2].start = 1;
    +
    2750 components[2].end = 0;
    +
    2751 components[3].start = 1;
    +
    2752 components[3].end = 0;
    +
    2753 components[4].start = 1;
    +
    2754 components[4].end = 0;
    +
    2755 components[5].start = 1;
    +
    2756 components[5].end = 0;
    +
    2757 components[6].start = 1;
    +
    2758 components[6].end = 0;
    +
    2759 components[7].start = 1;
    +
    2760 components[7].end = 0;
    +
    2761 memset(&value, 0, sizeof(value));
    +
    2762 if (scope_id) scope_id->invalidate();
    + +
    2764 }
    +
    2765
    +
    2766 public:
    + + +
    2769 std::shared_ptr<basic_parser<T>> scope_id;
    +
    2770
    +
    2771 protected:
    +
    2772 std::shared_ptr<basic_parser<T>>
    +
    2773 m_digit_0,
    +
    2774 m_digit_1,
    +
    2775 m_digit_2,
    +
    2776 m_digit_3,
    +
    2777 m_digit_4,
    +
    2778 m_digit_5,
    +
    2779 m_digit_6,
    +
    2780 m_digit_7,
    +
    2781 m_digit_8,
    +
    2782 m_digit_9,
    +
    2783 m_digit_10,
    +
    2784 m_digit_11,
    +
    2785 m_digit_12,
    +
    2786 m_digit_13,
    +
    2787 m_digit_14,
    +
    2788 m_digit_15;
    +
    2789 std::shared_ptr<basic_parser<T>> m_separator, m_scope_id_separator;
    +
    2790 };
    -
    2788
    - - -
    2791#ifdef _UNICODE
    - -
    2793#else
    - -
    2795#endif
    - -
    2797
    -
    2801 template <class T>
    -
    - -
    2803 {
    -
    2804 public:
    - -
    2806 _In_ bool allow_idn,
    -
    2807 _In_ const std::locale& locale = std::locale()) :
    -
    2808 basic_parser<T>(locale),
    -
    2809 m_allow_idn(allow_idn),
    -
    2810 allow_on_edge(true)
    -
    2811 {}
    -
    2812
    -
    2813 virtual bool match(
    -
    2814 _In_reads_or_z_(end) const T* text,
    -
    2815 _In_ size_t start = 0,
    -
    2816 _In_ size_t end = (size_t)-1,
    -
    2817 _In_ int flags = match_default)
    -
    2818 {
    -
    2819 assert(text || start >= end);
    -
    2820 if (start < end && text[start]) {
    -
    2821 if (('A' <= text[start] && text[start] <= 'Z') ||
    -
    2822 ('a' <= text[start] && text[start] <= 'z') ||
    -
    2823 ('0' <= text[start] && text[start] <= '9'))
    -
    2824 allow_on_edge = true;
    -
    2825 else if (text[start] == '-')
    -
    2826 allow_on_edge = false;
    -
    2827 else if (m_allow_idn && std::use_facet<std::ctype<T>>(m_locale).is(std::ctype_base::alnum, text[start]))
    -
    2828 allow_on_edge = true;
    -
    2829 else {
    -
    2830 interval.start = (interval.end = start) + 1;
    -
    2831 return false;
    -
    2832 }
    -
    2833 interval.end = (interval.start = start) + 1;
    -
    2834 return true;
    -
    2835 }
    -
    2836 interval.start = (interval.end = start) + 1;
    -
    2837 return false;
    -
    2838 }
    -
    2839
    -
    2840 public:
    - +
    2791
    + + +
    2794#ifdef _UNICODE
    + +
    2796#else
    + +
    2798#endif
    + +
    2800
    +
    2804 template <class T>
    +
    + +
    2806 {
    +
    2807 public:
    + +
    2809 _In_ bool allow_idn,
    +
    2810 _In_ const std::locale& locale = std::locale()) :
    +
    2811 basic_parser<T>(locale),
    +
    2812 m_allow_idn(allow_idn),
    +
    2813 allow_on_edge(true)
    +
    2814 {}
    +
    2815
    +
    2816 virtual bool match(
    +
    2817 _In_reads_or_z_(end) const T* text,
    +
    2818 _In_ size_t start = 0,
    +
    2819 _In_ size_t end = (size_t)-1,
    +
    2820 _In_ int flags = match_default)
    +
    2821 {
    +
    2822 assert(text || start >= end);
    +
    2823 if (start < end && text[start]) {
    +
    2824 if (('A' <= text[start] && text[start] <= 'Z') ||
    +
    2825 ('a' <= text[start] && text[start] <= 'z') ||
    +
    2826 ('0' <= text[start] && text[start] <= '9'))
    +
    2827 allow_on_edge = true;
    +
    2828 else if (text[start] == '-')
    +
    2829 allow_on_edge = false;
    +
    2830 else if (m_allow_idn && std::use_facet<std::ctype<T>>(this->m_locale).is(std::ctype_base::alnum, text[start]))
    +
    2831 allow_on_edge = true;
    +
    2832 else {
    +
    2833 this->interval.start = (this->interval.end = start) + 1;
    +
    2834 return false;
    +
    2835 }
    +
    2836 this->interval.end = (this->interval.start = start) + 1;
    +
    2837 return true;
    +
    2838 }
    +
    2839 this->interval.start = (this->interval.end = start) + 1;
    +
    2840 return false;
    +
    2841 }
    2842
    -
    2843 protected:
    -
    2844 bool m_allow_idn;
    -
    2845 };
    +
    2843 public:
    + +
    2845
    +
    2846 protected:
    +
    2847 bool m_allow_idn;
    +
    2848 };
    -
    2846
    - - -
    2849#ifdef _UNICODE
    - -
    2851#else
    - -
    2853#endif
    -
    2854
    -
    - -
    2859 {
    -
    2860 public:
    - -
    2862 _In_ bool allow_idn,
    -
    2863 _In_ const std::locale& locale = std::locale()) :
    - -
    2865 {}
    -
    2866
    -
    2867 virtual bool match(
    -
    2868 _In_reads_or_z_(end) const char* text,
    -
    2869 _In_ size_t start = 0,
    -
    2870 _In_ size_t end = (size_t)-1,
    -
    2871 _In_ int flags = match_default)
    -
    2872 {
    -
    2873 assert(text || start >= end);
    -
    2874 if (start < end && text[start]) {
    -
    2875 wchar_t buf[3];
    -
    2876 const wchar_t* chr = next_sgml_cp(text, start, end, interval.end, buf);
    -
    2877 const wchar_t* chr_end = chr + stdex::strlen(chr);
    -
    2878 if ((('A' <= chr[0] && chr[0] <= 'Z') ||
    -
    2879 ('a' <= chr[0] && chr[0] <= 'z') ||
    -
    2880 ('0' <= chr[0] && chr[0] <= '9')) && chr[1] == 0)
    -
    2881 allow_on_edge = true;
    -
    2882 else if (chr[0] == '-' && chr[1] == 0)
    -
    2883 allow_on_edge = false;
    -
    2884 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)
    -
    2885 allow_on_edge = true;
    -
    2886 else {
    -
    2887 interval.start = (interval.end = start) + 1;
    -
    2888 return false;
    -
    2889 }
    -
    2890 interval.start = start;
    -
    2891 return true;
    -
    2892 }
    -
    2893 interval.start = (interval.end = start) + 1;
    -
    2894 return false;
    -
    2895 }
    -
    2896 };
    +
    2849
    + + +
    2852#ifdef _UNICODE
    + +
    2854#else
    + +
    2856#endif
    +
    2857
    +
    + +
    2862 {
    +
    2863 public:
    + +
    2865 _In_ bool allow_idn,
    +
    2866 _In_ const std::locale& locale = std::locale()) :
    + +
    2868 {}
    +
    2869
    +
    2870 virtual bool match(
    +
    2871 _In_reads_or_z_(end) const char* text,
    +
    2872 _In_ size_t start = 0,
    +
    2873 _In_ size_t end = (size_t)-1,
    +
    2874 _In_ int flags = match_default)
    +
    2875 {
    +
    2876 assert(text || start >= end);
    +
    2877 if (start < end && text[start]) {
    +
    2878 wchar_t buf[3];
    +
    2879 const wchar_t* chr = next_sgml_cp(text, start, end, this->interval.end, buf);
    +
    2880 const wchar_t* chr_end = chr + stdex::strlen(chr);
    +
    2881 if ((('A' <= chr[0] && chr[0] <= 'Z') ||
    +
    2882 ('a' <= chr[0] && chr[0] <= 'z') ||
    +
    2883 ('0' <= chr[0] && chr[0] <= '9')) && chr[1] == 0)
    +
    2884 allow_on_edge = true;
    +
    2885 else if (chr[0] == '-' && chr[1] == 0)
    +
    2886 allow_on_edge = false;
    +
    2887 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)
    +
    2888 allow_on_edge = true;
    +
    2889 else {
    +
    2890 this->interval.start = (this->interval.end = start) + 1;
    +
    2891 return false;
    +
    2892 }
    +
    2893 this->interval.start = start;
    +
    2894 return true;
    +
    2895 }
    +
    2896 this->interval.start = (this->interval.end = start) + 1;
    +
    2897 return false;
    +
    2898 }
    +
    2899 };
    -
    2897
    -
    2901 template <class T>
    -
    - -
    2903 {
    -
    2904 public:
    - -
    2906 _In_ bool allow_absolute,
    -
    2907 _In_ const std::shared_ptr<basic_dns_domain_char<T>>& domain_char,
    -
    2908 _In_ const std::shared_ptr<basic_parser<T>>& separator,
    -
    2909 _In_ const std::locale& locale = std::locale()) :
    -
    2910 basic_parser<T>(locale),
    - -
    2912 m_domain_char(domain_char),
    -
    2913 m_separator(separator)
    -
    2914 {}
    -
    2915
    -
    2916 virtual bool match(
    -
    2917 _In_reads_or_z_(end) const T* text,
    -
    2918 _In_ size_t start = 0,
    -
    2919 _In_ size_t end = (size_t)-1,
    -
    2920 _In_ int flags = match_default)
    -
    2921 {
    -
    2922 assert(text || start >= end);
    -
    2923 size_t i = start, count;
    -
    2924 for (count = 0; i < end && text[i] && count < 127; count++) {
    -
    2925 if (m_domain_char->match(text, i, end, flags) &&
    -
    2926 m_domain_char->allow_on_edge)
    -
    2927 {
    -
    2928 // Domain start
    -
    2929 interval.end = i = m_domain_char->interval.end;
    -
    2930 while (i < end && text[i]) {
    -
    2931 if (m_domain_char->allow_on_edge &&
    -
    2932 m_separator->match(text, i, end, flags))
    -
    2933 {
    -
    2934 // Domain end
    -
    2935 if (m_allow_absolute)
    -
    2936 interval.end = i = m_separator->interval.end;
    -
    2937 else {
    -
    2938 interval.end = i;
    -
    2939 i = m_separator->interval.end;
    -
    2940 }
    -
    2941 break;
    -
    2942 }
    -
    2943 if (m_domain_char->match(text, i, end, flags)) {
    -
    2944 if (m_domain_char->allow_on_edge)
    -
    2945 interval.end = i = m_domain_char->interval.end;
    -
    2946 else
    -
    2947 i = m_domain_char->interval.end;
    -
    2948 }
    -
    2949 else {
    -
    2950 interval.start = start;
    -
    2951 return true;
    -
    2952 }
    -
    2953 }
    -
    2954 }
    -
    2955 else
    -
    2956 break;
    -
    2957 }
    -
    2958 if (count) {
    -
    2959 interval.start = start;
    -
    2960 return true;
    -
    2961 }
    -
    2962 interval.start = (interval.end = start) + 1;
    -
    2963 return false;
    -
    2964 }
    -
    2965
    -
    2966 protected:
    - -
    2968 std::shared_ptr<basic_dns_domain_char<T>> m_domain_char;
    -
    2969 std::shared_ptr<basic_parser<T>> m_separator;
    -
    2970 };
    +
    2900
    +
    2904 template <class T>
    +
    + +
    2906 {
    +
    2907 public:
    + +
    2909 _In_ bool allow_absolute,
    +
    2910 _In_ const std::shared_ptr<basic_dns_domain_char<T>>& domain_char,
    +
    2911 _In_ const std::shared_ptr<basic_parser<T>>& separator,
    +
    2912 _In_ const std::locale& locale = std::locale()) :
    +
    2913 basic_parser<T>(locale),
    + +
    2915 m_domain_char(domain_char),
    +
    2916 m_separator(separator)
    +
    2917 {}
    +
    2918
    +
    2919 virtual bool match(
    +
    2920 _In_reads_or_z_(end) const T* text,
    +
    2921 _In_ size_t start = 0,
    +
    2922 _In_ size_t end = (size_t)-1,
    +
    2923 _In_ int flags = match_default)
    +
    2924 {
    +
    2925 assert(text || start >= end);
    +
    2926 size_t i = start, count;
    +
    2927 for (count = 0; i < end && text[i] && count < 127; count++) {
    +
    2928 if (m_domain_char->match(text, i, end, flags) &&
    +
    2929 m_domain_char->allow_on_edge)
    +
    2930 {
    +
    2931 // Domain start
    +
    2932 this->interval.end = i = m_domain_char->interval.end;
    +
    2933 while (i < end && text[i]) {
    +
    2934 if (m_domain_char->allow_on_edge &&
    +
    2935 m_separator->match(text, i, end, flags))
    +
    2936 {
    +
    2937 // Domain end
    +
    2938 if (m_allow_absolute)
    +
    2939 this->interval.end = i = m_separator->interval.end;
    +
    2940 else {
    +
    2941 this->interval.end = i;
    +
    2942 i = m_separator->interval.end;
    +
    2943 }
    +
    2944 break;
    +
    2945 }
    +
    2946 if (m_domain_char->match(text, i, end, flags)) {
    +
    2947 if (m_domain_char->allow_on_edge)
    +
    2948 this->interval.end = i = m_domain_char->interval.end;
    +
    2949 else
    +
    2950 i = m_domain_char->interval.end;
    +
    2951 }
    +
    2952 else {
    +
    2953 this->interval.start = start;
    +
    2954 return true;
    +
    2955 }
    +
    2956 }
    +
    2957 }
    +
    2958 else
    +
    2959 break;
    +
    2960 }
    +
    2961 if (count) {
    +
    2962 this->interval.start = start;
    +
    2963 return true;
    +
    2964 }
    +
    2965 this->interval.start = (this->interval.end = start) + 1;
    +
    2966 return false;
    +
    2967 }
    +
    2968
    +
    2969 protected:
    + +
    2971 std::shared_ptr<basic_dns_domain_char<T>> m_domain_char;
    +
    2972 std::shared_ptr<basic_parser<T>> m_separator;
    +
    2973 };
    -
    2971
    - - -
    2974#ifdef _UNICODE
    -
    2975 using tdns_name = wdns_name;
    -
    2976#else
    -
    2977 using tdns_name = dns_name;
    -
    2978#endif
    - -
    2980
    -
    2984 template <class T>
    -
    - -
    2986 {
    -
    2987 public:
    -
    2988 basic_url_username_char(_In_ const std::locale& locale = std::locale()) : basic_parser<T>(locale) {}
    -
    2989
    -
    2990 virtual bool match(
    -
    2991 _In_reads_or_z_(end) const T* text,
    -
    2992 _In_ size_t start = 0,
    -
    2993 _In_ size_t end = (size_t)-1,
    -
    2994 _In_ int flags = match_default)
    -
    2995 {
    -
    2996 assert(text || start >= end);
    -
    2997 if (start < end && text[start]) {
    -
    2998 if (text[start] == '-' ||
    -
    2999 text[start] == '.' ||
    -
    3000 text[start] == '_' ||
    -
    3001 text[start] == '~' ||
    -
    3002 text[start] == '%' ||
    -
    3003 text[start] == '!' ||
    -
    3004 text[start] == '$' ||
    -
    3005 text[start] == '&' ||
    -
    3006 text[start] == '\'' ||
    -
    3007 //text[start] == '(' ||
    -
    3008 //text[start] == ')' ||
    -
    3009 text[start] == '*' ||
    -
    3010 text[start] == '+' ||
    -
    3011 text[start] == ',' ||
    -
    3012 text[start] == ';' ||
    -
    3013 text[start] == '=' ||
    -
    3014 std::use_facet<std::ctype<T>>(m_locale).is(std::ctype_base::alnum, text[start]))
    -
    3015 {
    -
    3016 interval.end = (interval.start = start) + 1;
    -
    3017 return true;
    -
    3018 }
    -
    3019 }
    -
    3020 interval.start = (interval.end = start) + 1;
    -
    3021 return false;
    -
    3022 }
    -
    3023 };
    +
    2974
    + + +
    2977#ifdef _UNICODE
    +
    2978 using tdns_name = wdns_name;
    +
    2979#else
    +
    2980 using tdns_name = dns_name;
    +
    2981#endif
    + +
    2983
    +
    2987 template <class T>
    +
    + +
    2989 {
    +
    2990 public:
    +
    2991 basic_url_username_char(_In_ const std::locale& locale = std::locale()) : basic_parser<T>(locale) {}
    +
    2992
    +
    2993 virtual bool match(
    +
    2994 _In_reads_or_z_(end) const T* text,
    +
    2995 _In_ size_t start = 0,
    +
    2996 _In_ size_t end = (size_t)-1,
    +
    2997 _In_ int flags = match_default)
    +
    2998 {
    +
    2999 assert(text || start >= end);
    +
    3000 if (start < end && text[start]) {
    +
    3001 if (text[start] == '-' ||
    +
    3002 text[start] == '.' ||
    +
    3003 text[start] == '_' ||
    +
    3004 text[start] == '~' ||
    +
    3005 text[start] == '%' ||
    +
    3006 text[start] == '!' ||
    +
    3007 text[start] == '$' ||
    +
    3008 text[start] == '&' ||
    +
    3009 text[start] == '\'' ||
    +
    3010 //text[start] == '(' ||
    +
    3011 //text[start] == ')' ||
    +
    3012 text[start] == '*' ||
    +
    3013 text[start] == '+' ||
    +
    3014 text[start] == ',' ||
    +
    3015 text[start] == ';' ||
    +
    3016 text[start] == '=' ||
    +
    3017 std::use_facet<std::ctype<T>>(this->m_locale).is(std::ctype_base::alnum, text[start]))
    +
    3018 {
    +
    3019 this->interval.end = (this->interval.start = start) + 1;
    +
    3020 return true;
    +
    3021 }
    +
    3022 }
    +
    3023 this->interval.start = (this->interval.end = start) + 1;
    +
    3024 return false;
    +
    3025 }
    +
    3026 };
    -
    3024
    - - -
    3027#ifdef _UNICODE
    - -
    3029#else
    - -
    3031#endif
    -
    3032
    -
    - -
    3037 {
    -
    3038 public:
    -
    3039 sgml_url_username_char(_In_ const std::locale& locale = std::locale()) : basic_url_username_char<char>(locale) {}
    -
    3040
    -
    3041 virtual bool match(
    -
    3042 _In_reads_or_z_(end) const char* text,
    -
    3043 _In_ size_t start = 0,
    -
    3044 _In_ size_t end = (size_t)-1,
    -
    3045 _In_ int flags = match_default)
    -
    3046 {
    -
    3047 assert(text || start >= end);
    -
    3048 if (start < end && text[start]) {
    -
    3049 wchar_t buf[3];
    -
    3050 const wchar_t* chr = next_sgml_cp(text, start, end, interval.end, buf);
    -
    3051 const wchar_t* chr_end = chr + stdex::strlen(chr);
    -
    3052 if ((chr[0] == L'-' ||
    -
    3053 chr[0] == L'.' ||
    -
    3054 chr[0] == L'_' ||
    -
    3055 chr[0] == L'~' ||
    -
    3056 chr[0] == L'%' ||
    -
    3057 chr[0] == L'!' ||
    -
    3058 chr[0] == L'$' ||
    -
    3059 chr[0] == L'&' ||
    -
    3060 chr[0] == L'\'' ||
    -
    3061 //chr[0] == L'(' ||
    -
    3062 //chr[0] == L')' ||
    -
    3063 chr[0] == L'*' ||
    -
    3064 chr[0] == L'+' ||
    -
    3065 chr[0] == L',' ||
    -
    3066 chr[0] == L';' ||
    -
    3067 chr[0] == L'=') && chr[1] == 0 ||
    -
    3068 std::use_facet<std::ctype<wchar_t>>(m_locale).scan_not(std::ctype_base::alnum, chr, chr_end) == chr_end)
    -
    3069 {
    -
    3070 interval.start = start;
    -
    3071 return true;
    -
    3072 }
    -
    3073 }
    -
    3074
    -
    3075 interval.start = (interval.end = start) + 1;
    -
    3076 return false;
    -
    3077 }
    -
    3078 };
    +
    3027
    + + +
    3030#ifdef _UNICODE
    + +
    3032#else
    + +
    3034#endif
    +
    3035
    +
    + +
    3040 {
    +
    3041 public:
    +
    3042 sgml_url_username_char(_In_ const std::locale& locale = std::locale()) : basic_url_username_char<char>(locale) {}
    +
    3043
    +
    3044 virtual bool match(
    +
    3045 _In_reads_or_z_(end) const char* text,
    +
    3046 _In_ size_t start = 0,
    +
    3047 _In_ size_t end = (size_t)-1,
    +
    3048 _In_ int flags = match_default)
    +
    3049 {
    +
    3050 assert(text || start >= end);
    +
    3051 if (start < end && text[start]) {
    +
    3052 wchar_t buf[3];
    +
    3053 const wchar_t* chr = next_sgml_cp(text, start, end, this->interval.end, buf);
    +
    3054 const wchar_t* chr_end = chr + stdex::strlen(chr);
    +
    3055 if (((chr[0] == L'-' ||
    +
    3056 chr[0] == L'.' ||
    +
    3057 chr[0] == L'_' ||
    +
    3058 chr[0] == L'~' ||
    +
    3059 chr[0] == L'%' ||
    +
    3060 chr[0] == L'!' ||
    +
    3061 chr[0] == L'$' ||
    +
    3062 chr[0] == L'&' ||
    +
    3063 chr[0] == L'\'' ||
    +
    3064 //chr[0] == L'(' ||
    +
    3065 //chr[0] == L')' ||
    +
    3066 chr[0] == L'*' ||
    +
    3067 chr[0] == L'+' ||
    +
    3068 chr[0] == L',' ||
    +
    3069 chr[0] == L';' ||
    +
    3070 chr[0] == L'=') && chr[1] == 0) ||
    +
    3071 std::use_facet<std::ctype<wchar_t>>(m_locale).scan_not(std::ctype_base::alnum, chr, chr_end) == chr_end)
    +
    3072 {
    +
    3073 this->interval.start = start;
    +
    3074 return true;
    +
    3075 }
    +
    3076 }
    +
    3077
    +
    3078 this->interval.start = (this->interval.end = start) + 1;
    +
    3079 return false;
    +
    3080 }
    +
    3081 };
    -
    3079
    -
    3083 template <class T>
    -
    - -
    3085 {
    -
    3086 public:
    -
    3087 basic_url_password_char(_In_ const std::locale& locale = std::locale()) : basic_parser<T>(locale) {}
    -
    3088
    -
    3089 virtual bool match(
    -
    3090 _In_reads_or_z_(end) const T* text,
    -
    3091 _In_ size_t start = 0,
    -
    3092 _In_ size_t end = (size_t)-1,
    -
    3093 _In_ int flags = match_default)
    -
    3094 {
    -
    3095 assert(text || start >= end);
    -
    3096 if (start < end && text[start]) {
    -
    3097 if (text[start] == '-' ||
    -
    3098 text[start] == '.' ||
    -
    3099 text[start] == '_' ||
    -
    3100 text[start] == '~' ||
    -
    3101 text[start] == '%' ||
    -
    3102 text[start] == '!' ||
    -
    3103 text[start] == '$' ||
    -
    3104 text[start] == '&' ||
    -
    3105 text[start] == '\'' ||
    -
    3106 text[start] == '(' ||
    -
    3107 text[start] == ')' ||
    -
    3108 text[start] == '*' ||
    -
    3109 text[start] == '+' ||
    -
    3110 text[start] == ',' ||
    -
    3111 text[start] == ';' ||
    -
    3112 text[start] == '=' ||
    -
    3113 text[start] == ':' ||
    -
    3114 std::use_facet<std::ctype<T>>(m_locale).is(std::ctype_base::alnum, text[start]))
    -
    3115 {
    -
    3116 interval.end = (interval.start = start) + 1;
    -
    3117 return true;
    -
    3118 }
    -
    3119 }
    -
    3120 interval.start = (interval.end = start) + 1;
    -
    3121 return false;
    -
    3122 }
    -
    3123 };
    +
    3082
    +
    3086 template <class T>
    +
    + +
    3088 {
    +
    3089 public:
    +
    3090 basic_url_password_char(_In_ const std::locale& locale = std::locale()) : basic_parser<T>(locale) {}
    +
    3091
    +
    3092 virtual bool match(
    +
    3093 _In_reads_or_z_(end) const T* text,
    +
    3094 _In_ size_t start = 0,
    +
    3095 _In_ size_t end = (size_t)-1,
    +
    3096 _In_ int flags = match_default)
    +
    3097 {
    +
    3098 assert(text || start >= end);
    +
    3099 if (start < end && text[start]) {
    +
    3100 if (text[start] == '-' ||
    +
    3101 text[start] == '.' ||
    +
    3102 text[start] == '_' ||
    +
    3103 text[start] == '~' ||
    +
    3104 text[start] == '%' ||
    +
    3105 text[start] == '!' ||
    +
    3106 text[start] == '$' ||
    +
    3107 text[start] == '&' ||
    +
    3108 text[start] == '\'' ||
    +
    3109 text[start] == '(' ||
    +
    3110 text[start] == ')' ||
    +
    3111 text[start] == '*' ||
    +
    3112 text[start] == '+' ||
    +
    3113 text[start] == ',' ||
    +
    3114 text[start] == ';' ||
    +
    3115 text[start] == '=' ||
    +
    3116 text[start] == ':' ||
    +
    3117 std::use_facet<std::ctype<T>>(this->m_locale).is(std::ctype_base::alnum, text[start]))
    +
    3118 {
    +
    3119 this->interval.end = (this->interval.start = start) + 1;
    +
    3120 return true;
    +
    3121 }
    +
    3122 }
    +
    3123 this->interval.start = (this->interval.end = start) + 1;
    +
    3124 return false;
    +
    3125 }
    +
    3126 };
    -
    3124
    - - -
    3127#ifdef _UNICODE
    - -
    3129#else
    - -
    3131#endif
    -
    3132
    -
    - -
    3137 {
    -
    3138 public:
    -
    3139 sgml_url_password_char(_In_ const std::locale& locale = std::locale()) : basic_url_password_char<char>(locale) {}
    -
    3140
    -
    3141 virtual bool match(
    -
    3142 _In_reads_or_z_(end) const char* text,
    -
    3143 _In_ size_t start = 0,
    -
    3144 _In_ size_t end = (size_t)-1,
    -
    3145 _In_ int flags = match_default)
    -
    3146 {
    -
    3147 assert(text || start >= end);
    -
    3148 if (start < end && text[start]) {
    -
    3149 wchar_t buf[3];
    -
    3150 const wchar_t* chr = next_sgml_cp(text, start, end, interval.end, buf);
    -
    3151 const wchar_t* chr_end = chr + stdex::strlen(chr);
    -
    3152 if ((chr[0] == L'-' ||
    -
    3153 chr[0] == L'.' ||
    -
    3154 chr[0] == L'_' ||
    -
    3155 chr[0] == L'~' ||
    -
    3156 chr[0] == L'%' ||
    -
    3157 chr[0] == L'!' ||
    -
    3158 chr[0] == L'$' ||
    -
    3159 chr[0] == L'&' ||
    -
    3160 chr[0] == L'\'' ||
    -
    3161 chr[0] == L'(' ||
    -
    3162 chr[0] == L')' ||
    -
    3163 chr[0] == L'*' ||
    -
    3164 chr[0] == L'+' ||
    -
    3165 chr[0] == L',' ||
    -
    3166 chr[0] == L';' ||
    -
    3167 chr[0] == L'=' ||
    -
    3168 chr[0] == L':') && chr[1] == 0 ||
    -
    3169 std::use_facet<std::ctype<wchar_t>>(m_locale).scan_not(std::ctype_base::alnum, chr, chr_end) == chr_end)
    -
    3170 {
    -
    3171 interval.start = start;
    -
    3172 return true;
    -
    3173 }
    -
    3174 }
    -
    3175 interval.start = (interval.end = start) + 1;
    -
    3176 return false;
    -
    3177 }
    -
    3178 };
    +
    3127
    + + +
    3130#ifdef _UNICODE
    + +
    3132#else
    + +
    3134#endif
    +
    3135
    +
    + +
    3140 {
    +
    3141 public:
    +
    3142 sgml_url_password_char(_In_ const std::locale& locale = std::locale()) : basic_url_password_char<char>(locale) {}
    +
    3143
    +
    3144 virtual bool match(
    +
    3145 _In_reads_or_z_(end) const char* text,
    +
    3146 _In_ size_t start = 0,
    +
    3147 _In_ size_t end = (size_t)-1,
    +
    3148 _In_ int flags = match_default)
    +
    3149 {
    +
    3150 assert(text || start >= end);
    +
    3151 if (start < end && text[start]) {
    +
    3152 wchar_t buf[3];
    +
    3153 const wchar_t* chr = next_sgml_cp(text, start, end, this->interval.end, buf);
    +
    3154 const wchar_t* chr_end = chr + stdex::strlen(chr);
    +
    3155 if (((chr[0] == L'-' ||
    +
    3156 chr[0] == L'.' ||
    +
    3157 chr[0] == L'_' ||
    +
    3158 chr[0] == L'~' ||
    +
    3159 chr[0] == L'%' ||
    +
    3160 chr[0] == L'!' ||
    +
    3161 chr[0] == L'$' ||
    +
    3162 chr[0] == L'&' ||
    +
    3163 chr[0] == L'\'' ||
    +
    3164 chr[0] == L'(' ||
    +
    3165 chr[0] == L')' ||
    +
    3166 chr[0] == L'*' ||
    +
    3167 chr[0] == L'+' ||
    +
    3168 chr[0] == L',' ||
    +
    3169 chr[0] == L';' ||
    +
    3170 chr[0] == L'=' ||
    +
    3171 chr[0] == L':') && chr[1] == 0) ||
    +
    3172 std::use_facet<std::ctype<wchar_t>>(m_locale).scan_not(std::ctype_base::alnum, chr, chr_end) == chr_end)
    +
    3173 {
    +
    3174 this->interval.start = start;
    +
    3175 return true;
    +
    3176 }
    +
    3177 }
    +
    3178 this->interval.start = (this->interval.end = start) + 1;
    +
    3179 return false;
    +
    3180 }
    +
    3181 };
    -
    3179
    -
    3183 template <class T>
    -
    - -
    3185 {
    -
    3186 public:
    -
    3187 basic_url_path_char(_In_ const std::locale& locale = std::locale()) : basic_parser<T>(locale) {}
    -
    3188
    -
    3189 virtual bool match(
    -
    3190 _In_reads_or_z_(end) const T* text,
    -
    3191 _In_ size_t start = 0,
    -
    3192 _In_ size_t end = (size_t)-1,
    -
    3193 _In_ int flags = match_default)
    -
    3194 {
    -
    3195 assert(text || start >= end);
    -
    3196 if (start < end && text[start]) {
    -
    3197 if (text[start] == '/' ||
    -
    3198 text[start] == '-' ||
    -
    3199 text[start] == '.' ||
    -
    3200 text[start] == '_' ||
    -
    3201 text[start] == '~' ||
    -
    3202 text[start] == '%' ||
    -
    3203 text[start] == '!' ||
    -
    3204 text[start] == '$' ||
    -
    3205 text[start] == '&' ||
    -
    3206 text[start] == '\'' ||
    -
    3207 text[start] == '(' ||
    -
    3208 text[start] == ')' ||
    -
    3209 text[start] == '*' ||
    -
    3210 text[start] == '+' ||
    -
    3211 text[start] == ',' ||
    -
    3212 text[start] == ';' ||
    -
    3213 text[start] == '=' ||
    -
    3214 text[start] == ':' ||
    -
    3215 text[start] == '@' ||
    -
    3216 text[start] == '?' ||
    -
    3217 text[start] == '#' ||
    -
    3218 std::use_facet<std::ctype<T>>(m_locale).is(std::ctype_base::alnum, text[start]))
    -
    3219 {
    -
    3220 interval.end = (interval.start = start) + 1;
    -
    3221 return true;
    -
    3222 }
    -
    3223 }
    -
    3224 interval.start = (interval.end = start) + 1;
    -
    3225 return false;
    -
    3226 }
    -
    3227 };
    +
    3182
    +
    3186 template <class T>
    +
    + +
    3188 {
    +
    3189 public:
    +
    3190 basic_url_path_char(_In_ const std::locale& locale = std::locale()) : basic_parser<T>(locale) {}
    +
    3191
    +
    3192 virtual bool match(
    +
    3193 _In_reads_or_z_(end) const T* text,
    +
    3194 _In_ size_t start = 0,
    +
    3195 _In_ size_t end = (size_t)-1,
    +
    3196 _In_ int flags = match_default)
    +
    3197 {
    +
    3198 assert(text || start >= end);
    +
    3199 if (start < end && text[start]) {
    +
    3200 if (text[start] == '/' ||
    +
    3201 text[start] == '-' ||
    +
    3202 text[start] == '.' ||
    +
    3203 text[start] == '_' ||
    +
    3204 text[start] == '~' ||
    +
    3205 text[start] == '%' ||
    +
    3206 text[start] == '!' ||
    +
    3207 text[start] == '$' ||
    +
    3208 text[start] == '&' ||
    +
    3209 text[start] == '\'' ||
    +
    3210 text[start] == '(' ||
    +
    3211 text[start] == ')' ||
    +
    3212 text[start] == '*' ||
    +
    3213 text[start] == '+' ||
    +
    3214 text[start] == ',' ||
    +
    3215 text[start] == ';' ||
    +
    3216 text[start] == '=' ||
    +
    3217 text[start] == ':' ||
    +
    3218 text[start] == '@' ||
    +
    3219 text[start] == '?' ||
    +
    3220 text[start] == '#' ||
    +
    3221 std::use_facet<std::ctype<T>>(this->m_locale).is(std::ctype_base::alnum, text[start]))
    +
    3222 {
    +
    3223 this->interval.end = (this->interval.start = start) + 1;
    +
    3224 return true;
    +
    3225 }
    +
    3226 }
    +
    3227 this->interval.start = (this->interval.end = start) + 1;
    +
    3228 return false;
    +
    3229 }
    +
    3230 };
    -
    3228
    - - -
    3231#ifdef _UNICODE
    - -
    3233#else
    - -
    3235#endif
    -
    3236
    -
    - -
    3241 {
    -
    3242 public:
    -
    3243 sgml_url_path_char(_In_ const std::locale& locale = std::locale()) : basic_url_path_char<char>(locale) {}
    -
    3244
    -
    3245 virtual bool match(
    -
    3246 _In_reads_or_z_(end) const char* text,
    -
    3247 _In_ size_t start = 0,
    -
    3248 _In_ size_t end = (size_t)-1,
    -
    3249 _In_ int flags = match_default)
    -
    3250 {
    -
    3251 assert(text || start >= end);
    -
    3252 if (start < end && text[start]) {
    -
    3253 wchar_t buf[3];
    -
    3254 const wchar_t* chr = next_sgml_cp(text, start, end, interval.end, buf);
    -
    3255 const wchar_t* chr_end = chr + stdex::strlen(chr);
    -
    3256 if ((chr[0] == L'/' ||
    -
    3257 chr[0] == L'-' ||
    -
    3258 chr[0] == L'.' ||
    -
    3259 chr[0] == L'_' ||
    -
    3260 chr[0] == L'~' ||
    -
    3261 chr[0] == L'%' ||
    -
    3262 chr[0] == L'!' ||
    -
    3263 chr[0] == L'$' ||
    -
    3264 chr[0] == L'&' ||
    -
    3265 chr[0] == L'\'' ||
    -
    3266 chr[0] == L'(' ||
    -
    3267 chr[0] == L')' ||
    -
    3268 chr[0] == L'*' ||
    -
    3269 chr[0] == L'+' ||
    -
    3270 chr[0] == L',' ||
    -
    3271 chr[0] == L';' ||
    -
    3272 chr[0] == L'=' ||
    -
    3273 chr[0] == L':' ||
    -
    3274 chr[0] == L'@' ||
    -
    3275 chr[0] == L'?' ||
    -
    3276 chr[0] == L'#') && chr[1] == 0 ||
    -
    3277 std::use_facet<std::ctype<wchar_t>>(m_locale).scan_not(std::ctype_base::alnum, chr, chr_end) == chr_end)
    -
    3278 {
    -
    3279 interval.start = start;
    -
    3280 return true;
    -
    3281 }
    -
    3282 }
    -
    3283 interval.start = (interval.end = start) + 1;
    -
    3284 return false;
    -
    3285 }
    -
    3286 };
    +
    3231
    + + +
    3234#ifdef _UNICODE
    + +
    3236#else
    + +
    3238#endif
    +
    3239
    +
    + +
    3244 {
    +
    3245 public:
    +
    3246 sgml_url_path_char(_In_ const std::locale& locale = std::locale()) : basic_url_path_char<char>(locale) {}
    +
    3247
    +
    3248 virtual bool match(
    +
    3249 _In_reads_or_z_(end) const char* text,
    +
    3250 _In_ size_t start = 0,
    +
    3251 _In_ size_t end = (size_t)-1,
    +
    3252 _In_ int flags = match_default)
    +
    3253 {
    +
    3254 assert(text || start >= end);
    +
    3255 if (start < end && text[start]) {
    +
    3256 wchar_t buf[3];
    +
    3257 const wchar_t* chr = next_sgml_cp(text, start, end, this->interval.end, buf);
    +
    3258 const wchar_t* chr_end = chr + stdex::strlen(chr);
    +
    3259 if (((chr[0] == L'/' ||
    +
    3260 chr[0] == L'-' ||
    +
    3261 chr[0] == L'.' ||
    +
    3262 chr[0] == L'_' ||
    +
    3263 chr[0] == L'~' ||
    +
    3264 chr[0] == L'%' ||
    +
    3265 chr[0] == L'!' ||
    +
    3266 chr[0] == L'$' ||
    +
    3267 chr[0] == L'&' ||
    +
    3268 chr[0] == L'\'' ||
    +
    3269 chr[0] == L'(' ||
    +
    3270 chr[0] == L')' ||
    +
    3271 chr[0] == L'*' ||
    +
    3272 chr[0] == L'+' ||
    +
    3273 chr[0] == L',' ||
    +
    3274 chr[0] == L';' ||
    +
    3275 chr[0] == L'=' ||
    +
    3276 chr[0] == L':' ||
    +
    3277 chr[0] == L'@' ||
    +
    3278 chr[0] == L'?' ||
    +
    3279 chr[0] == L'#') && chr[1] == 0) ||
    +
    3280 std::use_facet<std::ctype<wchar_t>>(m_locale).scan_not(std::ctype_base::alnum, chr, chr_end) == chr_end)
    +
    3281 {
    +
    3282 this->interval.start = start;
    +
    3283 return true;
    +
    3284 }
    +
    3285 }
    +
    3286 this->interval.start = (this->interval.end = start) + 1;
    +
    3287 return false;
    +
    3288 }
    +
    3289 };
    -
    3287
    -
    3291 template <class T>
    -
    - -
    3293 {
    -
    3294 public:
    - -
    3296 _In_ const std::shared_ptr<basic_parser<T>>& path_char,
    -
    3297 _In_ const std::shared_ptr<basic_parser<T>>& query_start,
    -
    3298 _In_ const std::shared_ptr<basic_parser<T>>& bookmark_start,
    -
    3299 _In_ const std::locale& locale = std::locale()) :
    -
    3300 basic_parser<T>(locale),
    -
    3301 m_path_char(path_char),
    -
    3302 m_query_start(query_start),
    -
    3303 m_bookmark_start(bookmark_start)
    -
    3304 {}
    -
    3305
    -
    3306 virtual bool match(
    -
    3307 _In_reads_or_z_(end) const T* text,
    -
    3308 _In_ size_t start = 0,
    -
    3309 _In_ size_t end = (size_t)-1,
    -
    3310 _In_ int flags = match_default)
    -
    3311 {
    -
    3312 assert(text || start >= end);
    -
    3313
    -
    3314 interval.end = start;
    -
    3315 path.start = start;
    -
    3316 query.start = 1;
    -
    3317 query.end = 0;
    -
    3318 bookmark.start = 1;
    -
    3319 bookmark.end = 0;
    -
    3320
    -
    3321 for (;;) {
    -
    3322 if (interval.end >= end || !text[interval.end])
    -
    3323 break;
    -
    3324 if (m_query_start->match(text, interval.end, end, flags)) {
    -
    3325 path.end = interval.end;
    -
    3326 query.start = interval.end = m_query_start->interval.end;
    -
    3327 for (;;) {
    -
    3328 if (interval.end >= end || !text[interval.end]) {
    -
    3329 query.end = interval.end;
    -
    3330 break;
    -
    3331 }
    -
    3332 if (m_bookmark_start->match(text, interval.end, end, flags)) {
    -
    3333 query.end = interval.end;
    -
    3334 bookmark.start = interval.end = m_bookmark_start->interval.end;
    -
    3335 for (;;) {
    -
    3336 if (interval.end >= end || !text[interval.end]) {
    -
    3337 bookmark.end = interval.end;
    -
    3338 break;
    -
    3339 }
    -
    3340 if (m_path_char->match(text, interval.end, end, flags))
    -
    3341 interval.end = m_path_char->interval.end;
    -
    3342 else {
    -
    3343 bookmark.end = interval.end;
    -
    3344 break;
    -
    3345 }
    -
    3346 }
    -
    3347 interval.start = start;
    -
    3348 return true;
    -
    3349 }
    -
    3350 if (m_path_char->match(text, interval.end, end, flags))
    -
    3351 interval.end = m_path_char->interval.end;
    -
    3352 else {
    -
    3353 query.end = interval.end;
    -
    3354 break;
    -
    3355 }
    -
    3356 }
    -
    3357 interval.start = start;
    -
    3358 return true;
    -
    3359 }
    -
    3360 if (m_bookmark_start->match(text, interval.end, end, flags)) {
    -
    3361 path.end = interval.end;
    -
    3362 bookmark.start = interval.end = m_bookmark_start->interval.end;
    -
    3363 for (;;) {
    -
    3364 if (interval.end >= end || !text[interval.end]) {
    -
    3365 bookmark.end = interval.end;
    -
    3366 break;
    -
    3367 }
    -
    3368 if (m_path_char->match(text, interval.end, end, flags))
    -
    3369 interval.end = m_path_char->interval.end;
    -
    3370 else {
    -
    3371 bookmark.end = interval.end;
    -
    3372 break;
    -
    3373 }
    -
    3374 }
    -
    3375 interval.start = start;
    -
    3376 return true;
    -
    3377 }
    -
    3378 if (m_path_char->match(text, interval.end, end, flags))
    -
    3379 interval.end = m_path_char->interval.end;
    -
    3380 else
    -
    3381 break;
    -
    3382 }
    -
    3383
    -
    3384 if (start < interval.end) {
    -
    3385 path.end = interval.end;
    -
    3386 interval.start = start;
    -
    3387 return true;
    -
    3388 }
    -
    3389
    -
    3390 path.start = 1;
    -
    3391 path.end = 0;
    -
    3392 bookmark.start = 1;
    -
    3393 bookmark.end = 0;
    -
    3394 interval.start = (interval.end = start) + 1;
    -
    3395 return false;
    -
    3396 }
    -
    3397
    -
    3398 virtual void invalidate()
    -
    3399 {
    -
    3400 path.start = 1;
    -
    3401 path.end = 0;
    -
    3402 query.start = 1;
    -
    3403 query.end = 0;
    -
    3404 bookmark.start = 1;
    -
    3405 bookmark.end = 0;
    - -
    3407 }
    -
    3408
    -
    3409 public:
    - - -
    3412 stdex::interval<size_t> bookmark;
    -
    3413
    -
    3414 protected:
    -
    3415 std::shared_ptr<basic_parser<T>> m_path_char;
    -
    3416 std::shared_ptr<basic_parser<T>> m_query_start;
    -
    3417 std::shared_ptr<basic_parser<T>> m_bookmark_start;
    -
    3418 };
    +
    3290
    +
    3294 template <class T>
    +
    + +
    3296 {
    +
    3297 public:
    + +
    3299 _In_ const std::shared_ptr<basic_parser<T>>& path_char,
    +
    3300 _In_ const std::shared_ptr<basic_parser<T>>& query_start,
    +
    3301 _In_ const std::shared_ptr<basic_parser<T>>& bookmark_start,
    +
    3302 _In_ const std::locale& locale = std::locale()) :
    +
    3303 basic_parser<T>(locale),
    +
    3304 m_path_char(path_char),
    +
    3305 m_query_start(query_start),
    +
    3306 m_bookmark_start(bookmark_start)
    +
    3307 {}
    +
    3308
    +
    3309 virtual bool match(
    +
    3310 _In_reads_or_z_(end) const T* text,
    +
    3311 _In_ size_t start = 0,
    +
    3312 _In_ size_t end = (size_t)-1,
    +
    3313 _In_ int flags = match_default)
    +
    3314 {
    +
    3315 assert(text || start >= end);
    +
    3316
    +
    3317 this->interval.end = start;
    +
    3318 path.start = start;
    +
    3319 query.start = 1;
    +
    3320 query.end = 0;
    +
    3321 bookmark.start = 1;
    +
    3322 bookmark.end = 0;
    +
    3323
    +
    3324 for (;;) {
    +
    3325 if (this->interval.end >= end || !text[this->interval.end])
    +
    3326 break;
    +
    3327 if (m_query_start->match(text, this->interval.end, end, flags)) {
    +
    3328 path.end = this->interval.end;
    +
    3329 query.start = this->interval.end = m_query_start->interval.end;
    +
    3330 for (;;) {
    +
    3331 if (this->interval.end >= end || !text[this->interval.end]) {
    +
    3332 query.end = this->interval.end;
    +
    3333 break;
    +
    3334 }
    +
    3335 if (m_bookmark_start->match(text, this->interval.end, end, flags)) {
    +
    3336 query.end = this->interval.end;
    +
    3337 bookmark.start = this->interval.end = m_bookmark_start->interval.end;
    +
    3338 for (;;) {
    +
    3339 if (this->interval.end >= end || !text[this->interval.end]) {
    +
    3340 bookmark.end = this->interval.end;
    +
    3341 break;
    +
    3342 }
    +
    3343 if (m_path_char->match(text, this->interval.end, end, flags))
    +
    3344 this->interval.end = m_path_char->interval.end;
    +
    3345 else {
    +
    3346 bookmark.end = this->interval.end;
    +
    3347 break;
    +
    3348 }
    +
    3349 }
    +
    3350 this->interval.start = start;
    +
    3351 return true;
    +
    3352 }
    +
    3353 if (m_path_char->match(text, this->interval.end, end, flags))
    +
    3354 this->interval.end = m_path_char->interval.end;
    +
    3355 else {
    +
    3356 query.end = this->interval.end;
    +
    3357 break;
    +
    3358 }
    +
    3359 }
    +
    3360 this->interval.start = start;
    +
    3361 return true;
    +
    3362 }
    +
    3363 if (m_bookmark_start->match(text, this->interval.end, end, flags)) {
    +
    3364 path.end = this->interval.end;
    +
    3365 bookmark.start = this->interval.end = m_bookmark_start->interval.end;
    +
    3366 for (;;) {
    +
    3367 if (this->interval.end >= end || !text[this->interval.end]) {
    +
    3368 bookmark.end = this->interval.end;
    +
    3369 break;
    +
    3370 }
    +
    3371 if (m_path_char->match(text, this->interval.end, end, flags))
    +
    3372 this->interval.end = m_path_char->interval.end;
    +
    3373 else {
    +
    3374 bookmark.end = this->interval.end;
    +
    3375 break;
    +
    3376 }
    +
    3377 }
    +
    3378 this->interval.start = start;
    +
    3379 return true;
    +
    3380 }
    +
    3381 if (m_path_char->match(text, this->interval.end, end, flags))
    +
    3382 this->interval.end = m_path_char->interval.end;
    +
    3383 else
    +
    3384 break;
    +
    3385 }
    +
    3386
    + +
    3388 path.end = this->interval.end;
    +
    3389 this->interval.start = start;
    +
    3390 return true;
    +
    3391 }
    +
    3392
    +
    3393 path.start = 1;
    +
    3394 path.end = 0;
    +
    3395 bookmark.start = 1;
    +
    3396 bookmark.end = 0;
    +
    3397 this->interval.start = (this->interval.end = start) + 1;
    +
    3398 return false;
    +
    3399 }
    +
    3400
    +
    3401 virtual void invalidate()
    +
    3402 {
    +
    3403 path.start = 1;
    +
    3404 path.end = 0;
    +
    3405 query.start = 1;
    +
    3406 query.end = 0;
    +
    3407 bookmark.start = 1;
    +
    3408 bookmark.end = 0;
    + +
    3410 }
    +
    3411
    +
    3412 public:
    + + +
    3415 stdex::interval<size_t> bookmark;
    +
    3416
    +
    3417 protected:
    +
    3418 std::shared_ptr<basic_parser<T>> m_path_char;
    +
    3419 std::shared_ptr<basic_parser<T>> m_query_start;
    +
    3420 std::shared_ptr<basic_parser<T>> m_bookmark_start;
    +
    3421 };
    -
    3419
    - - -
    3422#ifdef _UNICODE
    -
    3423 using turl_path = wurl_path;
    -
    3424#else
    -
    3425 using turl_path = url_path;
    -
    3426#endif
    - -
    3428
    -
    3432 template <class T>
    -
    -
    3433 class basic_url : public basic_parser<T>
    -
    3434 {
    -
    3435 public:
    -
    3436 basic_url(
    -
    3437 _In_ const std::shared_ptr<basic_parser<T>>& _http_scheme,
    -
    3438 _In_ const std::shared_ptr<basic_parser<T>>& _ftp_scheme,
    -
    3439 _In_ const std::shared_ptr<basic_parser<T>>& _mailto_scheme,
    -
    3440 _In_ const std::shared_ptr<basic_parser<T>>& _file_scheme,
    -
    3441 _In_ const std::shared_ptr<basic_parser<T>>& colon,
    -
    3442 _In_ const std::shared_ptr<basic_parser<T>>& slash,
    -
    3443 _In_ const std::shared_ptr<basic_parser<T>>& _username,
    -
    3444 _In_ const std::shared_ptr<basic_parser<T>>& _password,
    -
    3445 _In_ const std::shared_ptr<basic_parser<T>>& at,
    -
    3446 _In_ const std::shared_ptr<basic_parser<T>>& ip_lbracket,
    -
    3447 _In_ const std::shared_ptr<basic_parser<T>>& ip_rbracket,
    -
    3448 _In_ const std::shared_ptr<basic_parser<T>>& _ipv4_host,
    -
    3449 _In_ const std::shared_ptr<basic_parser<T>>& _ipv6_host,
    -
    3450 _In_ const std::shared_ptr<basic_parser<T>>& _dns_host,
    -
    3451 _In_ const std::shared_ptr<basic_parser<T>>& _port,
    -
    3452 _In_ const std::shared_ptr<basic_parser<T>>& _path,
    -
    3453 _In_ const std::locale& locale = std::locale()) :
    -
    3454 basic_parser<T>(locale),
    -
    3455 http_scheme(_http_scheme),
    -
    3456 ftp_scheme(_ftp_scheme),
    -
    3457 mailto_scheme(_mailto_scheme),
    -
    3458 file_scheme(_file_scheme),
    -
    3459 m_colon(colon),
    -
    3460 m_slash(slash),
    -
    3461 username(_username),
    -
    3462 password(_password),
    -
    3463 m_at(at),
    -
    3464 m_ip_lbracket(ip_lbracket),
    -
    3465 m_ip_rbracket(ip_rbracket),
    -
    3466 ipv4_host(_ipv4_host),
    -
    3467 ipv6_host(_ipv6_host),
    -
    3468 dns_host(_dns_host),
    -
    3469 port(_port),
    -
    3470 path(_path)
    -
    3471 {}
    -
    3472
    -
    3473 virtual bool match(
    -
    3474 _In_reads_or_z_(end) const T* text,
    -
    3475 _In_ size_t start = 0,
    -
    3476 _In_ size_t end = (size_t)-1,
    -
    3477 _In_ int flags = match_default)
    -
    3478 {
    -
    3479 assert(text || start >= end);
    -
    3480
    -
    3481 interval.end = start;
    -
    3482
    -
    3483 if (http_scheme->match(text, interval.end, end, flags) &&
    -
    3484 m_colon->match(text, http_scheme->interval.end, end, flags) &&
    -
    3485 m_slash->match(text, m_colon->interval.end, end, flags) &&
    -
    3486 m_slash->match(text, m_slash->interval.end, end, flags))
    -
    3487 {
    -
    3488 // http://
    -
    3489 interval.end = m_slash->interval.end;
    -
    3490 ftp_scheme->invalidate();
    -
    3491 mailto_scheme->invalidate();
    -
    3492 file_scheme->invalidate();
    -
    3493 }
    -
    3494 else if (ftp_scheme->match(text, interval.end, end, flags) &&
    -
    3495 m_colon->match(text, ftp_scheme->interval.end, end, flags) &&
    -
    3496 m_slash->match(text, m_colon->interval.end, end, flags) &&
    -
    3497 m_slash->match(text, m_slash->interval.end, end, flags))
    -
    3498 {
    -
    3499 // ftp://
    -
    3500 interval.end = m_slash->interval.end;
    -
    3501 http_scheme->invalidate();
    -
    3502 mailto_scheme->invalidate();
    -
    3503 file_scheme->invalidate();
    -
    3504 }
    -
    3505 else if (mailto_scheme->match(text, interval.end, end, flags) &&
    -
    3506 m_colon->match(text, mailto_scheme->interval.end, end, flags))
    -
    3507 {
    -
    3508 // mailto:
    -
    3509 interval.end = m_colon->interval.end;
    -
    3510 http_scheme->invalidate();
    -
    3511 ftp_scheme->invalidate();
    -
    3512 file_scheme->invalidate();
    -
    3513 }
    -
    3514 else if (file_scheme->match(text, interval.end, end, flags) &&
    -
    3515 m_colon->match(text, file_scheme->interval.end, end, flags) &&
    -
    3516 m_slash->match(text, m_colon->interval.end, end, flags) &&
    -
    3517 m_slash->match(text, m_slash->interval.end, end, flags))
    -
    3518 {
    -
    3519 // file://
    -
    3520 interval.end = m_slash->interval.end;
    -
    3521 http_scheme->invalidate();
    -
    3522 ftp_scheme->invalidate();
    -
    3523 mailto_scheme->invalidate();
    -
    3524 }
    -
    3525 else {
    -
    3526 // Default to http:
    -
    3527 http_scheme->invalidate();
    -
    3528 ftp_scheme->invalidate();
    -
    3529 mailto_scheme->invalidate();
    -
    3530 file_scheme->invalidate();
    -
    3531 }
    -
    3532
    -
    3533 if (ftp_scheme->interval) {
    -
    3534 if (username->match(text, interval.end, end, flags)) {
    -
    3535 if (m_colon->match(text, username->interval.end, end, flags) &&
    -
    3536 password->match(text, m_colon->interval.end, end, flags) &&
    -
    3537 m_at->match(text, password->interval.end, end, flags))
    -
    3538 {
    -
    3539 // Username and password
    -
    3540 interval.end = m_at->interval.end;
    -
    3541 }
    -
    3542 else if (m_at->match(text, interval.end, end, flags)) {
    -
    3543 // Username only
    -
    3544 interval.end = m_at->interval.end;
    -
    3545 password->invalidate();
    -
    3546 }
    -
    3547 else {
    -
    3548 username->invalidate();
    -
    3549 password->invalidate();
    -
    3550 }
    -
    3551 }
    -
    3552 else {
    -
    3553 username->invalidate();
    -
    3554 password->invalidate();
    -
    3555 }
    -
    3556
    -
    3557 if (ipv4_host->match(text, interval.end, end, flags)) {
    -
    3558 // Host is IPv4
    -
    3559 interval.end = ipv4_host->interval.end;
    -
    3560 ipv6_host->invalidate();
    -
    3561 dns_host->invalidate();
    -
    3562 }
    -
    3563 else if (
    -
    3564 m_ip_lbracket->match(text, interval.end, end, flags) &&
    -
    3565 ipv6_host->match(text, m_ip_lbracket->interval.end, end, flags) &&
    -
    3566 m_ip_rbracket->match(text, ipv6_host->interval.end, end, flags))
    -
    3567 {
    -
    3568 // Host is IPv6
    -
    3569 interval.end = m_ip_rbracket->interval.end;
    -
    3570 ipv4_host->invalidate();
    -
    3571 dns_host->invalidate();
    -
    3572 }
    -
    3573 else if (dns_host->match(text, interval.end, end, flags)) {
    -
    3574 // Host is hostname
    -
    3575 interval.end = dns_host->interval.end;
    -
    3576 ipv4_host->invalidate();
    -
    3577 ipv6_host->invalidate();
    -
    3578 }
    -
    3579 else {
    -
    3580 invalidate();
    -
    3581 return false;
    -
    3582 }
    -
    3583
    -
    3584 if (m_colon->match(text, interval.end, end, flags) &&
    -
    3585 port->match(text, m_colon->interval.end, end, flags))
    -
    3586 {
    -
    3587 // Port
    -
    3588 interval.end = port->interval.end;
    -
    3589 }
    -
    3590 else
    -
    3591 port->invalidate();
    -
    3592
    -
    3593 if (path->match(text, interval.end, end, flags)) {
    -
    3594 // Path
    -
    3595 interval.end = path->interval.end;
    -
    3596 }
    -
    3597
    -
    3598 interval.start = start;
    -
    3599 return true;
    -
    3600 }
    -
    3601
    -
    3602 if (mailto_scheme->interval) {
    -
    3603 if (username->match(text, interval.end, end, flags) &&
    -
    3604 m_at->match(text, username->interval.end, end, flags))
    -
    3605 {
    -
    3606 // Username
    -
    3607 interval.end = m_at->interval.end;
    -
    3608 }
    -
    3609 else {
    -
    3610 invalidate();
    -
    3611 return false;
    -
    3612 }
    -
    3613
    -
    3614 if (m_ip_lbracket->match(text, interval.end, end, flags) &&
    -
    3615 ipv4_host->match(text, m_ip_lbracket->interval.end, end, flags) &&
    -
    3616 m_ip_rbracket->match(text, ipv4_host->interval.end, end, flags))
    -
    3617 {
    -
    3618 // Host is IPv4
    -
    3619 interval.end = m_ip_rbracket->interval.end;
    -
    3620 ipv6_host->invalidate();
    -
    3621 dns_host->invalidate();
    -
    3622 }
    -
    3623 else if (
    -
    3624 m_ip_lbracket->match(text, interval.end, end, flags) &&
    -
    3625 ipv6_host->match(text, m_ip_lbracket->interval.end, end, flags) &&
    -
    3626 m_ip_rbracket->match(text, ipv6_host->interval.end, end, flags))
    -
    3627 {
    -
    3628 // Host is IPv6
    -
    3629 interval.end = m_ip_rbracket->interval.end;
    -
    3630 ipv4_host->invalidate();
    -
    3631 dns_host->invalidate();
    -
    3632 }
    -
    3633 else if (dns_host->match(text, interval.end, end, flags)) {
    -
    3634 // Host is hostname
    -
    3635 interval.end = dns_host->interval.end;
    -
    3636 ipv4_host->invalidate();
    -
    3637 ipv6_host->invalidate();
    -
    3638 }
    -
    3639 else {
    -
    3640 invalidate();
    -
    3641 return false;
    -
    3642 }
    -
    3643
    -
    3644 password->invalidate();
    -
    3645 port->invalidate();
    -
    3646 path->invalidate();
    -
    3647 interval.start = start;
    -
    3648 return true;
    -
    3649 }
    -
    3650
    -
    3651 if (file_scheme->interval) {
    -
    3652 if (path->match(text, interval.end, end, flags)) {
    -
    3653 // Path
    -
    3654 interval.end = path->interval.end;
    -
    3655 }
    -
    3656
    -
    3657 username->invalidate();
    -
    3658 password->invalidate();
    -
    3659 ipv4_host->invalidate();
    -
    3660 ipv6_host->invalidate();
    -
    3661 dns_host->invalidate();
    -
    3662 port->invalidate();
    -
    3663 interval.start = start;
    -
    3664 return true;
    -
    3665 }
    -
    3666
    -
    3667 // "http://" found or defaulted to
    -
    3668
    -
    3669 // If "http://" explicit, test for username&password.
    -
    3670 if (http_scheme->interval &&
    -
    3671 username->match(text, interval.end, end, flags))
    -
    3672 {
    -
    3673 if (m_colon->match(text, username->interval.end, end, flags) &&
    -
    3674 password->match(text, m_colon->interval.end, end, flags) &&
    -
    3675 m_at->match(text, password->interval.end, end, flags))
    -
    3676 {
    -
    3677 // Username and password
    -
    3678 interval.end = m_at->interval.end;
    -
    3679 }
    -
    3680 else if (m_at->match(text, username->interval.end, end, flags)) {
    -
    3681 // Username only
    -
    3682 interval.end = m_at->interval.end;
    -
    3683 password->invalidate();
    -
    3684 }
    -
    3685 else {
    -
    3686 username->invalidate();
    -
    3687 password->invalidate();
    -
    3688 }
    -
    3689 }
    -
    3690 else {
    -
    3691 username->invalidate();
    -
    3692 password->invalidate();
    -
    3693 }
    -
    3694
    -
    3695 if (ipv4_host->match(text, interval.end, end, flags)) {
    -
    3696 // Host is IPv4
    -
    3697 interval.end = ipv4_host->interval.end;
    -
    3698 ipv6_host->invalidate();
    -
    3699 dns_host->invalidate();
    -
    3700 }
    -
    3701 else if (
    -
    3702 m_ip_lbracket->match(text, interval.end, end, flags) &&
    -
    3703 ipv6_host->match(text, m_ip_lbracket->interval.end, end, flags) &&
    -
    3704 m_ip_rbracket->match(text, ipv6_host->interval.end, end, flags))
    -
    3705 {
    -
    3706 // Host is IPv6
    -
    3707 interval.end = m_ip_rbracket->interval.end;
    -
    3708 ipv4_host->invalidate();
    -
    3709 dns_host->invalidate();
    -
    3710 }
    -
    3711 else if (dns_host->match(text, interval.end, end, flags)) {
    -
    3712 // Host is hostname
    -
    3713 interval.end = dns_host->interval.end;
    -
    3714 ipv4_host->invalidate();
    -
    3715 ipv6_host->invalidate();
    -
    3716 }
    -
    3717 else {
    -
    3718 invalidate();
    -
    3719 return false;
    -
    3720 }
    -
    3721
    -
    3722 if (m_colon->match(text, interval.end, end, flags) &&
    -
    3723 port->match(text, m_colon->interval.end, end, flags))
    -
    3724 {
    -
    3725 // Port
    -
    3726 interval.end = port->interval.end;
    -
    3727 }
    -
    3728 else
    -
    3729 port->invalidate();
    -
    3730
    -
    3731 if (path->match(text, interval.end, end, flags)) {
    -
    3732 // Path
    -
    3733 interval.end = path->interval.end;
    -
    3734 }
    -
    3735
    -
    3736 interval.start = start;
    -
    3737 return true;
    -
    3738 }
    -
    3739
    -
    3740 virtual void invalidate()
    -
    3741 {
    -
    3742 http_scheme->invalidate();
    -
    3743 ftp_scheme->invalidate();
    -
    3744 mailto_scheme->invalidate();
    -
    3745 file_scheme->invalidate();
    -
    3746 username->invalidate();
    -
    3747 password->invalidate();
    -
    3748 ipv4_host->invalidate();
    -
    3749 ipv6_host->invalidate();
    -
    3750 dns_host->invalidate();
    -
    3751 port->invalidate();
    -
    3752 path->invalidate();
    - -
    3754 }
    -
    3755
    -
    3756 public:
    -
    3757 std::shared_ptr<basic_parser<T>> http_scheme;
    -
    3758 std::shared_ptr<basic_parser<T>> ftp_scheme;
    -
    3759 std::shared_ptr<basic_parser<T>> mailto_scheme;
    -
    3760 std::shared_ptr<basic_parser<T>> file_scheme;
    -
    3761 std::shared_ptr<basic_parser<T>> username;
    -
    3762 std::shared_ptr<basic_parser<T>> password;
    -
    3763 std::shared_ptr<basic_parser<T>> ipv4_host;
    -
    3764 std::shared_ptr<basic_parser<T>> ipv6_host;
    -
    3765 std::shared_ptr<basic_parser<T>> dns_host;
    -
    3766 std::shared_ptr<basic_parser<T>> port;
    -
    3767 std::shared_ptr<basic_parser<T>> path;
    -
    3768
    -
    3769 protected:
    -
    3770 std::shared_ptr<basic_parser<T>> m_colon;
    -
    3771 std::shared_ptr<basic_parser<T>> m_slash;
    -
    3772 std::shared_ptr<basic_parser<T>> m_at;
    -
    3773 std::shared_ptr<basic_parser<T>> m_ip_lbracket;
    -
    3774 std::shared_ptr<basic_parser<T>> m_ip_rbracket;
    -
    3775 };
    +
    3422
    + + +
    3425#ifdef _UNICODE
    +
    3426 using turl_path = wurl_path;
    +
    3427#else
    +
    3428 using turl_path = url_path;
    +
    3429#endif
    + +
    3431
    +
    3435 template <class T>
    +
    +
    3436 class basic_url : public basic_parser<T>
    +
    3437 {
    +
    3438 public:
    +
    3439 basic_url(
    +
    3440 _In_ const std::shared_ptr<basic_parser<T>>& _http_scheme,
    +
    3441 _In_ const std::shared_ptr<basic_parser<T>>& _ftp_scheme,
    +
    3442 _In_ const std::shared_ptr<basic_parser<T>>& _mailto_scheme,
    +
    3443 _In_ const std::shared_ptr<basic_parser<T>>& _file_scheme,
    +
    3444 _In_ const std::shared_ptr<basic_parser<T>>& colon,
    +
    3445 _In_ const std::shared_ptr<basic_parser<T>>& slash,
    +
    3446 _In_ const std::shared_ptr<basic_parser<T>>& _username,
    +
    3447 _In_ const std::shared_ptr<basic_parser<T>>& _password,
    +
    3448 _In_ const std::shared_ptr<basic_parser<T>>& at,
    +
    3449 _In_ const std::shared_ptr<basic_parser<T>>& ip_lbracket,
    +
    3450 _In_ const std::shared_ptr<basic_parser<T>>& ip_rbracket,
    +
    3451 _In_ const std::shared_ptr<basic_parser<T>>& _ipv4_host,
    +
    3452 _In_ const std::shared_ptr<basic_parser<T>>& _ipv6_host,
    +
    3453 _In_ const std::shared_ptr<basic_parser<T>>& _dns_host,
    +
    3454 _In_ const std::shared_ptr<basic_parser<T>>& _port,
    +
    3455 _In_ const std::shared_ptr<basic_parser<T>>& _path,
    +
    3456 _In_ const std::locale& locale = std::locale()) :
    +
    3457 basic_parser<T>(locale),
    +
    3458 http_scheme(_http_scheme),
    +
    3459 ftp_scheme(_ftp_scheme),
    +
    3460 mailto_scheme(_mailto_scheme),
    +
    3461 file_scheme(_file_scheme),
    +
    3462 m_colon(colon),
    +
    3463 m_slash(slash),
    +
    3464 username(_username),
    +
    3465 password(_password),
    +
    3466 m_at(at),
    +
    3467 m_ip_lbracket(ip_lbracket),
    +
    3468 m_ip_rbracket(ip_rbracket),
    +
    3469 ipv4_host(_ipv4_host),
    +
    3470 ipv6_host(_ipv6_host),
    +
    3471 dns_host(_dns_host),
    +
    3472 port(_port),
    +
    3473 path(_path)
    +
    3474 {}
    +
    3475
    +
    3476 virtual bool match(
    +
    3477 _In_reads_or_z_(end) const T* text,
    +
    3478 _In_ size_t start = 0,
    +
    3479 _In_ size_t end = (size_t)-1,
    +
    3480 _In_ int flags = match_default)
    +
    3481 {
    +
    3482 assert(text || start >= end);
    +
    3483
    +
    3484 this->interval.end = start;
    +
    3485
    +
    3486 if (http_scheme->match(text, this->interval.end, end, flags) &&
    +
    3487 m_colon->match(text, http_scheme->interval.end, end, flags) &&
    +
    3488 m_slash->match(text, m_colon->interval.end, end, flags) &&
    +
    3489 m_slash->match(text, m_slash->interval.end, end, flags))
    +
    3490 {
    +
    3491 // http://
    +
    3492 this->interval.end = m_slash->interval.end;
    +
    3493 ftp_scheme->invalidate();
    +
    3494 mailto_scheme->invalidate();
    +
    3495 file_scheme->invalidate();
    +
    3496 }
    +
    3497 else if (ftp_scheme->match(text, this->interval.end, end, flags) &&
    +
    3498 m_colon->match(text, ftp_scheme->interval.end, end, flags) &&
    +
    3499 m_slash->match(text, m_colon->interval.end, end, flags) &&
    +
    3500 m_slash->match(text, m_slash->interval.end, end, flags))
    +
    3501 {
    +
    3502 // ftp://
    +
    3503 this->interval.end = m_slash->interval.end;
    +
    3504 http_scheme->invalidate();
    +
    3505 mailto_scheme->invalidate();
    +
    3506 file_scheme->invalidate();
    +
    3507 }
    +
    3508 else if (mailto_scheme->match(text, this->interval.end, end, flags) &&
    +
    3509 m_colon->match(text, mailto_scheme->interval.end, end, flags))
    +
    3510 {
    +
    3511 // mailto:
    +
    3512 this->interval.end = m_colon->interval.end;
    +
    3513 http_scheme->invalidate();
    +
    3514 ftp_scheme->invalidate();
    +
    3515 file_scheme->invalidate();
    +
    3516 }
    +
    3517 else if (file_scheme->match(text, this->interval.end, end, flags) &&
    +
    3518 m_colon->match(text, file_scheme->interval.end, end, flags) &&
    +
    3519 m_slash->match(text, m_colon->interval.end, end, flags) &&
    +
    3520 m_slash->match(text, m_slash->interval.end, end, flags))
    +
    3521 {
    +
    3522 // file://
    +
    3523 this->interval.end = m_slash->interval.end;
    +
    3524 http_scheme->invalidate();
    +
    3525 ftp_scheme->invalidate();
    +
    3526 mailto_scheme->invalidate();
    +
    3527 }
    +
    3528 else {
    +
    3529 // Default to http:
    +
    3530 http_scheme->invalidate();
    +
    3531 ftp_scheme->invalidate();
    +
    3532 mailto_scheme->invalidate();
    +
    3533 file_scheme->invalidate();
    +
    3534 }
    +
    3535
    +
    3536 if (ftp_scheme->interval) {
    +
    3537 if (username->match(text, this->interval.end, end, flags)) {
    +
    3538 if (m_colon->match(text, username->interval.end, end, flags) &&
    +
    3539 password->match(text, m_colon->interval.end, end, flags) &&
    +
    3540 m_at->match(text, password->interval.end, end, flags))
    +
    3541 {
    +
    3542 // Username and password
    +
    3543 this->interval.end = m_at->interval.end;
    +
    3544 }
    +
    3545 else if (m_at->match(text, this->interval.end, end, flags)) {
    +
    3546 // Username only
    +
    3547 this->interval.end = m_at->interval.end;
    +
    3548 password->invalidate();
    +
    3549 }
    +
    3550 else {
    +
    3551 username->invalidate();
    +
    3552 password->invalidate();
    +
    3553 }
    +
    3554 }
    +
    3555 else {
    +
    3556 username->invalidate();
    +
    3557 password->invalidate();
    +
    3558 }
    +
    3559
    +
    3560 if (ipv4_host->match(text, this->interval.end, end, flags)) {
    +
    3561 // Host is IPv4
    +
    3562 this->interval.end = ipv4_host->interval.end;
    +
    3563 ipv6_host->invalidate();
    +
    3564 dns_host->invalidate();
    +
    3565 }
    +
    3566 else if (
    +
    3567 m_ip_lbracket->match(text, this->interval.end, end, flags) &&
    +
    3568 ipv6_host->match(text, m_ip_lbracket->interval.end, end, flags) &&
    +
    3569 m_ip_rbracket->match(text, ipv6_host->interval.end, end, flags))
    +
    3570 {
    +
    3571 // Host is IPv6
    +
    3572 this->interval.end = m_ip_rbracket->interval.end;
    +
    3573 ipv4_host->invalidate();
    +
    3574 dns_host->invalidate();
    +
    3575 }
    +
    3576 else if (dns_host->match(text, this->interval.end, end, flags)) {
    +
    3577 // Host is hostname
    +
    3578 this->interval.end = dns_host->interval.end;
    +
    3579 ipv4_host->invalidate();
    +
    3580 ipv6_host->invalidate();
    +
    3581 }
    +
    3582 else {
    +
    3583 invalidate();
    +
    3584 return false;
    +
    3585 }
    +
    3586
    +
    3587 if (m_colon->match(text, this->interval.end, end, flags) &&
    +
    3588 port->match(text, m_colon->interval.end, end, flags))
    +
    3589 {
    +
    3590 // Port
    +
    3591 this->interval.end = port->interval.end;
    +
    3592 }
    +
    3593 else
    +
    3594 port->invalidate();
    +
    3595
    +
    3596 if (path->match(text, this->interval.end, end, flags)) {
    +
    3597 // Path
    +
    3598 this->interval.end = path->interval.end;
    +
    3599 }
    +
    3600
    +
    3601 this->interval.start = start;
    +
    3602 return true;
    +
    3603 }
    +
    3604
    +
    3605 if (mailto_scheme->interval) {
    +
    3606 if (username->match(text, this->interval.end, end, flags) &&
    +
    3607 m_at->match(text, username->interval.end, end, flags))
    +
    3608 {
    +
    3609 // Username
    +
    3610 this->interval.end = m_at->interval.end;
    +
    3611 }
    +
    3612 else {
    +
    3613 invalidate();
    +
    3614 return false;
    +
    3615 }
    +
    3616
    +
    3617 if (m_ip_lbracket->match(text, this->interval.end, end, flags) &&
    +
    3618 ipv4_host->match(text, m_ip_lbracket->interval.end, end, flags) &&
    +
    3619 m_ip_rbracket->match(text, ipv4_host->interval.end, end, flags))
    +
    3620 {
    +
    3621 // Host is IPv4
    +
    3622 this->interval.end = m_ip_rbracket->interval.end;
    +
    3623 ipv6_host->invalidate();
    +
    3624 dns_host->invalidate();
    +
    3625 }
    +
    3626 else if (
    +
    3627 m_ip_lbracket->match(text, this->interval.end, end, flags) &&
    +
    3628 ipv6_host->match(text, m_ip_lbracket->interval.end, end, flags) &&
    +
    3629 m_ip_rbracket->match(text, ipv6_host->interval.end, end, flags))
    +
    3630 {
    +
    3631 // Host is IPv6
    +
    3632 this->interval.end = m_ip_rbracket->interval.end;
    +
    3633 ipv4_host->invalidate();
    +
    3634 dns_host->invalidate();
    +
    3635 }
    +
    3636 else if (dns_host->match(text, this->interval.end, end, flags)) {
    +
    3637 // Host is hostname
    +
    3638 this->interval.end = dns_host->interval.end;
    +
    3639 ipv4_host->invalidate();
    +
    3640 ipv6_host->invalidate();
    +
    3641 }
    +
    3642 else {
    +
    3643 invalidate();
    +
    3644 return false;
    +
    3645 }
    +
    3646
    +
    3647 password->invalidate();
    +
    3648 port->invalidate();
    +
    3649 path->invalidate();
    +
    3650 this->interval.start = start;
    +
    3651 return true;
    +
    3652 }
    +
    3653
    +
    3654 if (file_scheme->interval) {
    +
    3655 if (path->match(text, this->interval.end, end, flags)) {
    +
    3656 // Path
    +
    3657 this->interval.end = path->interval.end;
    +
    3658 }
    +
    3659
    +
    3660 username->invalidate();
    +
    3661 password->invalidate();
    +
    3662 ipv4_host->invalidate();
    +
    3663 ipv6_host->invalidate();
    +
    3664 dns_host->invalidate();
    +
    3665 port->invalidate();
    +
    3666 this->interval.start = start;
    +
    3667 return true;
    +
    3668 }
    +
    3669
    +
    3670 // "http://" found or defaulted to
    +
    3671
    +
    3672 // If "http://" explicit, test for username&password.
    +
    3673 if (http_scheme->interval &&
    +
    3674 username->match(text, this->interval.end, end, flags))
    +
    3675 {
    +
    3676 if (m_colon->match(text, username->interval.end, end, flags) &&
    +
    3677 password->match(text, m_colon->interval.end, end, flags) &&
    +
    3678 m_at->match(text, password->interval.end, end, flags))
    +
    3679 {
    +
    3680 // Username and password
    +
    3681 this->interval.end = m_at->interval.end;
    +
    3682 }
    +
    3683 else if (m_at->match(text, username->interval.end, end, flags)) {
    +
    3684 // Username only
    +
    3685 this->interval.end = m_at->interval.end;
    +
    3686 password->invalidate();
    +
    3687 }
    +
    3688 else {
    +
    3689 username->invalidate();
    +
    3690 password->invalidate();
    +
    3691 }
    +
    3692 }
    +
    3693 else {
    +
    3694 username->invalidate();
    +
    3695 password->invalidate();
    +
    3696 }
    +
    3697
    +
    3698 if (ipv4_host->match(text, this->interval.end, end, flags)) {
    +
    3699 // Host is IPv4
    +
    3700 this->interval.end = ipv4_host->interval.end;
    +
    3701 ipv6_host->invalidate();
    +
    3702 dns_host->invalidate();
    +
    3703 }
    +
    3704 else if (
    +
    3705 m_ip_lbracket->match(text, this->interval.end, end, flags) &&
    +
    3706 ipv6_host->match(text, m_ip_lbracket->interval.end, end, flags) &&
    +
    3707 m_ip_rbracket->match(text, ipv6_host->interval.end, end, flags))
    +
    3708 {
    +
    3709 // Host is IPv6
    +
    3710 this->interval.end = m_ip_rbracket->interval.end;
    +
    3711 ipv4_host->invalidate();
    +
    3712 dns_host->invalidate();
    +
    3713 }
    +
    3714 else if (dns_host->match(text, this->interval.end, end, flags)) {
    +
    3715 // Host is hostname
    +
    3716 this->interval.end = dns_host->interval.end;
    +
    3717 ipv4_host->invalidate();
    +
    3718 ipv6_host->invalidate();
    +
    3719 }
    +
    3720 else {
    +
    3721 invalidate();
    +
    3722 return false;
    +
    3723 }
    +
    3724
    +
    3725 if (m_colon->match(text, this->interval.end, end, flags) &&
    +
    3726 port->match(text, m_colon->interval.end, end, flags))
    +
    3727 {
    +
    3728 // Port
    +
    3729 this->interval.end = port->interval.end;
    +
    3730 }
    +
    3731 else
    +
    3732 port->invalidate();
    +
    3733
    +
    3734 if (path->match(text, this->interval.end, end, flags)) {
    +
    3735 // Path
    +
    3736 this->interval.end = path->interval.end;
    +
    3737 }
    +
    3738
    +
    3739 this->interval.start = start;
    +
    3740 return true;
    +
    3741 }
    +
    3742
    +
    3743 virtual void invalidate()
    +
    3744 {
    +
    3745 http_scheme->invalidate();
    +
    3746 ftp_scheme->invalidate();
    +
    3747 mailto_scheme->invalidate();
    +
    3748 file_scheme->invalidate();
    +
    3749 username->invalidate();
    +
    3750 password->invalidate();
    +
    3751 ipv4_host->invalidate();
    +
    3752 ipv6_host->invalidate();
    +
    3753 dns_host->invalidate();
    +
    3754 port->invalidate();
    +
    3755 path->invalidate();
    + +
    3757 }
    +
    3758
    +
    3759 public:
    +
    3760 std::shared_ptr<basic_parser<T>> http_scheme;
    +
    3761 std::shared_ptr<basic_parser<T>> ftp_scheme;
    +
    3762 std::shared_ptr<basic_parser<T>> mailto_scheme;
    +
    3763 std::shared_ptr<basic_parser<T>> file_scheme;
    +
    3764 std::shared_ptr<basic_parser<T>> username;
    +
    3765 std::shared_ptr<basic_parser<T>> password;
    +
    3766 std::shared_ptr<basic_parser<T>> ipv4_host;
    +
    3767 std::shared_ptr<basic_parser<T>> ipv6_host;
    +
    3768 std::shared_ptr<basic_parser<T>> dns_host;
    +
    3769 std::shared_ptr<basic_parser<T>> port;
    +
    3770 std::shared_ptr<basic_parser<T>> path;
    +
    3771
    +
    3772 protected:
    +
    3773 std::shared_ptr<basic_parser<T>> m_colon;
    +
    3774 std::shared_ptr<basic_parser<T>> m_slash;
    +
    3775 std::shared_ptr<basic_parser<T>> m_at;
    +
    3776 std::shared_ptr<basic_parser<T>> m_ip_lbracket;
    +
    3777 std::shared_ptr<basic_parser<T>> m_ip_rbracket;
    +
    3778 };
    -
    3776
    -
    3777 using url = basic_url<char>;
    -
    3778 using wurl = basic_url<wchar_t>;
    -
    3779#ifdef _UNICODE
    -
    3780 using turl = wurl;
    -
    3781#else
    -
    3782 using turl = url;
    -
    3783#endif
    -
    3784 using sgml_url = basic_url<char>;
    -
    3785
    -
    3789 template <class T>
    -
    - -
    3791 {
    -
    3792 public:
    - -
    3794 _In_ const std::shared_ptr<basic_parser<T>>& _username,
    -
    3795 _In_ const std::shared_ptr<basic_parser<T>>& at,
    -
    3796 _In_ const std::shared_ptr<basic_parser<T>>& ip_lbracket,
    -
    3797 _In_ const std::shared_ptr<basic_parser<T>>& ip_rbracket,
    -
    3798 _In_ const std::shared_ptr<basic_parser<T>>& _ipv4_host,
    -
    3799 _In_ const std::shared_ptr<basic_parser<T>>& _ipv6_host,
    -
    3800 _In_ const std::shared_ptr<basic_parser<T>>& _dns_host,
    -
    3801 _In_ const std::locale& locale = std::locale()) :
    -
    3802 basic_parser<T>(locale),
    -
    3803 username(_username),
    -
    3804 m_at(at),
    -
    3805 m_ip_lbracket(ip_lbracket),
    -
    3806 m_ip_rbracket(ip_rbracket),
    -
    3807 ipv4_host(_ipv4_host),
    -
    3808 ipv6_host(_ipv6_host),
    -
    3809 dns_host(_dns_host)
    -
    3810 {}
    -
    3811
    -
    3812 virtual bool match(
    -
    3813 _In_reads_or_z_(end) const T* text,
    -
    3814 _In_ size_t start = 0,
    -
    3815 _In_ size_t end = (size_t)-1,
    -
    3816 _In_ int flags = match_default)
    -
    3817 {
    -
    3818 assert(text || start >= end);
    -
    3819
    -
    3820 if (username->match(text, start, end, flags) &&
    -
    3821 m_at->match(text, username->interval.end, end, flags))
    -
    3822 {
    -
    3823 // Username@
    -
    3824 if (m_ip_lbracket->match(text, m_at->interval.end, end, flags) &&
    -
    3825 ipv4_host->match(text, m_ip_lbracket->interval.end, end, flags) &&
    -
    3826 m_ip_rbracket->match(text, ipv4_host->interval.end, end, flags))
    -
    3827 {
    -
    3828 // Host is IPv4
    -
    3829 interval.end = m_ip_rbracket->interval.end;
    -
    3830 ipv6_host->invalidate();
    -
    3831 dns_host->invalidate();
    -
    3832 }
    -
    3833 else if (
    -
    3834 m_ip_lbracket->match(text, m_at->interval.end, end, flags) &&
    -
    3835 ipv6_host->match(text, m_ip_lbracket->interval.end, end, flags) &&
    -
    3836 m_ip_rbracket->match(text, ipv6_host->interval.end, end, flags))
    -
    3837 {
    -
    3838 // Host is IPv6
    -
    3839 interval.end = m_ip_rbracket->interval.end;
    -
    3840 ipv4_host->invalidate();
    -
    3841 dns_host->invalidate();
    -
    3842 }
    -
    3843 else if (dns_host->match(text, m_at->interval.end, end, flags)) {
    -
    3844 // Host is hostname
    -
    3845 interval.end = dns_host->interval.end;
    -
    3846 ipv4_host->invalidate();
    -
    3847 ipv6_host->invalidate();
    -
    3848 }
    -
    3849 else
    -
    3850 goto error;
    -
    3851 interval.start = start;
    -
    3852 return true;
    -
    3853 }
    -
    3854
    -
    3855 error:
    -
    3856 username->invalidate();
    -
    3857 ipv4_host->invalidate();
    -
    3858 ipv6_host->invalidate();
    -
    3859 dns_host->invalidate();
    -
    3860 interval.start = (interval.end = start) + 1;
    -
    3861 return false;
    -
    3862 }
    -
    3863
    -
    3864 virtual void invalidate()
    -
    3865 {
    -
    3866 username->invalidate();
    -
    3867 ipv4_host->invalidate();
    -
    3868 ipv6_host->invalidate();
    -
    3869 dns_host->invalidate();
    - -
    3871 }
    -
    3872
    -
    3873 public:
    -
    3874 std::shared_ptr<basic_parser<T>> username;
    -
    3875 std::shared_ptr<basic_parser<T>> ipv4_host;
    -
    3876 std::shared_ptr<basic_parser<T>> ipv6_host;
    -
    3877 std::shared_ptr<basic_parser<T>> dns_host;
    -
    3878
    -
    3879 protected:
    -
    3880 std::shared_ptr<basic_parser<T>> m_at;
    -
    3881 std::shared_ptr<basic_parser<T>> m_ip_lbracket;
    -
    3882 std::shared_ptr<basic_parser<T>> m_ip_rbracket;
    -
    3883 };
    +
    3779
    +
    3780 using url = basic_url<char>;
    +
    3781 using wurl = basic_url<wchar_t>;
    +
    3782#ifdef _UNICODE
    +
    3783 using turl = wurl;
    +
    3784#else
    +
    3785 using turl = url;
    +
    3786#endif
    +
    3787 using sgml_url = basic_url<char>;
    +
    3788
    +
    3792 template <class T>
    +
    + +
    3794 {
    +
    3795 public:
    + +
    3797 _In_ const std::shared_ptr<basic_parser<T>>& _username,
    +
    3798 _In_ const std::shared_ptr<basic_parser<T>>& at,
    +
    3799 _In_ const std::shared_ptr<basic_parser<T>>& ip_lbracket,
    +
    3800 _In_ const std::shared_ptr<basic_parser<T>>& ip_rbracket,
    +
    3801 _In_ const std::shared_ptr<basic_parser<T>>& _ipv4_host,
    +
    3802 _In_ const std::shared_ptr<basic_parser<T>>& _ipv6_host,
    +
    3803 _In_ const std::shared_ptr<basic_parser<T>>& _dns_host,
    +
    3804 _In_ const std::locale& locale = std::locale()) :
    +
    3805 basic_parser<T>(locale),
    +
    3806 username(_username),
    +
    3807 m_at(at),
    +
    3808 m_ip_lbracket(ip_lbracket),
    +
    3809 m_ip_rbracket(ip_rbracket),
    +
    3810 ipv4_host(_ipv4_host),
    +
    3811 ipv6_host(_ipv6_host),
    +
    3812 dns_host(_dns_host)
    +
    3813 {}
    +
    3814
    +
    3815 virtual bool match(
    +
    3816 _In_reads_or_z_(end) const T* text,
    +
    3817 _In_ size_t start = 0,
    +
    3818 _In_ size_t end = (size_t)-1,
    +
    3819 _In_ int flags = match_default)
    +
    3820 {
    +
    3821 assert(text || start >= end);
    +
    3822
    +
    3823 if (username->match(text, start, end, flags) &&
    +
    3824 m_at->match(text, username->interval.end, end, flags))
    +
    3825 {
    +
    3826 // Username@
    +
    3827 if (m_ip_lbracket->match(text, m_at->interval.end, end, flags) &&
    +
    3828 ipv4_host->match(text, m_ip_lbracket->interval.end, end, flags) &&
    +
    3829 m_ip_rbracket->match(text, ipv4_host->interval.end, end, flags))
    +
    3830 {
    +
    3831 // Host is IPv4
    +
    3832 this->interval.end = m_ip_rbracket->interval.end;
    +
    3833 ipv6_host->invalidate();
    +
    3834 dns_host->invalidate();
    +
    3835 }
    +
    3836 else if (
    +
    3837 m_ip_lbracket->match(text, m_at->interval.end, end, flags) &&
    +
    3838 ipv6_host->match(text, m_ip_lbracket->interval.end, end, flags) &&
    +
    3839 m_ip_rbracket->match(text, ipv6_host->interval.end, end, flags))
    +
    3840 {
    +
    3841 // Host is IPv6
    +
    3842 this->interval.end = m_ip_rbracket->interval.end;
    +
    3843 ipv4_host->invalidate();
    +
    3844 dns_host->invalidate();
    +
    3845 }
    +
    3846 else if (dns_host->match(text, m_at->interval.end, end, flags)) {
    +
    3847 // Host is hostname
    +
    3848 this->interval.end = dns_host->interval.end;
    +
    3849 ipv4_host->invalidate();
    +
    3850 ipv6_host->invalidate();
    +
    3851 }
    +
    3852 else
    +
    3853 goto error;
    +
    3854 this->interval.start = start;
    +
    3855 return true;
    +
    3856 }
    +
    3857
    +
    3858 error:
    +
    3859 username->invalidate();
    +
    3860 ipv4_host->invalidate();
    +
    3861 ipv6_host->invalidate();
    +
    3862 dns_host->invalidate();
    +
    3863 this->interval.start = (this->interval.end = start) + 1;
    +
    3864 return false;
    +
    3865 }
    +
    3866
    +
    3867 virtual void invalidate()
    +
    3868 {
    +
    3869 username->invalidate();
    +
    3870 ipv4_host->invalidate();
    +
    3871 ipv6_host->invalidate();
    +
    3872 dns_host->invalidate();
    + +
    3874 }
    +
    3875
    +
    3876 public:
    +
    3877 std::shared_ptr<basic_parser<T>> username;
    +
    3878 std::shared_ptr<basic_parser<T>> ipv4_host;
    +
    3879 std::shared_ptr<basic_parser<T>> ipv6_host;
    +
    3880 std::shared_ptr<basic_parser<T>> dns_host;
    +
    3881
    +
    3882 protected:
    +
    3883 std::shared_ptr<basic_parser<T>> m_at;
    +
    3884 std::shared_ptr<basic_parser<T>> m_ip_lbracket;
    +
    3885 std::shared_ptr<basic_parser<T>> m_ip_rbracket;
    +
    3886 };
    -
    3884
    - - -
    3887#ifdef _UNICODE
    - -
    3889#else
    - -
    3891#endif
    - -
    3893
    -
    3897 template <class T>
    -
    - -
    3899 {
    -
    3900 public:
    - -
    3902 _In_ const std::shared_ptr<basic_parser<T>>& _emoticon,
    -
    3903 _In_ const std::shared_ptr<basic_parser<T>>& _apex,
    -
    3904 _In_ const std::shared_ptr<basic_parser<T>>& _eyes,
    -
    3905 _In_ const std::shared_ptr<basic_parser<T>>& _nose,
    -
    3906 _In_ const std::shared_ptr<basic_set<T>>& _mouth,
    -
    3907 _In_ const std::locale& locale = std::locale()) :
    -
    3908 basic_parser<T>(locale),
    - -
    3910 apex(_apex),
    -
    3911 eyes(_eyes),
    -
    3912 nose(_nose),
    -
    3913 mouth(_mouth)
    -
    3914 {}
    -
    3915
    -
    3916 virtual bool match(
    -
    3917 _In_reads_or_z_(end) const T* text,
    -
    3918 _In_ size_t start = 0,
    -
    3919 _In_ size_t end = (size_t)-1,
    -
    3920 _In_ int flags = match_default)
    -
    3921 {
    -
    3922 assert(text || start >= end);
    -
    3923
    -
    3924 if (emoticon && emoticon->match(text, start, end, flags)) {
    -
    3925 if (apex) apex->invalidate();
    -
    3926 eyes->invalidate();
    -
    3927 if (nose) nose->invalidate();
    -
    3928 mouth->invalidate();
    -
    3929 interval.start = start;
    - -
    3931 return true;
    -
    3932 }
    -
    3933
    -
    3934 interval.end = start;
    -
    3935
    -
    3936 if (apex && apex->match(text, interval.end, end, flags))
    -
    3937 interval.end = apex->interval.end;
    +
    3887
    + + +
    3890#ifdef _UNICODE
    + +
    3892#else
    + +
    3894#endif
    + +
    3896
    +
    3900 template <class T>
    +
    + +
    3902 {
    +
    3903 public:
    + +
    3905 _In_ const std::shared_ptr<basic_parser<T>>& _emoticon,
    +
    3906 _In_ const std::shared_ptr<basic_parser<T>>& _apex,
    +
    3907 _In_ const std::shared_ptr<basic_parser<T>>& _eyes,
    +
    3908 _In_ const std::shared_ptr<basic_parser<T>>& _nose,
    +
    3909 _In_ const std::shared_ptr<basic_set<T>>& _mouth,
    +
    3910 _In_ const std::locale& locale = std::locale()) :
    +
    3911 basic_parser<T>(locale),
    + +
    3913 apex(_apex),
    +
    3914 eyes(_eyes),
    +
    3915 nose(_nose),
    +
    3916 mouth(_mouth)
    +
    3917 {}
    +
    3918
    +
    3919 virtual bool match(
    +
    3920 _In_reads_or_z_(end) const T* text,
    +
    3921 _In_ size_t start = 0,
    +
    3922 _In_ size_t end = (size_t)-1,
    +
    3923 _In_ int flags = match_default)
    +
    3924 {
    +
    3925 assert(text || start >= end);
    +
    3926
    +
    3927 if (emoticon && emoticon->match(text, start, end, flags)) {
    +
    3928 if (apex) apex->invalidate();
    +
    3929 eyes->invalidate();
    +
    3930 if (nose) nose->invalidate();
    +
    3931 mouth->invalidate();
    +
    3932 this->interval.start = start;
    +
    3933 this->interval.end = emoticon->interval.end;
    +
    3934 return true;
    +
    3935 }
    +
    3936
    +
    3937 this->interval.end = start;
    3938
    -
    3939 if (eyes->match(text, interval.end, end, flags)) {
    -
    3940 if (nose && nose->match(text, eyes->interval.end, end, flags) &&
    -
    3941 mouth->match(text, nose->interval.end, end, flags))
    -
    3942 {
    -
    3943 size_t
    - -
    3945 hit_offset = mouth->hit_offset;
    -
    3946 // Mouth may repeat :-)))))))
    -
    3947 for (interval.end = mouth->interval.end; mouth->match(text, interval.end, end, flags) && mouth->hit_offset == hit_offset; interval.end = mouth->interval.end);
    -
    3948 mouth->interval.start = start_mouth;
    - -
    3950 interval.start = start;
    -
    3951 return true;
    -
    3952 }
    -
    3953 if (mouth->match(text, eyes->interval.end, end, flags)) {
    -
    3954 size_t
    - -
    3956 hit_offset = mouth->hit_offset;
    -
    3957 // Mouth may repeat :-)))))))
    -
    3958 for (interval.end = mouth->interval.end; mouth->match(text, interval.end, end, flags) && mouth->hit_offset == hit_offset; interval.end = mouth->interval.end);
    -
    3959 if (nose) nose->invalidate();
    -
    3960 mouth->interval.start = start_mouth;
    - -
    3962 interval.start = start;
    -
    3963 return true;
    -
    3964 }
    -
    3965 }
    -
    3966
    -
    3967 if (emoticon) emoticon->invalidate();
    -
    3968 if (apex) apex->invalidate();
    -
    3969 eyes->invalidate();
    -
    3970 if (nose) nose->invalidate();
    -
    3971 mouth->invalidate();
    -
    3972 interval.start = (interval.end = start) + 1;
    -
    3973 return false;
    -
    3974 }
    -
    3975
    -
    3976 virtual void invalidate()
    -
    3977 {
    -
    3978 if (emoticon) emoticon->invalidate();
    -
    3979 if (apex) apex->invalidate();
    -
    3980 eyes->invalidate();
    -
    3981 if (nose) nose->invalidate();
    -
    3982 mouth->invalidate();
    - -
    3984 }
    -
    3985
    -
    3986 public:
    -
    3987 std::shared_ptr<basic_parser<T>> emoticon;
    -
    3988 std::shared_ptr<basic_parser<T>> apex;
    -
    3989 std::shared_ptr<basic_parser<T>> eyes;
    -
    3990 std::shared_ptr<basic_parser<T>> nose;
    -
    3991 std::shared_ptr<basic_set<T>> mouth;
    -
    3992 };
    +
    3939 if (apex && apex->match(text, this->interval.end, end, flags))
    +
    3940 this->interval.end = apex->interval.end;
    +
    3941
    +
    3942 if (eyes->match(text, this->interval.end, end, flags)) {
    +
    3943 if (nose && nose->match(text, eyes->interval.end, end, flags) &&
    +
    3944 mouth->match(text, nose->interval.end, end, flags))
    +
    3945 {
    +
    3946 size_t
    + +
    3948 hit_offset = mouth->hit_offset;
    +
    3949 // Mouth may repeat :-)))))))
    +
    3950 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);
    +
    3951 mouth->interval.start = start_mouth;
    +
    3952 mouth->interval.end = this->interval.end;
    +
    3953 this->interval.start = start;
    +
    3954 return true;
    +
    3955 }
    +
    3956 if (mouth->match(text, eyes->interval.end, end, flags)) {
    +
    3957 size_t
    + +
    3959 hit_offset = mouth->hit_offset;
    +
    3960 // Mouth may repeat :-)))))))
    +
    3961 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);
    +
    3962 if (nose) nose->invalidate();
    +
    3963 mouth->interval.start = start_mouth;
    +
    3964 mouth->interval.end = this->interval.end;
    +
    3965 this->interval.start = start;
    +
    3966 return true;
    +
    3967 }
    +
    3968 }
    +
    3969
    +
    3970 if (emoticon) emoticon->invalidate();
    +
    3971 if (apex) apex->invalidate();
    +
    3972 eyes->invalidate();
    +
    3973 if (nose) nose->invalidate();
    +
    3974 mouth->invalidate();
    +
    3975 this->interval.start = (this->interval.end = start) + 1;
    +
    3976 return false;
    +
    3977 }
    +
    3978
    +
    3979 virtual void invalidate()
    +
    3980 {
    +
    3981 if (emoticon) emoticon->invalidate();
    +
    3982 if (apex) apex->invalidate();
    +
    3983 eyes->invalidate();
    +
    3984 if (nose) nose->invalidate();
    +
    3985 mouth->invalidate();
    + +
    3987 }
    +
    3988
    +
    3989 public:
    +
    3990 std::shared_ptr<basic_parser<T>> emoticon;
    +
    3991 std::shared_ptr<basic_parser<T>> apex;
    +
    3992 std::shared_ptr<basic_parser<T>> eyes;
    +
    3993 std::shared_ptr<basic_parser<T>> nose;
    +
    3994 std::shared_ptr<basic_set<T>> mouth;
    +
    3995 };
    -
    3993
    - - -
    3996#ifdef _UNICODE
    -
    3997 using temoticon = wemoticon;
    -
    3998#else
    -
    3999 using temoticon = emoticon;
    -
    4000#endif
    - -
    4002
    -
    4006 enum date_format_t {
    -
    4007 date_format_none = 0,
    -
    4008 date_format_dmy = 0x1,
    -
    4009 date_format_mdy = 0x2,
    -
    4010 date_format_ymd = 0x4,
    -
    4011 date_format_ym = 0x8,
    -
    4012 date_format_my = 0x10,
    -
    4013 date_format_dm = 0x20,
    -
    4014 date_format_md = 0x40,
    -
    4015 };
    -
    4016
    -
    4020 template <class T>
    -
    -
    4021 class basic_date : public basic_parser<T>
    -
    4022 {
    -
    4023 public:
    -
    4024 basic_date(
    -
    4025 _In_ int format_mask,
    -
    4026 _In_ const std::shared_ptr<basic_integer<T>>& _day,
    -
    4027 _In_ const std::shared_ptr<basic_integer<T>>& _month,
    -
    4028 _In_ const std::shared_ptr<basic_integer<T>>& _year,
    -
    4029 _In_ const std::shared_ptr<basic_set<T>>& separator,
    -
    4030 _In_ const std::shared_ptr<basic_parser<T>>& space,
    -
    4031 _In_ const std::locale& locale = std::locale()) :
    -
    4032 basic_parser<T>(locale),
    -
    4033 format(date_format_none),
    -
    4034 m_format_mask(format_mask),
    -
    4035 day(_day),
    -
    4036 month(_month),
    -
    4037 year(_year),
    -
    4038 m_separator(separator),
    -
    4039 m_space(space)
    -
    4040 {}
    -
    4041
    -
    4042 virtual bool match(
    -
    4043 _In_reads_or_z_(end) const T* text,
    -
    4044 _In_ size_t start = 0,
    -
    4045 _In_ size_t end = (size_t)-1,
    -
    4046 _In_ int flags = match_default)
    -
    4047 {
    -
    4048 assert(text || start >= end);
    -
    4049
    -
    4050 const int space_match_flags = flags & ~match_multiline; // Spaces in dates must never be broken in new line.
    -
    4051 if ((m_format_mask & date_format_dmy) == date_format_dmy) {
    -
    4052 if (day->match(text, start, end, flags)) {
    -
    4053 for (interval.end = day->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
    -
    4054 if (m_separator->match(text, interval.end, end, flags)) {
    -
    4055 size_t hit_offset = m_separator->hit_offset;
    -
    4056 for (interval.end = m_separator->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
    -
    4057 if (month->match(text, interval.end, end, flags)) {
    -
    4058 for (interval.end = month->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
    -
    4059 if (m_separator->match(text, interval.end, end, flags) &&
    -
    4060 m_separator->hit_offset == hit_offset) // Both separators must match.
    -
    4061 {
    -
    4062 for (interval.end = m_separator->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
    -
    4063 if (year->match(text, interval.end, end, flags) &&
    -
    4064 is_valid(day->value, month->value))
    -
    4065 {
    -
    4066 interval.start = start;
    -
    4067 interval.end = year->interval.end;
    -
    4068 format = date_format_dmy;
    -
    4069 return true;
    -
    4070 }
    -
    4071 }
    -
    4072 }
    -
    4073 }
    -
    4074 }
    -
    4075 }
    -
    4076
    -
    4077 if ((m_format_mask & date_format_mdy) == date_format_mdy) {
    -
    4078 if (month->match(text, start, end, flags)) {
    -
    4079 for (interval.end = month->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
    -
    4080 if (m_separator->match(text, interval.end, end, flags)) {
    -
    4081 size_t hit_offset = m_separator->hit_offset;
    -
    4082 for (interval.end = m_separator->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
    -
    4083 if (day->match(text, interval.end, end, flags)) {
    -
    4084 for (interval.end = day->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
    -
    4085 if (m_separator->match(text, interval.end, end, flags) &&
    -
    4086 m_separator->hit_offset == hit_offset) // Both separators must match.
    -
    4087 {
    -
    4088 for (interval.end = m_separator->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
    -
    4089 if (year->match(text, interval.end, end, flags) &&
    -
    4090 is_valid(day->value, month->value))
    -
    4091 {
    -
    4092 interval.start = start;
    -
    4093 interval.end = year->interval.end;
    -
    4094 format = date_format_mdy;
    -
    4095 return true;
    -
    4096 }
    -
    4097 }
    -
    4098 }
    -
    4099 }
    -
    4100 }
    -
    4101 }
    -
    4102
    -
    4103 if ((m_format_mask & date_format_ymd) == date_format_ymd) {
    -
    4104 if (year->match(text, start, end, flags)) {
    -
    4105 for (interval.end = year->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
    -
    4106 if (m_separator->match(text, interval.end, end, flags)) {
    -
    4107 size_t hit_offset = m_separator->hit_offset;
    -
    4108 for (interval.end = m_separator->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
    -
    4109 if (month->match(text, interval.end, end, flags)) {
    -
    4110 for (interval.end = month->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
    -
    4111 if (m_separator->match(text, interval.end, end, flags) &&
    -
    4112 m_separator->hit_offset == hit_offset) // Both separators must match.
    -
    4113 {
    -
    4114 for (interval.end = m_separator->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
    -
    4115 if (day->match(text, interval.end, end, flags) &&
    -
    4116 is_valid(day->value, month->value))
    -
    4117 {
    -
    4118 interval.start = start;
    -
    4119 interval.end = day->interval.end;
    -
    4120 format = date_format_ymd;
    -
    4121 return true;
    -
    4122 }
    -
    4123 }
    -
    4124 }
    -
    4125 }
    -
    4126 }
    -
    4127 }
    -
    4128
    -
    4129 if ((m_format_mask & date_format_ym) == date_format_ym) {
    -
    4130 if (year->match(text, start, end, flags)) {
    -
    4131 for (interval.end = year->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
    -
    4132 if (m_separator->match(text, interval.end, end, flags)) {
    -
    4133 for (interval.end = m_separator->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
    -
    4134 if (month->match(text, interval.end, end, flags) &&
    -
    4135 is_valid((size_t)-1, month->value))
    -
    4136 {
    -
    4137 if (day) day->invalidate();
    -
    4138 interval.start = start;
    -
    4139 interval.end = month->interval.end;
    -
    4140 format = date_format_ym;
    -
    4141 return true;
    -
    4142 }
    -
    4143 }
    -
    4144 }
    -
    4145 }
    -
    4146
    -
    4147 if ((m_format_mask & date_format_my) == date_format_my) {
    -
    4148 if (month->match(text, start, end, flags)) {
    -
    4149 for (interval.end = month->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
    -
    4150 if (m_separator->match(text, interval.end, end, flags)) {
    -
    4151 for (interval.end = m_separator->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
    -
    4152 if (year->match(text, interval.end, end, flags) &&
    -
    4153 is_valid((size_t)-1, month->value))
    -
    4154 {
    -
    4155 if (day) day->invalidate();
    -
    4156 interval.start = start;
    -
    4157 interval.end = year->interval.end;
    -
    4158 format = date_format_my;
    -
    4159 return true;
    -
    4160 }
    -
    4161 }
    -
    4162 }
    -
    4163 }
    -
    4164
    -
    4165 if ((m_format_mask & date_format_dm) == date_format_dm) {
    -
    4166 if (day->match(text, start, end, flags)) {
    -
    4167 for (interval.end = day->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
    -
    4168 if (m_separator->match(text, interval.end, end, flags)) {
    -
    4169 size_t hit_offset = m_separator->hit_offset;
    -
    4170 for (interval.end = m_separator->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
    -
    4171 if (month->match(text, interval.end, end, flags) &&
    -
    4172 is_valid(day->value, month->value))
    -
    4173 {
    -
    4174 if (year) year->invalidate();
    -
    4175 interval.start = start;
    -
    4176 for (interval.end = month->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
    -
    4177 if (m_separator->match(text, interval.end, end, flags) &&
    -
    4178 m_separator->hit_offset == hit_offset) // Both separators must match.
    -
    4179 interval.end = m_separator->interval.end;
    -
    4180 else
    -
    4181 interval.end = month->interval.end;
    -
    4182 format = date_format_dm;
    -
    4183 return true;
    -
    4184 }
    -
    4185 }
    -
    4186 }
    -
    4187 }
    -
    4188
    -
    4189 if ((m_format_mask & date_format_md) == date_format_md) {
    -
    4190 if (month->match(text, start, end, flags)) {
    -
    4191 for (interval.end = month->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
    -
    4192 if (m_separator->match(text, interval.end, end, flags)) {
    -
    4193 size_t hit_offset = m_separator->hit_offset;
    -
    4194 for (interval.end = m_separator->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
    -
    4195 if (day->match(text, interval.end, end, flags) &&
    -
    4196 is_valid(day->value, month->value))
    -
    4197 {
    -
    4198 if (year) year->invalidate();
    -
    4199 interval.start = start;
    -
    4200 for (interval.end = day->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
    -
    4201 if (m_separator->match(text, interval.end, end, flags) &&
    -
    4202 m_separator->hit_offset == hit_offset) // Both separators must match.
    -
    4203 interval.end = m_separator->interval.end;
    -
    4204 else
    -
    4205 interval.end = day->interval.end;
    -
    4206 format = date_format_md;
    -
    4207 return true;
    -
    4208 }
    -
    4209 }
    -
    4210 }
    -
    4211 }
    -
    4212
    -
    4213 if (day) day->invalidate();
    -
    4214 if (month) month->invalidate();
    -
    4215 if (year) year->invalidate();
    -
    4216 format = date_format_none;
    -
    4217 interval.start = (interval.end = start) + 1;
    -
    4218 return false;
    -
    4219 }
    -
    4220
    -
    4221 virtual void invalidate()
    -
    4222 {
    -
    4223 if (day) day->invalidate();
    -
    4224 if (month) month->invalidate();
    -
    4225 if (year) year->invalidate();
    -
    4226 format = date_format_none;
    - -
    4228 }
    -
    4229
    -
    4230 protected:
    -
    4231 static inline bool is_valid(size_t day, size_t month)
    -
    4232 {
    -
    4233 if (month == (size_t)-1) {
    -
    4234 // Default to January. This allows validating day only, as January has all 31 days.
    -
    4235 month = 1;
    -
    4236 }
    -
    4237 if (day == (size_t)-1) {
    -
    4238 // Default to 1st day in month. This allows validating month only, as each month has 1st day.
    -
    4239 day = 1;
    -
    4240 }
    -
    4241
    -
    4242 switch (month) {
    -
    4243 case 1:
    -
    4244 case 3:
    -
    4245 case 5:
    -
    4246 case 7:
    -
    4247 case 8:
    -
    4248 case 10:
    -
    4249 case 12:
    -
    4250 return 1 <= day && day <= 31;
    -
    4251 case 2:
    -
    4252 return 1 <= day && day <= 29;
    -
    4253 case 4:
    -
    4254 case 6:
    -
    4255 case 9:
    -
    4256 case 11:
    -
    4257 return 1 <= day && day <= 30;
    -
    4258 default:
    -
    4259 return false;
    -
    4260 }
    -
    4261 }
    -
    4262
    -
    4263 public:
    -
    4264 date_format_t format;
    -
    4265 std::shared_ptr<basic_integer<T>> day;
    -
    4266 std::shared_ptr<basic_integer<T>> month;
    -
    4267 std::shared_ptr<basic_integer<T>> year;
    -
    4268
    -
    4269 protected:
    -
    4270 int m_format_mask;
    -
    4271 std::shared_ptr<basic_set<T>> m_separator;
    -
    4272 std::shared_ptr<basic_parser<T>> m_space;
    -
    4273 };
    +
    3996
    + + +
    3999#ifdef _UNICODE
    +
    4000 using temoticon = wemoticon;
    +
    4001#else
    +
    4002 using temoticon = emoticon;
    +
    4003#endif
    + +
    4005
    +
    4009 enum date_format_t {
    +
    4010 date_format_none = 0,
    +
    4011 date_format_dmy = 0x1,
    +
    4012 date_format_mdy = 0x2,
    +
    4013 date_format_ymd = 0x4,
    +
    4014 date_format_ym = 0x8,
    +
    4015 date_format_my = 0x10,
    +
    4016 date_format_dm = 0x20,
    +
    4017 date_format_md = 0x40,
    +
    4018 };
    +
    4019
    +
    4023 template <class T>
    +
    +
    4024 class basic_date : public basic_parser<T>
    +
    4025 {
    +
    4026 public:
    +
    4027 basic_date(
    +
    4028 _In_ int format_mask,
    +
    4029 _In_ const std::shared_ptr<basic_integer<T>>& _day,
    +
    4030 _In_ const std::shared_ptr<basic_integer<T>>& _month,
    +
    4031 _In_ const std::shared_ptr<basic_integer<T>>& _year,
    +
    4032 _In_ const std::shared_ptr<basic_set<T>>& separator,
    +
    4033 _In_ const std::shared_ptr<basic_parser<T>>& space,
    +
    4034 _In_ const std::locale& locale = std::locale()) :
    +
    4035 basic_parser<T>(locale),
    +
    4036 format(date_format_none),
    +
    4037 m_format_mask(format_mask),
    +
    4038 day(_day),
    +
    4039 month(_month),
    +
    4040 year(_year),
    +
    4041 m_separator(separator),
    +
    4042 m_space(space)
    +
    4043 {}
    +
    4044
    +
    4045 virtual bool match(
    +
    4046 _In_reads_or_z_(end) const T* text,
    +
    4047 _In_ size_t start = 0,
    +
    4048 _In_ size_t end = (size_t)-1,
    +
    4049 _In_ int flags = match_default)
    +
    4050 {
    +
    4051 assert(text || start >= end);
    +
    4052
    +
    4053 const int space_match_flags = flags & ~match_multiline; // Spaces in dates must never be broken in new line.
    +
    4054 if ((m_format_mask & date_format_dmy) == date_format_dmy) {
    +
    4055 if (day->match(text, start, end, flags)) {
    +
    4056 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);
    +
    4057 if (m_separator->match(text, this->interval.end, end, flags)) {
    +
    4058 size_t hit_offset = m_separator->hit_offset;
    +
    4059 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);
    +
    4060 if (month->match(text, this->interval.end, end, flags)) {
    +
    4061 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);
    +
    4062 if (m_separator->match(text, this->interval.end, end, flags) &&
    +
    4063 m_separator->hit_offset == hit_offset) // Both separators must match.
    +
    4064 {
    +
    4065 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);
    +
    4066 if (year->match(text, this->interval.end, end, flags) &&
    +
    4067 is_valid(day->value, month->value))
    +
    4068 {
    +
    4069 this->interval.start = start;
    +
    4070 this->interval.end = year->interval.end;
    +
    4071 format = date_format_dmy;
    +
    4072 return true;
    +
    4073 }
    +
    4074 }
    +
    4075 }
    +
    4076 }
    +
    4077 }
    +
    4078 }
    +
    4079
    +
    4080 if ((m_format_mask & date_format_mdy) == date_format_mdy) {
    +
    4081 if (month->match(text, start, end, flags)) {
    +
    4082 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);
    +
    4083 if (m_separator->match(text, this->interval.end, end, flags)) {
    +
    4084 size_t hit_offset = m_separator->hit_offset;
    +
    4085 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);
    +
    4086 if (day->match(text, this->interval.end, end, flags)) {
    +
    4087 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);
    +
    4088 if (m_separator->match(text, this->interval.end, end, flags) &&
    +
    4089 m_separator->hit_offset == hit_offset) // Both separators must match.
    +
    4090 {
    +
    4091 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);
    +
    4092 if (year->match(text, this->interval.end, end, flags) &&
    +
    4093 is_valid(day->value, month->value))
    +
    4094 {
    +
    4095 this->interval.start = start;
    +
    4096 this->interval.end = year->interval.end;
    +
    4097 format = date_format_mdy;
    +
    4098 return true;
    +
    4099 }
    +
    4100 }
    +
    4101 }
    +
    4102 }
    +
    4103 }
    +
    4104 }
    +
    4105
    +
    4106 if ((m_format_mask & date_format_ymd) == date_format_ymd) {
    +
    4107 if (year->match(text, start, end, flags)) {
    +
    4108 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);
    +
    4109 if (m_separator->match(text, this->interval.end, end, flags)) {
    +
    4110 size_t hit_offset = m_separator->hit_offset;
    +
    4111 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);
    +
    4112 if (month->match(text, this->interval.end, end, flags)) {
    +
    4113 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);
    +
    4114 if (m_separator->match(text, this->interval.end, end, flags) &&
    +
    4115 m_separator->hit_offset == hit_offset) // Both separators must match.
    +
    4116 {
    +
    4117 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);
    +
    4118 if (day->match(text, this->interval.end, end, flags) &&
    +
    4119 is_valid(day->value, month->value))
    +
    4120 {
    +
    4121 this->interval.start = start;
    +
    4122 this->interval.end = day->interval.end;
    +
    4123 format = date_format_ymd;
    +
    4124 return true;
    +
    4125 }
    +
    4126 }
    +
    4127 }
    +
    4128 }
    +
    4129 }
    +
    4130 }
    +
    4131
    +
    4132 if ((m_format_mask & date_format_ym) == date_format_ym) {
    +
    4133 if (year->match(text, start, end, flags)) {
    +
    4134 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);
    +
    4135 if (m_separator->match(text, this->interval.end, end, flags)) {
    +
    4136 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);
    +
    4137 if (month->match(text, this->interval.end, end, flags) &&
    +
    4138 is_valid((size_t)-1, month->value))
    +
    4139 {
    +
    4140 if (day) day->invalidate();
    +
    4141 this->interval.start = start;
    +
    4142 this->interval.end = month->interval.end;
    +
    4143 format = date_format_ym;
    +
    4144 return true;
    +
    4145 }
    +
    4146 }
    +
    4147 }
    +
    4148 }
    +
    4149
    +
    4150 if ((m_format_mask & date_format_my) == date_format_my) {
    +
    4151 if (month->match(text, start, end, flags)) {
    +
    4152 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);
    +
    4153 if (m_separator->match(text, this->interval.end, end, flags)) {
    +
    4154 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);
    +
    4155 if (year->match(text, this->interval.end, end, flags) &&
    +
    4156 is_valid((size_t)-1, month->value))
    +
    4157 {
    +
    4158 if (day) day->invalidate();
    +
    4159 this->interval.start = start;
    +
    4160 this->interval.end = year->interval.end;
    +
    4161 format = date_format_my;
    +
    4162 return true;
    +
    4163 }
    +
    4164 }
    +
    4165 }
    +
    4166 }
    +
    4167
    +
    4168 if ((m_format_mask & date_format_dm) == date_format_dm) {
    +
    4169 if (day->match(text, start, end, flags)) {
    +
    4170 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);
    +
    4171 if (m_separator->match(text, this->interval.end, end, flags)) {
    +
    4172 size_t hit_offset = m_separator->hit_offset;
    +
    4173 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);
    +
    4174 if (month->match(text, this->interval.end, end, flags) &&
    +
    4175 is_valid(day->value, month->value))
    +
    4176 {
    +
    4177 if (year) year->invalidate();
    +
    4178 this->interval.start = start;
    +
    4179 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);
    +
    4180 if (m_separator->match(text, this->interval.end, end, flags) &&
    +
    4181 m_separator->hit_offset == hit_offset) // Both separators must match.
    +
    4182 this->interval.end = m_separator->interval.end;
    +
    4183 else
    +
    4184 this->interval.end = month->interval.end;
    +
    4185 format = date_format_dm;
    +
    4186 return true;
    +
    4187 }
    +
    4188 }
    +
    4189 }
    +
    4190 }
    +
    4191
    +
    4192 if ((m_format_mask & date_format_md) == date_format_md) {
    +
    4193 if (month->match(text, start, end, flags)) {
    +
    4194 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);
    +
    4195 if (m_separator->match(text, this->interval.end, end, flags)) {
    +
    4196 size_t hit_offset = m_separator->hit_offset;
    +
    4197 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);
    +
    4198 if (day->match(text, this->interval.end, end, flags) &&
    +
    4199 is_valid(day->value, month->value))
    +
    4200 {
    +
    4201 if (year) year->invalidate();
    +
    4202 this->interval.start = start;
    +
    4203 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);
    +
    4204 if (m_separator->match(text, this->interval.end, end, flags) &&
    +
    4205 m_separator->hit_offset == hit_offset) // Both separators must match.
    +
    4206 this->interval.end = m_separator->interval.end;
    +
    4207 else
    +
    4208 this->interval.end = day->interval.end;
    +
    4209 format = date_format_md;
    +
    4210 return true;
    +
    4211 }
    +
    4212 }
    +
    4213 }
    +
    4214 }
    +
    4215
    +
    4216 if (day) day->invalidate();
    +
    4217 if (month) month->invalidate();
    +
    4218 if (year) year->invalidate();
    +
    4219 format = date_format_none;
    +
    4220 this->interval.start = (this->interval.end = start) + 1;
    +
    4221 return false;
    +
    4222 }
    +
    4223
    +
    4224 virtual void invalidate()
    +
    4225 {
    +
    4226 if (day) day->invalidate();
    +
    4227 if (month) month->invalidate();
    +
    4228 if (year) year->invalidate();
    +
    4229 format = date_format_none;
    + +
    4231 }
    +
    4232
    +
    4233 protected:
    +
    4234 static inline bool is_valid(size_t day, size_t month)
    +
    4235 {
    +
    4236 if (month == (size_t)-1) {
    +
    4237 // Default to January. This allows validating day only, as January has all 31 days.
    +
    4238 month = 1;
    +
    4239 }
    +
    4240 if (day == (size_t)-1) {
    +
    4241 // Default to 1st day in month. This allows validating month only, as each month has 1st day.
    +
    4242 day = 1;
    +
    4243 }
    +
    4244
    +
    4245 switch (month) {
    +
    4246 case 1:
    +
    4247 case 3:
    +
    4248 case 5:
    +
    4249 case 7:
    +
    4250 case 8:
    +
    4251 case 10:
    +
    4252 case 12:
    +
    4253 return 1 <= day && day <= 31;
    +
    4254 case 2:
    +
    4255 return 1 <= day && day <= 29;
    +
    4256 case 4:
    +
    4257 case 6:
    +
    4258 case 9:
    +
    4259 case 11:
    +
    4260 return 1 <= day && day <= 30;
    +
    4261 default:
    +
    4262 return false;
    +
    4263 }
    +
    4264 }
    +
    4265
    +
    4266 public:
    +
    4267 date_format_t format;
    +
    4268 std::shared_ptr<basic_integer<T>> day;
    +
    4269 std::shared_ptr<basic_integer<T>> month;
    +
    4270 std::shared_ptr<basic_integer<T>> year;
    +
    4271
    +
    4272 protected:
    +
    4273 int m_format_mask;
    +
    4274 std::shared_ptr<basic_set<T>> m_separator;
    +
    4275 std::shared_ptr<basic_parser<T>> m_space;
    +
    4276 };
    -
    4274
    -
    4275 using date = basic_date<char>;
    -
    4276 using wdate = basic_date<wchar_t>;
    -
    4277#ifdef _UNICODE
    -
    4278 using tdate = wdate;
    -
    4279#else
    -
    4280 using tdate = date;
    -
    4281#endif
    - -
    4283
    -
    4287 template <class T>
    -
    -
    4288 class basic_time : public basic_parser<T>
    -
    4289 {
    -
    4290 public:
    -
    4291 basic_time(
    -
    4292 _In_ const std::shared_ptr<basic_integer10<T>>& _hour,
    -
    4293 _In_ const std::shared_ptr<basic_integer10<T>>& _minute,
    -
    4294 _In_ const std::shared_ptr<basic_integer10<T>>& _second,
    -
    4295 _In_ const std::shared_ptr<basic_integer10<T>>& _millisecond,
    -
    4296 _In_ const std::shared_ptr<basic_set<T>>& separator,
    -
    4297 _In_ const std::shared_ptr<basic_parser<T>>& millisecond_separator,
    -
    4298 _In_ const std::locale& locale = std::locale()) :
    -
    4299 basic_parser<T>(locale),
    -
    4300 hour(_hour),
    -
    4301 minute(_minute),
    -
    4302 second(_second),
    -
    4303 millisecond(_millisecond),
    -
    4304 m_separator(separator),
    -
    4305 m_millisecond_separator(millisecond_separator)
    -
    4306 {}
    -
    4307
    -
    4308 virtual bool match(
    -
    4309 _In_reads_or_z_(end) const T* text,
    -
    4310 _In_ size_t start = 0,
    -
    4311 _In_ size_t end = (size_t)-1,
    -
    4312 _In_ int flags = match_default)
    -
    4313 {
    -
    4314 assert(text || start >= end);
    -
    4315
    -
    4316 if (hour->match(text, start, end, flags) &&
    -
    4317 m_separator->match(text, hour->interval.end, end, flags) &&
    -
    4318 minute->match(text, m_separator->interval.end, end, flags) &&
    -
    4319 minute->value < 60)
    -
    4320 {
    -
    4321 // hh::mm
    -
    4322 size_t hit_offset = m_separator->hit_offset;
    -
    4323 if (m_separator->match(text, minute->interval.end, end, flags) &&
    -
    4324 m_separator->hit_offset == hit_offset && // Both separators must match.
    -
    4325 second && second->match(text, m_separator->interval.end, end, flags) &&
    -
    4326 second->value < 60)
    -
    4327 {
    -
    4328 // hh::mm:ss
    -
    4329 if (m_millisecond_separator && m_millisecond_separator->match(text, second->interval.end, end, flags) &&
    -
    4330 millisecond && millisecond->match(text, m_millisecond_separator->interval.end, end, flags) &&
    -
    4331 millisecond->value < 1000)
    -
    4332 {
    -
    4333 // hh::mm:ss.mmmm
    -
    4334 interval.end = millisecond->interval.end;
    -
    4335 }
    -
    4336 else {
    -
    4337 if (millisecond) millisecond->invalidate();
    -
    4338 interval.end = second->interval.end;
    -
    4339 }
    -
    4340 }
    -
    4341 else {
    -
    4342 if (second) second->invalidate();
    -
    4343 if (millisecond) millisecond->invalidate();
    -
    4344 interval.end = minute->interval.end;
    -
    4345 }
    -
    4346 interval.start = start;
    -
    4347 return true;
    -
    4348 }
    -
    4349
    -
    4350 hour->invalidate();
    -
    4351 minute->invalidate();
    -
    4352 if (second) second->invalidate();
    -
    4353 if (millisecond) millisecond->invalidate();
    -
    4354 interval.start = (interval.end = start) + 1;
    -
    4355 return false;
    -
    4356 }
    -
    4357
    -
    4358 virtual void invalidate()
    -
    4359 {
    -
    4360 hour->invalidate();
    -
    4361 minute->invalidate();
    -
    4362 if (second) second->invalidate();
    -
    4363 if (millisecond) millisecond->invalidate();
    - -
    4365 }
    -
    4366
    -
    4367 public:
    -
    4368 std::shared_ptr<basic_integer10<T>> hour;
    -
    4369 std::shared_ptr<basic_integer10<T>> minute;
    -
    4370 std::shared_ptr<basic_integer10<T>> second;
    -
    4371 std::shared_ptr<basic_integer10<T>> millisecond;
    -
    4372
    -
    4373 protected:
    -
    4374 std::shared_ptr<basic_set<T>> m_separator;
    -
    4375 std::shared_ptr<basic_parser<T>> m_millisecond_separator;
    -
    4376 };
    +
    4277
    +
    4278 using date = basic_date<char>;
    +
    4279 using wdate = basic_date<wchar_t>;
    +
    4280#ifdef _UNICODE
    +
    4281 using tdate = wdate;
    +
    4282#else
    +
    4283 using tdate = date;
    +
    4284#endif
    + +
    4286
    +
    4290 template <class T>
    +
    +
    4291 class basic_time : public basic_parser<T>
    +
    4292 {
    +
    4293 public:
    +
    4294 basic_time(
    +
    4295 _In_ const std::shared_ptr<basic_integer10<T>>& _hour,
    +
    4296 _In_ const std::shared_ptr<basic_integer10<T>>& _minute,
    +
    4297 _In_ const std::shared_ptr<basic_integer10<T>>& _second,
    +
    4298 _In_ const std::shared_ptr<basic_integer10<T>>& _millisecond,
    +
    4299 _In_ const std::shared_ptr<basic_set<T>>& separator,
    +
    4300 _In_ const std::shared_ptr<basic_parser<T>>& millisecond_separator,
    +
    4301 _In_ const std::locale& locale = std::locale()) :
    +
    4302 basic_parser<T>(locale),
    +
    4303 hour(_hour),
    +
    4304 minute(_minute),
    +
    4305 second(_second),
    +
    4306 millisecond(_millisecond),
    +
    4307 m_separator(separator),
    +
    4308 m_millisecond_separator(millisecond_separator)
    +
    4309 {}
    +
    4310
    +
    4311 virtual bool match(
    +
    4312 _In_reads_or_z_(end) const T* text,
    +
    4313 _In_ size_t start = 0,
    +
    4314 _In_ size_t end = (size_t)-1,
    +
    4315 _In_ int flags = match_default)
    +
    4316 {
    +
    4317 assert(text || start >= end);
    +
    4318
    +
    4319 if (hour->match(text, start, end, flags) &&
    +
    4320 m_separator->match(text, hour->interval.end, end, flags) &&
    +
    4321 minute->match(text, m_separator->interval.end, end, flags) &&
    +
    4322 minute->value < 60)
    +
    4323 {
    +
    4324 // hh::mm
    +
    4325 size_t hit_offset = m_separator->hit_offset;
    +
    4326 if (m_separator->match(text, minute->interval.end, end, flags) &&
    +
    4327 m_separator->hit_offset == hit_offset && // Both separators must match.
    +
    4328 second && second->match(text, m_separator->interval.end, end, flags) &&
    +
    4329 second->value < 60)
    +
    4330 {
    +
    4331 // hh::mm:ss
    +
    4332 if (m_millisecond_separator && m_millisecond_separator->match(text, second->interval.end, end, flags) &&
    +
    4333 millisecond && millisecond->match(text, m_millisecond_separator->interval.end, end, flags) &&
    +
    4334 millisecond->value < 1000)
    +
    4335 {
    +
    4336 // hh::mm:ss.mmmm
    +
    4337 this->interval.end = millisecond->interval.end;
    +
    4338 }
    +
    4339 else {
    +
    4340 if (millisecond) millisecond->invalidate();
    +
    4341 this->interval.end = second->interval.end;
    +
    4342 }
    +
    4343 }
    +
    4344 else {
    +
    4345 if (second) second->invalidate();
    +
    4346 if (millisecond) millisecond->invalidate();
    +
    4347 this->interval.end = minute->interval.end;
    +
    4348 }
    +
    4349 this->interval.start = start;
    +
    4350 return true;
    +
    4351 }
    +
    4352
    +
    4353 hour->invalidate();
    +
    4354 minute->invalidate();
    +
    4355 if (second) second->invalidate();
    +
    4356 if (millisecond) millisecond->invalidate();
    +
    4357 this->interval.start = (this->interval.end = start) + 1;
    +
    4358 return false;
    +
    4359 }
    +
    4360
    +
    4361 virtual void invalidate()
    +
    4362 {
    +
    4363 hour->invalidate();
    +
    4364 minute->invalidate();
    +
    4365 if (second) second->invalidate();
    +
    4366 if (millisecond) millisecond->invalidate();
    + +
    4368 }
    +
    4369
    +
    4370 public:
    +
    4371 std::shared_ptr<basic_integer10<T>> hour;
    +
    4372 std::shared_ptr<basic_integer10<T>> minute;
    +
    4373 std::shared_ptr<basic_integer10<T>> second;
    +
    4374 std::shared_ptr<basic_integer10<T>> millisecond;
    +
    4375
    +
    4376 protected:
    +
    4377 std::shared_ptr<basic_set<T>> m_separator;
    +
    4378 std::shared_ptr<basic_parser<T>> m_millisecond_separator;
    +
    4379 };
    -
    4377
    -
    4378 using time = basic_time<char>;
    -
    4379 using wtime = basic_time<wchar_t>;
    -
    4380#ifdef _UNICODE
    -
    4381 using ttime = wtime;
    -
    4382#else
    -
    4383 using ttime = time;
    -
    4384#endif
    - -
    4386
    -
    4390 template <class T>
    -
    -
    4391 class basic_angle : public basic_parser<T>
    -
    4392 {
    -
    4393 public:
    - -
    4395 _In_ const std::shared_ptr<basic_integer10<T>>& _degree,
    -
    4396 _In_ const std::shared_ptr<basic_parser<T>>& _degree_separator,
    -
    4397 _In_ const std::shared_ptr<basic_integer10<T>>& _minute,
    -
    4398 _In_ const std::shared_ptr<basic_parser<T>>& _minute_separator,
    -
    4399 _In_ const std::shared_ptr<basic_integer10<T>>& _second,
    -
    4400 _In_ const std::shared_ptr<basic_parser<T>>& _second_separator,
    -
    4401 _In_ const std::shared_ptr<basic_parser<T>>& _decimal,
    -
    4402 _In_ const std::locale& locale = std::locale()) :
    -
    4403 basic_parser<T>(locale),
    -
    4404 degree(_degree),
    -
    4405 degree_separator(_degree_separator),
    -
    4406 minute(_minute),
    -
    4407 minute_separator(_minute_separator),
    -
    4408 second(_second),
    -
    4409 second_separator(_second_separator),
    -
    4410 decimal(_decimal)
    -
    4411 {}
    -
    4412
    -
    4413 virtual bool match(
    -
    4414 _In_reads_or_z_(end) const T* text,
    -
    4415 _In_ size_t start = 0,
    -
    4416 _In_ size_t end = (size_t)-1,
    -
    4417 _In_ int flags = match_default)
    -
    4418 {
    -
    4419 assert(text || start >= end);
    -
    4420
    -
    4421 interval.end = start;
    -
    4422
    -
    4423 if (degree->match(text, interval.end, end, flags) &&
    -
    4424 degree_separator->match(text, degree->interval.end, end, flags))
    -
    4425 {
    -
    4426 // Degrees
    -
    4427 interval.end = degree_separator->interval.end;
    -
    4428 }
    -
    4429 else {
    -
    4430 degree->invalidate();
    -
    4431 degree_separator->invalidate();
    -
    4432 }
    -
    4433
    -
    4434 if (minute->match(text, interval.end, end, flags) &&
    -
    4435 minute->value < 60 &&
    -
    4436 minute_separator->match(text, minute->interval.end, end, flags))
    -
    4437 {
    -
    4438 // Minutes
    -
    4439 interval.end = minute_separator->interval.end;
    -
    4440 }
    -
    4441 else {
    -
    4442 minute->invalidate();
    -
    4443 minute_separator->invalidate();
    -
    4444 }
    -
    4445
    -
    4446 if (second && second->match(text, interval.end, end, flags) &&
    -
    4447 second->value < 60)
    -
    4448 {
    -
    4449 // Seconds
    -
    4450 interval.end = second->interval.end;
    -
    4451 if (second_separator && second_separator->match(text, interval.end, end, flags))
    -
    4452 interval.end = second_separator->interval.end;
    -
    4453 else
    -
    4454 if (second_separator) second_separator->invalidate();
    -
    4455 }
    -
    4456 else {
    -
    4457 if (second) second->invalidate();
    -
    4458 if (second_separator) second_separator->invalidate();
    -
    4459 }
    -
    4460
    -
    4461 if (degree->interval.start < degree->interval.end ||
    -
    4462 minute->interval.start < minute->interval.end ||
    -
    4463 second && second->interval.start < second->interval.end)
    -
    4464 {
    -
    4465 if (decimal && decimal->match(text, interval.end, end, flags)) {
    -
    4466 // Decimals
    -
    4467 interval.end = decimal->interval.end;
    -
    4468 }
    -
    4469 else if (decimal)
    -
    4470 decimal->invalidate();
    -
    4471 interval.start = start;
    -
    4472 return true;
    -
    4473 }
    -
    4474 if (decimal) decimal->invalidate();
    -
    4475 interval.start = (interval.end = start) + 1;
    -
    4476 return false;
    -
    4477 }
    -
    4478
    -
    4479 virtual void invalidate()
    -
    4480 {
    -
    4481 degree->invalidate();
    -
    4482 degree_separator->invalidate();
    -
    4483 minute->invalidate();
    -
    4484 minute_separator->invalidate();
    -
    4485 if (second) second->invalidate();
    -
    4486 if (second_separator) second_separator->invalidate();
    -
    4487 if (decimal) decimal->invalidate();
    - -
    4489 }
    -
    4490
    -
    4491 public:
    -
    4492 std::shared_ptr<basic_integer10<T>> degree;
    -
    4493 std::shared_ptr<basic_parser<T>> degree_separator;
    -
    4494 std::shared_ptr<basic_integer10<T>> minute;
    -
    4495 std::shared_ptr<basic_parser<T>> minute_separator;
    -
    4496 std::shared_ptr<basic_integer10<T>> second;
    -
    4497 std::shared_ptr<basic_parser<T>> second_separator;
    -
    4498 std::shared_ptr<basic_parser<T>> decimal;
    -
    4499 };
    +
    4380
    +
    4381 using time = basic_time<char>;
    +
    4382 using wtime = basic_time<wchar_t>;
    +
    4383#ifdef _UNICODE
    +
    4384 using ttime = wtime;
    +
    4385#else
    +
    4386 using ttime = time;
    +
    4387#endif
    + +
    4389
    +
    4393 template <class T>
    +
    +
    4394 class basic_angle : public basic_parser<T>
    +
    4395 {
    +
    4396 public:
    + +
    4398 _In_ const std::shared_ptr<basic_integer10<T>>& _degree,
    +
    4399 _In_ const std::shared_ptr<basic_parser<T>>& _degree_separator,
    +
    4400 _In_ const std::shared_ptr<basic_integer10<T>>& _minute,
    +
    4401 _In_ const std::shared_ptr<basic_parser<T>>& _minute_separator,
    +
    4402 _In_ const std::shared_ptr<basic_integer10<T>>& _second,
    +
    4403 _In_ const std::shared_ptr<basic_parser<T>>& _second_separator,
    +
    4404 _In_ const std::shared_ptr<basic_parser<T>>& _decimal,
    +
    4405 _In_ const std::locale& locale = std::locale()) :
    +
    4406 basic_parser<T>(locale),
    +
    4407 degree(_degree),
    +
    4408 degree_separator(_degree_separator),
    +
    4409 minute(_minute),
    +
    4410 minute_separator(_minute_separator),
    +
    4411 second(_second),
    +
    4412 second_separator(_second_separator),
    +
    4413 decimal(_decimal)
    +
    4414 {}
    +
    4415
    +
    4416 virtual bool match(
    +
    4417 _In_reads_or_z_(end) const T* text,
    +
    4418 _In_ size_t start = 0,
    +
    4419 _In_ size_t end = (size_t)-1,
    +
    4420 _In_ int flags = match_default)
    +
    4421 {
    +
    4422 assert(text || start >= end);
    +
    4423
    +
    4424 this->interval.end = start;
    +
    4425
    +
    4426 if (degree->match(text, this->interval.end, end, flags) &&
    +
    4427 degree_separator->match(text, degree->interval.end, end, flags))
    +
    4428 {
    +
    4429 // Degrees
    +
    4430 this->interval.end = degree_separator->interval.end;
    +
    4431 }
    +
    4432 else {
    +
    4433 degree->invalidate();
    +
    4434 degree_separator->invalidate();
    +
    4435 }
    +
    4436
    +
    4437 if (minute->match(text, this->interval.end, end, flags) &&
    +
    4438 minute->value < 60 &&
    +
    4439 minute_separator->match(text, minute->interval.end, end, flags))
    +
    4440 {
    +
    4441 // Minutes
    +
    4442 this->interval.end = minute_separator->interval.end;
    +
    4443 }
    +
    4444 else {
    +
    4445 minute->invalidate();
    +
    4446 minute_separator->invalidate();
    +
    4447 }
    +
    4448
    +
    4449 if (second && second->match(text, this->interval.end, end, flags) &&
    +
    4450 second->value < 60)
    +
    4451 {
    +
    4452 // Seconds
    +
    4453 this->interval.end = second->interval.end;
    +
    4454 if (second_separator && second_separator->match(text, this->interval.end, end, flags))
    +
    4455 this->interval.end = second_separator->interval.end;
    +
    4456 else
    +
    4457 if (second_separator) second_separator->invalidate();
    +
    4458 }
    +
    4459 else {
    +
    4460 if (second) second->invalidate();
    +
    4461 if (second_separator) second_separator->invalidate();
    +
    4462 }
    +
    4463
    +
    4464 if (degree->interval.start < degree->interval.end ||
    +
    4465 minute->interval.start < minute->interval.end ||
    +
    4466 (second && second->interval.start < second->interval.end))
    +
    4467 {
    +
    4468 if (decimal && decimal->match(text, this->interval.end, end, flags)) {
    +
    4469 // Decimals
    +
    4470 this->interval.end = decimal->interval.end;
    +
    4471 }
    +
    4472 else if (decimal)
    +
    4473 decimal->invalidate();
    +
    4474 this->interval.start = start;
    +
    4475 return true;
    +
    4476 }
    +
    4477 if (decimal) decimal->invalidate();
    +
    4478 this->interval.start = (this->interval.end = start) + 1;
    +
    4479 return false;
    +
    4480 }
    +
    4481
    +
    4482 virtual void invalidate()
    +
    4483 {
    +
    4484 degree->invalidate();
    +
    4485 degree_separator->invalidate();
    +
    4486 minute->invalidate();
    +
    4487 minute_separator->invalidate();
    +
    4488 if (second) second->invalidate();
    +
    4489 if (second_separator) second_separator->invalidate();
    +
    4490 if (decimal) decimal->invalidate();
    + +
    4492 }
    +
    4493
    +
    4494 public:
    +
    4495 std::shared_ptr<basic_integer10<T>> degree;
    +
    4496 std::shared_ptr<basic_parser<T>> degree_separator;
    +
    4497 std::shared_ptr<basic_integer10<T>> minute;
    +
    4498 std::shared_ptr<basic_parser<T>> minute_separator;
    +
    4499 std::shared_ptr<basic_integer10<T>> second;
    +
    4500 std::shared_ptr<basic_parser<T>> second_separator;
    +
    4501 std::shared_ptr<basic_parser<T>> decimal;
    +
    4502 };
    -
    4500
    -
    4501 using angle = basic_angle<char>;
    - -
    4503#ifdef _UNICODE
    -
    4504 using RRegElKot = wangle;
    -
    4505#else
    -
    4506 using RRegElKot = angle;
    -
    4507#endif
    - -
    4509
    -
    4513 template <class T>
    -
    - -
    4515 {
    -
    4516 public:
    - -
    4518 _In_ const std::shared_ptr<basic_parser<T>>& digit,
    -
    4519 _In_ const std::shared_ptr<basic_parser<T>>& plus_sign,
    -
    4520 _In_ const std::shared_ptr<basic_set<T>>& lparenthesis,
    -
    4521 _In_ const std::shared_ptr<basic_set<T>>& rparenthesis,
    -
    4522 _In_ const std::shared_ptr<basic_parser<T>>& separator,
    -
    4523 _In_ const std::shared_ptr<basic_parser<T>>& space,
    -
    4524 _In_ const std::locale& locale = std::locale()) :
    -
    4525 basic_parser<T>(locale),
    -
    4526 m_digit(digit),
    -
    4527 m_plus_sign(plus_sign),
    -
    4528 m_lparenthesis(lparenthesis),
    -
    4529 m_rparenthesis(rparenthesis),
    -
    4530 m_separator(separator),
    -
    4531 m_space(space)
    -
    4532 {}
    -
    4533
    -
    4534 virtual bool match(
    -
    4535 _In_reads_or_z_(end) const T* text,
    -
    4536 _In_ size_t start = 0,
    -
    4537 _In_ size_t end = (size_t)-1,
    -
    4538 _In_ int flags = match_default)
    -
    4539 {
    -
    4540 assert(text || start >= end);
    -
    4541
    -
    4542 size_t safe_digit_end = start, safe_value_size = 0;
    -
    4543 bool has_digits = false, after_digit = false, in_parentheses = false, after_parentheses = false;
    -
    4544 const int space_match_flags = flags & ~match_multiline; // Spaces in phone numbers must never be broken in new line.
    -
    4545
    -
    4546 interval.end = start;
    -
    4547 value.clear();
    -
    4548 m_lparenthesis->invalidate();
    -
    4549 m_rparenthesis->invalidate();
    -
    4550
    -
    4551 if (m_plus_sign && m_plus_sign->match(text, interval.end, end, flags)) {
    -
    4552 value.append(text + m_plus_sign->interval.start, text + m_plus_sign->interval.end);
    -
    4553 safe_value_size = value.size();
    -
    4554 interval.end = m_plus_sign->interval.end;
    -
    4555 }
    -
    4556
    -
    4557 for (;;) {
    -
    4558 assert(text || interval.end >= end);
    -
    4559 if (interval.end >= end || !text[interval.end])
    -
    4560 break;
    -
    4561 if (m_digit->match(text, interval.end, end, flags)) {
    -
    4562 // Digit
    -
    4563 value.append(text + m_digit->interval.start, text + m_digit->interval.end);
    -
    4564 interval.end = m_digit->interval.end;
    -
    4565 if (!in_parentheses) {
    - -
    4567 safe_value_size = value.size();
    -
    4568 has_digits = true;
    -
    4569 }
    -
    4570 after_digit = true;
    -
    4571 after_parentheses = false;
    -
    4572 }
    -
    4573 else if (
    -
    4574 m_lparenthesis && !m_lparenthesis->interval && // No left parenthesis yet
    -
    4575 m_rparenthesis && !m_rparenthesis->interval && // Right parenthesis after left
    -
    4576 m_lparenthesis->match(text, interval.end, end, flags))
    -
    4577 {
    -
    4578 // Left parenthesis
    -
    4579 value.append(text + m_lparenthesis->interval.start, m_lparenthesis->interval.size());
    -
    4580 interval.end = m_lparenthesis->interval.end;
    -
    4581 in_parentheses = true;
    -
    4582 after_digit = false;
    -
    4583 after_parentheses = false;
    -
    4584 }
    -
    4585 else if (
    -
    4586 in_parentheses && // After left parenthesis
    -
    4587 m_rparenthesis && !m_rparenthesis->interval && // No right parenthesis yet
    -
    4588 m_rparenthesis->match(text, interval.end, end, flags) &&
    -
    4589 m_lparenthesis->hit_offset == m_rparenthesis->hit_offset) // Left and right parentheses must match
    -
    4590 {
    -
    4591 // Right parenthesis
    -
    4592 value.append(text + m_rparenthesis->interval.start, text + m_rparenthesis->interval.end);
    -
    4593 interval.end = m_rparenthesis->interval.end;
    - -
    4595 safe_value_size = value.size();
    -
    4596 in_parentheses = false;
    -
    4597 after_digit = false;
    -
    4598 after_parentheses = true;
    -
    4599 }
    -
    4600 else if (
    -
    4601 after_digit &&
    -
    4602 !in_parentheses && // No separators inside parentheses
    -
    4603 !after_parentheses && // No separators following right parenthesis
    -
    4604 m_separator && m_separator->match(text, interval.end, end, flags))
    -
    4605 {
    -
    4606 // Separator
    -
    4607 interval.end = m_separator->interval.end;
    -
    4608 after_digit = false;
    -
    4609 after_parentheses = false;
    -
    4610 }
    -
    4611 else if (
    - -
    4613 m_space && m_space->match(text, interval.end, end, space_match_flags))
    -
    4614 {
    -
    4615 // Space
    -
    4616 interval.end = m_space->interval.end;
    -
    4617 after_digit = false;
    -
    4618 after_parentheses = false;
    -
    4619 }
    -
    4620 else
    -
    4621 break;
    -
    4622 }
    -
    4623 if (has_digits) {
    -
    4624 value.erase(safe_value_size);
    -
    4625 interval.start = start;
    - -
    4627 return true;
    -
    4628 }
    -
    4629 value.clear();
    -
    4630 interval.start = (interval.end = start) + 1;
    -
    4631 return false;
    -
    4632 }
    -
    4633
    -
    4634 virtual void invalidate()
    -
    4635 {
    -
    4636 value.clear();
    - -
    4638 }
    -
    4639
    -
    4640 public:
    -
    4641 std::basic_string<T> value;
    +
    4503
    +
    4504 using angle = basic_angle<char>;
    + +
    4506#ifdef _UNICODE
    +
    4507 using RRegElKot = wangle;
    +
    4508#else
    +
    4509 using RRegElKot = angle;
    +
    4510#endif
    + +
    4512
    +
    4516 template <class T>
    +
    + +
    4518 {
    +
    4519 public:
    + +
    4521 _In_ const std::shared_ptr<basic_parser<T>>& digit,
    +
    4522 _In_ const std::shared_ptr<basic_parser<T>>& plus_sign,
    +
    4523 _In_ const std::shared_ptr<basic_set<T>>& lparenthesis,
    +
    4524 _In_ const std::shared_ptr<basic_set<T>>& rparenthesis,
    +
    4525 _In_ const std::shared_ptr<basic_parser<T>>& separator,
    +
    4526 _In_ const std::shared_ptr<basic_parser<T>>& space,
    +
    4527 _In_ const std::locale& locale = std::locale()) :
    +
    4528 basic_parser<T>(locale),
    +
    4529 m_digit(digit),
    +
    4530 m_plus_sign(plus_sign),
    +
    4531 m_lparenthesis(lparenthesis),
    +
    4532 m_rparenthesis(rparenthesis),
    +
    4533 m_separator(separator),
    +
    4534 m_space(space)
    +
    4535 {}
    +
    4536
    +
    4537 virtual bool match(
    +
    4538 _In_reads_or_z_(end) const T* text,
    +
    4539 _In_ size_t start = 0,
    +
    4540 _In_ size_t end = (size_t)-1,
    +
    4541 _In_ int flags = match_default)
    +
    4542 {
    +
    4543 assert(text || start >= end);
    +
    4544
    +
    4545 size_t safe_digit_end = start, safe_value_size = 0;
    +
    4546 bool has_digits = false, after_digit = false, in_parentheses = false, after_parentheses = false;
    +
    4547 const int space_match_flags = flags & ~match_multiline; // Spaces in phone numbers must never be broken in new line.
    +
    4548
    +
    4549 this->interval.end = start;
    +
    4550 value.clear();
    +
    4551 m_lparenthesis->invalidate();
    +
    4552 m_rparenthesis->invalidate();
    +
    4553
    +
    4554 if (m_plus_sign && m_plus_sign->match(text, this->interval.end, end, flags)) {
    +
    4555 value.append(text + m_plus_sign->interval.start, text + m_plus_sign->interval.end);
    +
    4556 safe_value_size = value.size();
    +
    4557 this->interval.end = m_plus_sign->interval.end;
    +
    4558 }
    +
    4559
    +
    4560 for (;;) {
    +
    4561 assert(text || this->interval.end >= end);
    +
    4562 if (this->interval.end >= end || !text[this->interval.end])
    +
    4563 break;
    +
    4564 if (m_digit->match(text, this->interval.end, end, flags)) {
    +
    4565 // Digit
    +
    4566 value.append(text + m_digit->interval.start, text + m_digit->interval.end);
    +
    4567 this->interval.end = m_digit->interval.end;
    +
    4568 if (!in_parentheses) {
    +
    4569 safe_digit_end = this->interval.end;
    +
    4570 safe_value_size = value.size();
    +
    4571 has_digits = true;
    +
    4572 }
    +
    4573 after_digit = true;
    +
    4574 after_parentheses = false;
    +
    4575 }
    +
    4576 else if (
    +
    4577 m_lparenthesis && !m_lparenthesis->interval && // No left parenthesis yet
    +
    4578 m_rparenthesis && !m_rparenthesis->interval && // Right parenthesis after left
    +
    4579 m_lparenthesis->match(text, this->interval.end, end, flags))
    +
    4580 {
    +
    4581 // Left parenthesis
    +
    4582 value.append(text + m_lparenthesis->interval.start, m_lparenthesis->interval.size());
    +
    4583 this->interval.end = m_lparenthesis->interval.end;
    +
    4584 in_parentheses = true;
    +
    4585 after_digit = false;
    +
    4586 after_parentheses = false;
    +
    4587 }
    +
    4588 else if (
    +
    4589 in_parentheses && // After left parenthesis
    +
    4590 m_rparenthesis && !m_rparenthesis->interval && // No right parenthesis yet
    +
    4591 m_rparenthesis->match(text, this->interval.end, end, flags) &&
    +
    4592 m_lparenthesis->hit_offset == m_rparenthesis->hit_offset) // Left and right parentheses must match
    +
    4593 {
    +
    4594 // Right parenthesis
    +
    4595 value.append(text + m_rparenthesis->interval.start, text + m_rparenthesis->interval.end);
    +
    4596 this->interval.end = m_rparenthesis->interval.end;
    +
    4597 safe_digit_end = this->interval.end;
    +
    4598 safe_value_size = value.size();
    +
    4599 in_parentheses = false;
    +
    4600 after_digit = false;
    +
    4601 after_parentheses = true;
    +
    4602 }
    +
    4603 else if (
    +
    4604 after_digit &&
    +
    4605 !in_parentheses && // No separators inside parentheses
    +
    4606 !after_parentheses && // No separators following right parenthesis
    +
    4607 m_separator && m_separator->match(text, this->interval.end, end, flags))
    +
    4608 {
    +
    4609 // Separator
    +
    4610 this->interval.end = m_separator->interval.end;
    +
    4611 after_digit = false;
    +
    4612 after_parentheses = false;
    +
    4613 }
    +
    4614 else if (
    + +
    4616 m_space && m_space->match(text, this->interval.end, end, space_match_flags))
    +
    4617 {
    +
    4618 // Space
    +
    4619 this->interval.end = m_space->interval.end;
    +
    4620 after_digit = false;
    +
    4621 after_parentheses = false;
    +
    4622 }
    +
    4623 else
    +
    4624 break;
    +
    4625 }
    +
    4626 if (has_digits) {
    +
    4627 value.erase(safe_value_size);
    +
    4628 this->interval.start = start;
    +
    4629 this->interval.end = safe_digit_end;
    +
    4630 return true;
    +
    4631 }
    +
    4632 value.clear();
    +
    4633 this->interval.start = (this->interval.end = start) + 1;
    +
    4634 return false;
    +
    4635 }
    +
    4636
    +
    4637 virtual void invalidate()
    +
    4638 {
    +
    4639 value.clear();
    + +
    4641 }
    4642
    -
    4643 protected:
    -
    4644 std::shared_ptr<basic_parser<T>> m_digit;
    -
    4645 std::shared_ptr<basic_parser<T>> m_plus_sign;
    -
    4646 std::shared_ptr<basic_set<T>> m_lparenthesis;
    -
    4647 std::shared_ptr<basic_set<T>> m_rparenthesis;
    -
    4648 std::shared_ptr<basic_parser<T>> m_separator;
    -
    4649 std::shared_ptr<basic_parser<T>> m_space;
    -
    4650 };
    +
    4643 public:
    +
    4644 std::basic_string<T> value;
    +
    4645
    +
    4646 protected:
    +
    4647 std::shared_ptr<basic_parser<T>> m_digit;
    +
    4648 std::shared_ptr<basic_parser<T>> m_plus_sign;
    +
    4649 std::shared_ptr<basic_set<T>> m_lparenthesis;
    +
    4650 std::shared_ptr<basic_set<T>> m_rparenthesis;
    +
    4651 std::shared_ptr<basic_parser<T>> m_separator;
    +
    4652 std::shared_ptr<basic_parser<T>> m_space;
    +
    4653 };
    -
    4651
    - - -
    4654#ifdef _UNICODE
    - -
    4656#else
    - -
    4658#endif
    - -
    4660
    -
    4664 template <class T>
    -
    - -
    4666 {
    -
    4667 public:
    - -
    4669 _In_ const std::shared_ptr<basic_parser<T>>& element,
    -
    4670 _In_ const std::shared_ptr<basic_parser<T>>& digit,
    -
    4671 _In_ const std::shared_ptr<basic_parser<T>>& sign,
    -
    4672 _In_ const std::locale& locale = std::locale()) :
    -
    4673 basic_parser<T>(locale),
    -
    4674 m_element(element),
    -
    4675 m_digit(digit),
    -
    4676 m_sign(sign),
    -
    4677 has_digits(false),
    -
    4678 has_charge(false)
    -
    4679 {}
    -
    4680
    -
    4681 virtual bool match(
    -
    4682 _In_reads_or_z_(end) const T* text,
    -
    4683 _In_ size_t start = 0,
    -
    4684 _In_ size_t end = (size_t)-1,
    -
    4685 _In_ int flags = match_default)
    -
    4686 {
    -
    4687 assert(text || start >= end);
    -
    4688
    -
    4689 has_digits = false;
    -
    4690 has_charge = false;
    -
    4691 interval.end = start;
    -
    4692
    -
    4693 const int element_match_flags = flags & ~match_case_insensitive; // Chemical elements are always case-sensitive.
    -
    4694 for (;;) {
    -
    4695 if (m_element->match(text, interval.end, end, element_match_flags)) {
    -
    4696 interval.end = m_element->interval.end;
    -
    4697 while (m_digit->match(text, interval.end, end, flags)) {
    -
    4698 interval.end = m_digit->interval.end;
    -
    4699 has_digits = true;
    -
    4700 }
    -
    4701 }
    -
    4702 else if (start < interval.end) {
    -
    4703 if (m_sign->match(text, interval.end, end, flags)) {
    -
    4704 interval.end = m_sign->interval.end;
    -
    4705 has_charge = true;
    -
    4706 }
    -
    4707 interval.start = start;
    -
    4708 return true;
    -
    4709 }
    -
    4710 else {
    -
    4711 interval.start = (interval.end = start) + 1;
    -
    4712 return false;
    -
    4713 }
    -
    4714 }
    -
    4715 }
    -
    4716
    -
    4717 virtual void invalidate()
    -
    4718 {
    -
    4719 has_digits = false;
    -
    4720 has_charge = false;
    - -
    4722 }
    -
    4723
    -
    4724 public:
    -
    4725 bool has_digits;
    -
    4726 bool has_charge;
    -
    4727
    -
    4728 protected:
    -
    4729 std::shared_ptr<basic_parser<T>> m_element;
    -
    4730 std::shared_ptr<basic_parser<T>> m_digit;
    -
    4731 std::shared_ptr<basic_parser<T>> m_sign;
    -
    4732 };
    +
    4654
    + + +
    4657#ifdef _UNICODE
    + +
    4659#else
    + +
    4661#endif
    + +
    4663
    +
    4667 template <class T>
    +
    + +
    4669 {
    +
    4670 public:
    + +
    4672 _In_ const std::shared_ptr<basic_parser<T>>& element,
    +
    4673 _In_ const std::shared_ptr<basic_parser<T>>& digit,
    +
    4674 _In_ const std::shared_ptr<basic_parser<T>>& sign,
    +
    4675 _In_ const std::locale& locale = std::locale()) :
    +
    4676 basic_parser<T>(locale),
    +
    4677 m_element(element),
    +
    4678 m_digit(digit),
    +
    4679 m_sign(sign),
    +
    4680 has_digits(false),
    +
    4681 has_charge(false)
    +
    4682 {}
    +
    4683
    +
    4684 virtual bool match(
    +
    4685 _In_reads_or_z_(end) const T* text,
    +
    4686 _In_ size_t start = 0,
    +
    4687 _In_ size_t end = (size_t)-1,
    +
    4688 _In_ int flags = match_default)
    +
    4689 {
    +
    4690 assert(text || start >= end);
    +
    4691
    +
    4692 has_digits = false;
    +
    4693 has_charge = false;
    +
    4694 this->interval.end = start;
    +
    4695
    +
    4696 const int element_match_flags = flags & ~match_case_insensitive; // Chemical elements are always case-sensitive.
    +
    4697 for (;;) {
    +
    4698 if (m_element->match(text, this->interval.end, end, element_match_flags)) {
    +
    4699 this->interval.end = m_element->interval.end;
    +
    4700 while (m_digit->match(text, this->interval.end, end, flags)) {
    +
    4701 this->interval.end = m_digit->interval.end;
    +
    4702 has_digits = true;
    +
    4703 }
    +
    4704 }
    +
    4705 else if (start < this->interval.end) {
    +
    4706 if (m_sign->match(text, this->interval.end, end, flags)) {
    +
    4707 this->interval.end = m_sign->interval.end;
    +
    4708 has_charge = true;
    +
    4709 }
    +
    4710 this->interval.start = start;
    +
    4711 return true;
    +
    4712 }
    +
    4713 else {
    +
    4714 this->interval.start = (this->interval.end = start) + 1;
    +
    4715 return false;
    +
    4716 }
    +
    4717 }
    +
    4718 }
    +
    4719
    +
    4720 virtual void invalidate()
    +
    4721 {
    +
    4722 has_digits = false;
    +
    4723 has_charge = false;
    + +
    4725 }
    +
    4726
    +
    4727 public:
    +
    4728 bool has_digits;
    +
    4729 bool has_charge;
    +
    4730
    +
    4731 protected:
    +
    4732 std::shared_ptr<basic_parser<T>> m_element;
    +
    4733 std::shared_ptr<basic_parser<T>> m_digit;
    +
    4734 std::shared_ptr<basic_parser<T>> m_sign;
    +
    4735 };
    -
    4733
    - - -
    4736#ifdef _UNICODE
    - -
    4738#else
    - -
    4740#endif
    - -
    4742
    -
    - -
    4747 {
    -
    4748 public:
    -
    4749 virtual bool match(
    -
    4750 _In_reads_or_z_(end) const char* text,
    -
    4751 _In_ size_t start = 0,
    -
    4752 _In_ size_t end = (size_t)-1,
    -
    4753 _In_ int flags = match_default)
    -
    4754 {
    -
    4755 assert(text || start >= end);
    -
    4756 interval.end = start;
    -
    4757
    -
    4758 assert(text || interval.end >= end);
    -
    4759 if (interval.end < end && text[interval.end]) {
    -
    4760 if (text[interval.end] == '\r') {
    -
    4761 interval.end++;
    -
    4762 if (interval.end < end && text[interval.end] == '\n') {
    -
    4763 interval.start = start;
    -
    4764 interval.end++;
    -
    4765 return true;
    -
    4766 }
    -
    4767 }
    -
    4768 else if (text[interval.end] == '\n') {
    -
    4769 interval.start = start;
    -
    4770 interval.end++;
    -
    4771 return true;
    -
    4772 }
    -
    4773 }
    -
    4774 interval.start = (interval.end = start) + 1;
    -
    4775 return false;
    -
    4776 }
    -
    4777 };
    +
    4736
    + + +
    4739#ifdef _UNICODE
    + +
    4741#else
    + +
    4743#endif
    + +
    4745
    +
    + +
    4750 {
    +
    4751 public:
    +
    4752 virtual bool match(
    +
    4753 _In_reads_or_z_(end) const char* text,
    +
    4754 _In_ size_t start = 0,
    +
    4755 _In_ size_t end = (size_t)-1,
    +
    4756 _In_ int flags = match_default)
    +
    4757 {
    +
    4758 assert(text || start >= end);
    +
    4759 this->interval.end = start;
    +
    4760
    +
    4761 assert(text || this->interval.end >= end);
    +
    4762 if (this->interval.end < end && text[this->interval.end]) {
    +
    4763 if (text[this->interval.end] == '\r') {
    +
    4764 this->interval.end++;
    +
    4765 if (this->interval.end < end && text[this->interval.end] == '\n') {
    +
    4766 this->interval.start = start;
    +
    4767 this->interval.end++;
    +
    4768 return true;
    +
    4769 }
    +
    4770 }
    +
    4771 else if (text[this->interval.end] == '\n') {
    +
    4772 this->interval.start = start;
    +
    4773 this->interval.end++;
    +
    4774 return true;
    +
    4775 }
    +
    4776 }
    +
    4777 this->interval.start = (this->interval.end = start) + 1;
    +
    4778 return false;
    +
    4779 }
    +
    4780 };
    -
    4778
    -
    -
    4782 class http_space : public parser
    -
    4783 {
    -
    4784 public:
    -
    4785 virtual bool match(
    -
    4786 _In_reads_or_z_(end) const char* text,
    -
    4787 _In_ size_t start = 0,
    -
    4788 _In_ size_t end = (size_t)-1,
    -
    4789 _In_ int flags = match_default)
    -
    4790 {
    -
    4791 assert(text || start >= end);
    -
    4792 interval.end = start;
    -
    4793 if (m_line_break.match(text, interval.end, end, flags)) {
    -
    4794 interval.end = m_line_break.interval.end;
    -
    4795 if (interval.end < end && text[interval.end] && isspace(text[interval.end])) {
    -
    4796 interval.start = start;
    -
    4797 interval.end++;
    -
    4798 while (interval.end < end && text[interval.end] && isspace(text[interval.end])) interval.end++;
    -
    4799 return true;
    -
    4800 }
    -
    4801 }
    -
    4802 else if (interval.end < end && text[interval.end] && isspace(text[interval.end])) {
    -
    4803 interval.start = start;
    -
    4804 interval.end++;
    -
    4805 while (interval.end < end && text[interval.end] && isspace(text[interval.end])) interval.end++;
    -
    4806 return true;
    -
    4807 }
    -
    4808 interval.start = (interval.end = start) + 1;
    -
    4809 return false;
    -
    4810 }
    -
    4811
    -
    4812 protected:
    -
    4813 http_line_break m_line_break;
    -
    4814 };
    +
    4781
    +
    +
    4785 class http_space : public parser
    +
    4786 {
    +
    4787 public:
    +
    4788 virtual bool match(
    +
    4789 _In_reads_or_z_(end) const char* text,
    +
    4790 _In_ size_t start = 0,
    +
    4791 _In_ size_t end = (size_t)-1,
    +
    4792 _In_ int flags = match_default)
    +
    4793 {
    +
    4794 assert(text || start >= end);
    +
    4795 this->interval.end = start;
    +
    4796 if (m_line_break.match(text, this->interval.end, end, flags)) {
    +
    4797 this->interval.end = m_line_break.interval.end;
    +
    4798 if (this->interval.end < end && text[this->interval.end] && isspace(text[this->interval.end])) {
    +
    4799 this->interval.start = start;
    +
    4800 this->interval.end++;
    +
    4801 while (this->interval.end < end && text[this->interval.end] && isspace(text[this->interval.end])) this->interval.end++;
    +
    4802 return true;
    +
    4803 }
    +
    4804 }
    +
    4805 else if (this->interval.end < end && text[this->interval.end] && isspace(text[this->interval.end])) {
    +
    4806 this->interval.start = start;
    +
    4807 this->interval.end++;
    +
    4808 while (this->interval.end < end && text[this->interval.end] && isspace(text[this->interval.end])) this->interval.end++;
    +
    4809 return true;
    +
    4810 }
    +
    4811 this->interval.start = (this->interval.end = start) + 1;
    +
    4812 return false;
    +
    4813 }
    +
    4814
    +
    4815 protected:
    +
    4816 http_line_break m_line_break;
    +
    4817 };
    -
    4815
    -
    -
    4819 class http_text_char : public parser
    -
    4820 {
    -
    4821 public:
    -
    4822 virtual bool match(
    -
    4823 _In_reads_or_z_(end) const char* text,
    -
    4824 _In_ size_t start = 0,
    -
    4825 _In_ size_t end = (size_t)-1,
    -
    4826 _In_ int flags = match_default)
    -
    4827 {
    -
    4828 assert(text || start >= end);
    -
    4829 interval.end = start;
    -
    4830
    -
    4831 assert(text || interval.end >= end);
    -
    4832 if (m_space.match(text, interval.end, end, flags)) {
    -
    4833 interval.start = start;
    -
    4834 interval.end = m_space.interval.end;
    -
    4835 return true;
    -
    4836 }
    -
    4837 else if (interval.end < end && text[interval.end] && text[interval.end] >= 0x20) {
    -
    4838 interval.start = start;
    -
    4839 interval.end++;
    -
    4840 return true;
    -
    4841 }
    -
    4842 interval.start = (interval.end = start) + 1;
    -
    4843 return false;
    -
    4844 }
    -
    4845
    -
    4846 protected:
    -
    4847 http_space m_space;
    -
    4848 };
    +
    4818
    +
    +
    4822 class http_text_char : public parser
    +
    4823 {
    +
    4824 public:
    +
    4825 virtual bool match(
    +
    4826 _In_reads_or_z_(end) const char* text,
    +
    4827 _In_ size_t start = 0,
    +
    4828 _In_ size_t end = (size_t)-1,
    +
    4829 _In_ int flags = match_default)
    +
    4830 {
    +
    4831 assert(text || start >= end);
    +
    4832 this->interval.end = start;
    +
    4833
    +
    4834 assert(text || this->interval.end >= end);
    +
    4835 if (m_space.match(text, this->interval.end, end, flags)) {
    +
    4836 this->interval.start = start;
    +
    4837 this->interval.end = m_space.interval.end;
    +
    4838 return true;
    +
    4839 }
    +
    4840 else if (this->interval.end < end && text[this->interval.end] && text[this->interval.end] >= 0x20) {
    +
    4841 this->interval.start = start;
    +
    4842 this->interval.end++;
    +
    4843 return true;
    +
    4844 }
    +
    4845 this->interval.start = (this->interval.end = start) + 1;
    +
    4846 return false;
    +
    4847 }
    +
    4848
    +
    4849 protected:
    +
    4850 http_space m_space;
    +
    4851 };
    -
    4849
    -
    -
    4853 class http_token : public parser
    -
    4854 {
    -
    4855 public:
    -
    4856 virtual bool match(
    -
    4857 _In_reads_or_z_(end) const char* text,
    -
    4858 _In_ size_t start = 0,
    -
    4859 _In_ size_t end = (size_t)-1,
    -
    4860 _In_ int flags = match_default)
    -
    4861 {
    -
    4862 assert(text || start >= end);
    -
    4863 interval.end = start;
    -
    4864 for (;;) {
    -
    4865 if (interval.end < end && text[interval.end]) {
    -
    4866 if ((unsigned int)text[interval.end] < 0x20 ||
    -
    4867 (unsigned int)text[interval.end] == 0x7f ||
    -
    4868 text[interval.end] == '(' ||
    -
    4869 text[interval.end] == ')' ||
    -
    4870 text[interval.end] == '<' ||
    -
    4871 text[interval.end] == '>' ||
    -
    4872 text[interval.end] == '@' ||
    -
    4873 text[interval.end] == ',' ||
    -
    4874 text[interval.end] == ';' ||
    -
    4875 text[interval.end] == ':' ||
    -
    4876 text[interval.end] == '\\' ||
    -
    4877 text[interval.end] == '\"' ||
    -
    4878 text[interval.end] == '/' ||
    -
    4879 text[interval.end] == '[' ||
    -
    4880 text[interval.end] == ']' ||
    -
    4881 text[interval.end] == '?' ||
    -
    4882 text[interval.end] == '=' ||
    -
    4883 text[interval.end] == '{' ||
    -
    4884 text[interval.end] == '}' ||
    - -
    4886 break;
    -
    4887 else
    -
    4888 interval.end++;
    -
    4889 }
    -
    4890 else
    -
    4891 break;
    -
    4892 }
    -
    4893 if (start < interval.end) {
    -
    4894 interval.start = start;
    -
    4895 return true;
    -
    4896 }
    -
    4897 else {
    -
    4898 interval.start = (interval.end = start) + 1;
    -
    4899 return false;
    -
    4900 }
    -
    4901 }
    -
    4902 };
    +
    4852
    +
    +
    4856 class http_token : public parser
    +
    4857 {
    +
    4858 public:
    +
    4859 virtual bool match(
    +
    4860 _In_reads_or_z_(end) const char* text,
    +
    4861 _In_ size_t start = 0,
    +
    4862 _In_ size_t end = (size_t)-1,
    +
    4863 _In_ int flags = match_default)
    +
    4864 {
    +
    4865 assert(text || start >= end);
    +
    4866 this->interval.end = start;
    +
    4867 for (;;) {
    +
    4868 if (this->interval.end < end && text[this->interval.end]) {
    +
    4869 if ((unsigned int)text[this->interval.end] < 0x20 ||
    +
    4870 (unsigned int)text[this->interval.end] == 0x7f ||
    +
    4871 text[this->interval.end] == '(' ||
    +
    4872 text[this->interval.end] == ')' ||
    +
    4873 text[this->interval.end] == '<' ||
    +
    4874 text[this->interval.end] == '>' ||
    +
    4875 text[this->interval.end] == '@' ||
    +
    4876 text[this->interval.end] == ',' ||
    +
    4877 text[this->interval.end] == ';' ||
    +
    4878 text[this->interval.end] == ':' ||
    +
    4879 text[this->interval.end] == '\\' ||
    +
    4880 text[this->interval.end] == '\"' ||
    +
    4881 text[this->interval.end] == '/' ||
    +
    4882 text[this->interval.end] == '[' ||
    +
    4883 text[this->interval.end] == ']' ||
    +
    4884 text[this->interval.end] == '?' ||
    +
    4885 text[this->interval.end] == '=' ||
    +
    4886 text[this->interval.end] == '{' ||
    +
    4887 text[this->interval.end] == '}' ||
    +
    4888 isspace(text[this->interval.end]))
    +
    4889 break;
    +
    4890 else
    +
    4891 this->interval.end++;
    +
    4892 }
    +
    4893 else
    +
    4894 break;
    +
    4895 }
    + +
    4897 this->interval.start = start;
    +
    4898 return true;
    +
    4899 }
    +
    4900 else {
    +
    4901 this->interval.start = (this->interval.end = start) + 1;
    +
    4902 return false;
    +
    4903 }
    +
    4904 }
    +
    4905 };
    -
    4903
    -
    - -
    4908 {
    -
    4909 public:
    -
    4910 virtual bool match(
    -
    4911 _In_reads_or_z_(end) const char* text,
    -
    4912 _In_ size_t start = 0,
    -
    4913 _In_ size_t end = (size_t)-1,
    -
    4914 _In_ int flags = match_default)
    -
    4915 {
    -
    4916 assert(text || start >= end);
    -
    4917 interval.end = start;
    -
    4918 if (interval.end < end && text[interval.end] != '"')
    -
    4919 goto error;
    -
    4920 interval.end++;
    - -
    4922 for (;;) {
    -
    4923 assert(text || interval.end >= end);
    -
    4924 if (interval.end < end && text[interval.end]) {
    -
    4925 if (text[interval.end] == '"') {
    - -
    4927 interval.end++;
    -
    4928 break;
    -
    4929 }
    -
    4930 else if (text[interval.end] == '\\') {
    -
    4931 interval.end++;
    -
    4932 if (interval.end < end && text[interval.end]) {
    -
    4933 interval.end++;
    -
    4934 }
    -
    4935 else
    -
    4936 goto error;
    -
    4937 }
    -
    4938 else if (m_chr.match(text, interval.end, end, flags))
    -
    4939 interval.end++;
    -
    4940 else
    -
    4941 goto error;
    -
    4942 }
    -
    4943 else
    -
    4944 goto error;
    -
    4945 }
    -
    4946 interval.start = start;
    -
    4947 return true;
    -
    4948
    -
    4949 error:
    -
    4950 content.start = 1;
    -
    4951 content.end = 0;
    -
    4952 interval.start = (interval.end = start) + 1;
    -
    4953 return false;
    -
    4954 }
    -
    4955
    -
    4956 virtual void invalidate()
    -
    4957 {
    -
    4958 content.start = 1;
    -
    4959 content.end = 0;
    -
    4960 parser::invalidate();
    -
    4961 }
    -
    4962
    -
    4963 public:
    - +
    4906
    +
    + +
    4911 {
    +
    4912 public:
    +
    4913 virtual bool match(
    +
    4914 _In_reads_or_z_(end) const char* text,
    +
    4915 _In_ size_t start = 0,
    +
    4916 _In_ size_t end = (size_t)-1,
    +
    4917 _In_ int flags = match_default)
    +
    4918 {
    +
    4919 assert(text || start >= end);
    +
    4920 this->interval.end = start;
    +
    4921 if (this->interval.end < end && text[this->interval.end] != '"')
    +
    4922 goto error;
    +
    4923 this->interval.end++;
    +
    4924 content.start = this->interval.end;
    +
    4925 for (;;) {
    +
    4926 assert(text || this->interval.end >= end);
    +
    4927 if (this->interval.end < end && text[this->interval.end]) {
    +
    4928 if (text[this->interval.end] == '"') {
    +
    4929 content.end = this->interval.end;
    +
    4930 this->interval.end++;
    +
    4931 break;
    +
    4932 }
    +
    4933 else if (text[this->interval.end] == '\\') {
    +
    4934 this->interval.end++;
    +
    4935 if (this->interval.end < end && text[this->interval.end]) {
    +
    4936 this->interval.end++;
    +
    4937 }
    +
    4938 else
    +
    4939 goto error;
    +
    4940 }
    +
    4941 else if (m_chr.match(text, this->interval.end, end, flags))
    +
    4942 this->interval.end++;
    +
    4943 else
    +
    4944 goto error;
    +
    4945 }
    +
    4946 else
    +
    4947 goto error;
    +
    4948 }
    +
    4949 this->interval.start = start;
    +
    4950 return true;
    +
    4951
    +
    4952 error:
    +
    4953 content.start = 1;
    +
    4954 content.end = 0;
    +
    4955 this->interval.start = (this->interval.end = start) + 1;
    +
    4956 return false;
    +
    4957 }
    +
    4958
    +
    4959 virtual void invalidate()
    +
    4960 {
    +
    4961 content.start = 1;
    +
    4962 content.end = 0;
    +
    4963 parser::invalidate();
    +
    4964 }
    4965
    -
    4966 protected:
    -
    4967 http_text_char m_chr;
    -
    4968 };
    +
    4966 public:
    + +
    4968
    +
    4969 protected:
    +
    4970 http_text_char m_chr;
    +
    4971 };
    -
    4969
    -
    -
    4973 class http_value : public parser
    -
    4974 {
    -
    4975 public:
    -
    4976 virtual bool match(
    -
    4977 _In_reads_or_z_(end) const char* text,
    -
    4978 _In_ size_t start = 0,
    -
    4979 _In_ size_t end = (size_t)-1,
    -
    4980 _In_ int flags = match_default)
    -
    4981 {
    -
    4982 assert(text || start >= end);
    -
    4983 interval.end = start;
    -
    4984 if (string.match(text, interval.end, end, flags)) {
    -
    4985 token.invalidate();
    -
    4986 interval.end = string.interval.end;
    -
    4987 interval.start = start;
    -
    4988 return true;
    -
    4989 }
    -
    4990 else if (token.match(text, interval.end, end, flags)) {
    -
    4991 string.invalidate();
    - -
    4993 interval.start = start;
    -
    4994 return true;
    -
    4995 }
    -
    4996 else {
    -
    4997 interval.start = (interval.end = start) + 1;
    -
    4998 return false;
    -
    4999 }
    -
    5000 }
    -
    5001
    -
    5002 virtual void invalidate()
    -
    5003 {
    -
    5004 string.invalidate();
    -
    5005 token.invalidate();
    -
    5006 parser::invalidate();
    -
    5007 }
    -
    5008
    -
    5009 public:
    - - -
    5012 };
    +
    4972
    +
    +
    4976 class http_value : public parser
    +
    4977 {
    +
    4978 public:
    +
    4979 virtual bool match(
    +
    4980 _In_reads_or_z_(end) const char* text,
    +
    4981 _In_ size_t start = 0,
    +
    4982 _In_ size_t end = (size_t)-1,
    +
    4983 _In_ int flags = match_default)
    +
    4984 {
    +
    4985 assert(text || start >= end);
    +
    4986 this->interval.end = start;
    +
    4987 if (string.match(text, this->interval.end, end, flags)) {
    +
    4988 token.invalidate();
    +
    4989 this->interval.end = string.interval.end;
    +
    4990 this->interval.start = start;
    +
    4991 return true;
    +
    4992 }
    +
    4993 else if (token.match(text, this->interval.end, end, flags)) {
    +
    4994 string.invalidate();
    +
    4995 this->interval.end = token.interval.end;
    +
    4996 this->interval.start = start;
    +
    4997 return true;
    +
    4998 }
    +
    4999 else {
    +
    5000 this->interval.start = (this->interval.end = start) + 1;
    +
    5001 return false;
    +
    5002 }
    +
    5003 }
    +
    5004
    +
    5005 virtual void invalidate()
    +
    5006 {
    +
    5007 string.invalidate();
    +
    5008 token.invalidate();
    +
    5009 parser::invalidate();
    +
    5010 }
    +
    5011
    +
    5012 public:
    + + +
    5015 };
    -
    5013
    -
    -
    5017 class http_parameter : public parser
    -
    5018 {
    -
    5019 public:
    -
    5020 virtual bool match(
    -
    5021 _In_reads_or_z_(end) const char* text,
    -
    5022 _In_ size_t start = 0,
    -
    5023 _In_ size_t end = (size_t)-1,
    -
    5024 _In_ int flags = match_default)
    -
    5025 {
    -
    5026 assert(text || start >= end);
    -
    5027 interval.end = start;
    -
    5028 if (name.match(text, interval.end, end, flags))
    - -
    5030 else
    -
    5031 goto error;
    -
    5032 while (m_space.match(text, interval.end, end, flags))
    -
    5033 interval.end = m_space.interval.end;
    -
    5034 assert(text || interval.end >= end);
    -
    5035 if (interval.end < end && text[interval.end] == '=')
    -
    5036 interval.end++;
    -
    5037 else
    -
    5038 while (m_space.match(text, interval.end, end, flags))
    -
    5039 interval.end = m_space.interval.end;
    -
    5040 if (value.match(text, interval.end, end, flags))
    - -
    5042 else
    -
    5043 goto error;
    -
    5044 interval.start = start;
    -
    5045 return true;
    -
    5046
    -
    5047 error:
    -
    5048 name.invalidate();
    -
    5049 value.invalidate();
    -
    5050 interval.start = (interval.end = start) + 1;
    -
    5051 return false;
    -
    5052 }
    -
    5053
    -
    5054 virtual void invalidate()
    -
    5055 {
    -
    5056 name.invalidate();
    -
    5057 value.invalidate();
    -
    5058 parser::invalidate();
    -
    5059 }
    -
    5060
    -
    5061 public:
    - - -
    5064
    -
    5065 protected:
    -
    5066 http_space m_space;
    -
    5067 };
    +
    5016
    +
    +
    5020 class http_parameter : public parser
    +
    5021 {
    +
    5022 public:
    +
    5023 virtual bool match(
    +
    5024 _In_reads_or_z_(end) const char* text,
    +
    5025 _In_ size_t start = 0,
    +
    5026 _In_ size_t end = (size_t)-1,
    +
    5027 _In_ int flags = match_default)
    +
    5028 {
    +
    5029 assert(text || start >= end);
    +
    5030 this->interval.end = start;
    +
    5031 if (name.match(text, this->interval.end, end, flags))
    +
    5032 this->interval.end = name.interval.end;
    +
    5033 else
    +
    5034 goto error;
    +
    5035 while (m_space.match(text, this->interval.end, end, flags))
    +
    5036 this->interval.end = m_space.interval.end;
    +
    5037 assert(text || this->interval.end >= end);
    +
    5038 if (this->interval.end < end && text[this->interval.end] == '=')
    +
    5039 this->interval.end++;
    +
    5040 else
    +
    5041 while (m_space.match(text, this->interval.end, end, flags))
    +
    5042 this->interval.end = m_space.interval.end;
    +
    5043 if (value.match(text, this->interval.end, end, flags))
    +
    5044 this->interval.end = value.interval.end;
    +
    5045 else
    +
    5046 goto error;
    +
    5047 this->interval.start = start;
    +
    5048 return true;
    +
    5049
    +
    5050 error:
    +
    5051 name.invalidate();
    +
    5052 value.invalidate();
    +
    5053 this->interval.start = (this->interval.end = start) + 1;
    +
    5054 return false;
    +
    5055 }
    +
    5056
    +
    5057 virtual void invalidate()
    +
    5058 {
    +
    5059 name.invalidate();
    +
    5060 value.invalidate();
    +
    5061 parser::invalidate();
    +
    5062 }
    +
    5063
    +
    5064 public:
    + + +
    5067
    +
    5068 protected:
    +
    5069 http_space m_space;
    +
    5070 };
    -
    5068
    -
    -
    5072 class http_any_type : public parser
    -
    5073 {
    -
    5074 public:
    -
    5075 virtual bool match(
    -
    5076 _In_reads_or_z_(end) const char* text,
    -
    5077 _In_ size_t start = 0,
    -
    5078 _In_ size_t end = (size_t)-1,
    -
    5079 _In_ int flags = match_default)
    -
    5080 {
    -
    5081 assert(text || start >= end);
    -
    5082 if (start + 2 < end &&
    -
    5083 text[start] == '*' &&
    -
    5084 text[start + 1] == '/' &&
    -
    5085 text[start + 2] == '*')
    -
    5086 {
    -
    5087 interval.end = (interval.start = start) + 3;
    -
    5088 return true;
    -
    5089 }
    -
    5090 else if (start < end && text[start] == '*') {
    -
    5091 interval.end = (interval.start = start) + 1;
    -
    5092 return true;
    -
    5093 }
    -
    5094 else {
    -
    5095 interval.start = (interval.end = start) + 1;
    -
    5096 return false;
    -
    5097 }
    -
    5098 }
    -
    5099 };
    +
    5071
    +
    +
    5075 class http_any_type : public parser
    +
    5076 {
    +
    5077 public:
    +
    5078 virtual bool match(
    +
    5079 _In_reads_or_z_(end) const char* text,
    +
    5080 _In_ size_t start = 0,
    +
    5081 _In_ size_t end = (size_t)-1,
    +
    5082 _In_ int flags = match_default)
    +
    5083 {
    +
    5084 assert(text || start >= end);
    +
    5085 if (start + 2 < end &&
    +
    5086 text[start] == '*' &&
    +
    5087 text[start + 1] == '/' &&
    +
    5088 text[start + 2] == '*')
    +
    5089 {
    +
    5090 this->interval.end = (this->interval.start = start) + 3;
    +
    5091 return true;
    +
    5092 }
    +
    5093 else if (start < end && text[start] == '*') {
    +
    5094 this->interval.end = (this->interval.start = start) + 1;
    +
    5095 return true;
    +
    5096 }
    +
    5097 else {
    +
    5098 this->interval.start = (this->interval.end = start) + 1;
    +
    5099 return false;
    +
    5100 }
    +
    5101 }
    +
    5102 };
    -
    5100
    -
    - -
    5105 {
    -
    5106 public:
    -
    5107 virtual bool match(
    -
    5108 _In_reads_or_z_(end) const char* text,
    -
    5109 _In_ size_t start = 0,
    -
    5110 _In_ size_t end = (size_t)-1,
    -
    5111 _In_ int flags = match_default)
    -
    5112 {
    -
    5113 assert(text || start >= end);
    -
    5114 interval.end = start;
    -
    5115 if (type.match(text, interval.end, end, flags))
    -
    5116 interval.end = type.interval.end;
    -
    5117 else
    -
    5118 goto error;
    -
    5119 while (m_space.match(text, interval.end, end, flags))
    -
    5120 interval.end = m_space.interval.end;
    -
    5121 if (interval.end < end && text[interval.end] == '/')
    -
    5122 interval.end++;
    -
    5123 else
    -
    5124 goto error;
    -
    5125 while (m_space.match(text, interval.end, end, flags))
    -
    5126 interval.end = m_space.interval.end;
    -
    5127 if (subtype.match(text, interval.end, end, flags))
    -
    5128 interval.end = subtype.interval.end;
    -
    5129 else
    -
    5130 goto error;
    -
    5131 interval.start = start;
    -
    5132 return true;
    -
    5133
    -
    5134 error:
    -
    5135 type.invalidate();
    -
    5136 subtype.invalidate();
    -
    5137 interval.start = (interval.end = start) + 1;
    -
    5138 return false;
    -
    5139 }
    -
    5140
    -
    5141 virtual void invalidate()
    -
    5142 {
    -
    5143 type.invalidate();
    -
    5144 subtype.invalidate();
    -
    5145 parser::invalidate();
    -
    5146 }
    -
    5147
    -
    5148 public:
    -
    5149 http_token type;
    -
    5150 http_token subtype;
    -
    5151
    -
    5152 protected:
    -
    5153 http_space m_space;
    -
    5154 };
    +
    5103
    +
    + +
    5108 {
    +
    5109 public:
    +
    5110 virtual bool match(
    +
    5111 _In_reads_or_z_(end) const char* text,
    +
    5112 _In_ size_t start = 0,
    +
    5113 _In_ size_t end = (size_t)-1,
    +
    5114 _In_ int flags = match_default)
    +
    5115 {
    +
    5116 assert(text || start >= end);
    +
    5117 this->interval.end = start;
    +
    5118 if (type.match(text, this->interval.end, end, flags))
    +
    5119 this->interval.end = type.interval.end;
    +
    5120 else
    +
    5121 goto error;
    +
    5122 while (m_space.match(text, this->interval.end, end, flags))
    +
    5123 this->interval.end = m_space.interval.end;
    +
    5124 if (this->interval.end < end && text[this->interval.end] == '/')
    +
    5125 this->interval.end++;
    +
    5126 else
    +
    5127 goto error;
    +
    5128 while (m_space.match(text, this->interval.end, end, flags))
    +
    5129 this->interval.end = m_space.interval.end;
    +
    5130 if (subtype.match(text, this->interval.end, end, flags))
    +
    5131 this->interval.end = subtype.interval.end;
    +
    5132 else
    +
    5133 goto error;
    +
    5134 this->interval.start = start;
    +
    5135 return true;
    +
    5136
    +
    5137 error:
    +
    5138 type.invalidate();
    +
    5139 subtype.invalidate();
    +
    5140 this->interval.start = (this->interval.end = start) + 1;
    +
    5141 return false;
    +
    5142 }
    +
    5143
    +
    5144 virtual void invalidate()
    +
    5145 {
    +
    5146 type.invalidate();
    +
    5147 subtype.invalidate();
    +
    5148 parser::invalidate();
    +
    5149 }
    +
    5150
    +
    5151 public:
    +
    5152 http_token type;
    +
    5153 http_token subtype;
    +
    5154
    +
    5155 protected:
    +
    5156 http_space m_space;
    +
    5157 };
    -
    5155
    -
    - -
    5160 {
    -
    5161 public:
    -
    5162 virtual bool match(
    -
    5163 _In_reads_or_z_(end) const char* text,
    -
    5164 _In_ size_t start = 0,
    -
    5165 _In_ size_t end = (size_t)-1,
    -
    5166 _In_ int flags = match_default)
    -
    5167 {
    -
    5168 assert(text || start >= end);
    -
    5169 if (!http_media_range::match(text, start, end, flags))
    -
    5170 goto error;
    -
    5171 params.clear();
    -
    5172 for (;;) {
    -
    5173 if (interval.end < end && text[interval.end]) {
    -
    5174 if (m_space.match(text, interval.end, end, flags))
    -
    5175 interval.end = m_space.interval.end;
    -
    5176 else if (text[interval.end] == ';') {
    -
    5177 interval.end++;
    -
    5178 while (m_space.match(text, interval.end, end, flags))
    -
    5179 interval.end = m_space.interval.end;
    - -
    5181 if (param.match(text, interval.end, end, flags)) {
    - -
    5183 params.push_back(std::move(param));
    -
    5184 }
    -
    5185 else
    -
    5186 break;
    -
    5187 }
    -
    5188 else
    -
    5189 break;
    -
    5190 }
    -
    5191 else
    -
    5192 break;
    -
    5193 }
    -
    5194 interval.end = params.empty() ? subtype.interval.end : params.back().interval.end;
    -
    5195 return true;
    -
    5196
    -
    5197 error:
    -
    5198 http_media_range::invalidate();
    -
    5199 params.clear();
    -
    5200 interval.start = (interval.end = start) + 1;
    -
    5201 return false;
    -
    5202 }
    -
    5203
    -
    5204 virtual void invalidate()
    -
    5205 {
    -
    5206 params.clear();
    -
    5207 http_media_range::invalidate();
    -
    5208 }
    -
    5209
    -
    5210 public:
    -
    5211 std::list<http_parameter> params;
    -
    5212 };
    +
    5158
    +
    + +
    5163 {
    +
    5164 public:
    +
    5165 virtual bool match(
    +
    5166 _In_reads_or_z_(end) const char* text,
    +
    5167 _In_ size_t start = 0,
    +
    5168 _In_ size_t end = (size_t)-1,
    +
    5169 _In_ int flags = match_default)
    +
    5170 {
    +
    5171 assert(text || start >= end);
    +
    5172 if (!http_media_range::match(text, start, end, flags))
    +
    5173 goto error;
    +
    5174 params.clear();
    +
    5175 for (;;) {
    +
    5176 if (this->interval.end < end && text[this->interval.end]) {
    +
    5177 if (m_space.match(text, this->interval.end, end, flags))
    +
    5178 this->interval.end = m_space.interval.end;
    +
    5179 else if (text[this->interval.end] == ';') {
    +
    5180 this->interval.end++;
    +
    5181 while (m_space.match(text, this->interval.end, end, flags))
    +
    5182 this->interval.end = m_space.interval.end;
    + +
    5184 if (param.match(text, this->interval.end, end, flags)) {
    +
    5185 this->interval.end = param.interval.end;
    +
    5186 params.push_back(std::move(param));
    +
    5187 }
    +
    5188 else
    +
    5189 break;
    +
    5190 }
    +
    5191 else
    +
    5192 break;
    +
    5193 }
    +
    5194 else
    +
    5195 break;
    +
    5196 }
    +
    5197 this->interval.end = params.empty() ? subtype.interval.end : params.back().interval.end;
    +
    5198 return true;
    +
    5199
    +
    5200 error:
    +
    5201 http_media_range::invalidate();
    +
    5202 params.clear();
    +
    5203 this->interval.start = (this->interval.end = start) + 1;
    +
    5204 return false;
    +
    5205 }
    +
    5206
    +
    5207 virtual void invalidate()
    +
    5208 {
    +
    5209 params.clear();
    +
    5210 http_media_range::invalidate();
    +
    5211 }
    +
    5212
    +
    5213 public:
    +
    5214 std::list<http_parameter> params;
    +
    5215 };
    -
    5213
    -
    - -
    5218 {
    -
    5219 public:
    -
    5220 virtual bool match(
    -
    5221 _In_reads_or_z_(end) const char* text,
    -
    5222 _In_ size_t start = 0,
    -
    5223 _In_ size_t end = (size_t)-1,
    -
    5224 _In_ int flags = match_default)
    -
    5225 {
    -
    5226 assert(text || start >= end);
    -
    5227 interval.end = start;
    -
    5228 for (;;) {
    -
    5229 if (interval.end < end && text[interval.end]) {
    -
    5230 if ((unsigned int)text[interval.end] < 0x20 ||
    -
    5231 (unsigned int)text[interval.end] == 0x7f ||
    -
    5232 text[interval.end] == ':' ||
    -
    5233 text[interval.end] == '/' ||
    - -
    5235 break;
    -
    5236 else
    -
    5237 interval.end++;
    -
    5238 }
    -
    5239 else
    -
    5240 break;
    -
    5241 }
    -
    5242 if (start < interval.end) {
    -
    5243 interval.start = start;
    -
    5244 return true;
    -
    5245 }
    -
    5246 interval.start = (interval.end = start) + 1;
    -
    5247 return false;
    -
    5248 }
    -
    5249 };
    +
    5216
    +
    + +
    5221 {
    +
    5222 public:
    +
    5223 virtual bool match(
    +
    5224 _In_reads_or_z_(end) const char* text,
    +
    5225 _In_ size_t start = 0,
    +
    5226 _In_ size_t end = (size_t)-1,
    +
    5227 _In_ int flags = match_default)
    +
    5228 {
    +
    5229 assert(text || start >= end);
    +
    5230 this->interval.end = start;
    +
    5231 for (;;) {
    +
    5232 if (this->interval.end < end && text[this->interval.end]) {
    +
    5233 if ((unsigned int)text[this->interval.end] < 0x20 ||
    +
    5234 (unsigned int)text[this->interval.end] == 0x7f ||
    +
    5235 text[this->interval.end] == ':' ||
    +
    5236 text[this->interval.end] == '/' ||
    +
    5237 isspace(text[this->interval.end]))
    +
    5238 break;
    +
    5239 else
    +
    5240 this->interval.end++;
    +
    5241 }
    +
    5242 else
    +
    5243 break;
    +
    5244 }
    + +
    5246 this->interval.start = start;
    +
    5247 return true;
    +
    5248 }
    +
    5249 this->interval.start = (this->interval.end = start) + 1;
    +
    5250 return false;
    +
    5251 }
    +
    5252 };
    -
    5250
    -
    -
    5254 class http_url_port : public parser
    -
    5255 {
    -
    5256 public:
    -
    5257 http_url_port(_In_ const std::locale& locale = std::locale()) :
    -
    5258 parser(locale),
    -
    5259 value(0)
    -
    5260 {}
    -
    5261
    -
    5262 virtual bool match(
    -
    5263 _In_reads_or_z_(end) const char* text,
    -
    5264 _In_ size_t start = 0,
    -
    5265 _In_ size_t end = (size_t)-1,
    -
    5266 _In_ int flags = match_default)
    -
    5267 {
    -
    5268 assert(text || start >= end);
    -
    5269 value = 0;
    -
    5270 interval.end = start;
    -
    5271 for (;;) {
    -
    5272 if (interval.end < end && text[interval.end]) {
    -
    5273 if ('0' <= text[interval.end] && text[interval.end] <= '9') {
    -
    5274 size_t _value = (size_t)value * 10 + text[interval.end] - '0';
    -
    5275 if (_value > (uint16_t)-1) {
    -
    5276 value = 0;
    -
    5277 interval.start = (interval.end = start) + 1;
    -
    5278 return false;
    -
    5279 }
    -
    5280 value = (uint16_t)_value;
    -
    5281 interval.end++;
    -
    5282 }
    -
    5283 else
    -
    5284 break;
    -
    5285 }
    -
    5286 else
    -
    5287 break;
    -
    5288 }
    -
    5289 if (start < interval.end) {
    -
    5290 interval.start = start;
    -
    5291 return true;
    -
    5292 }
    -
    5293 interval.start = (interval.end = start) + 1;
    -
    5294 return false;
    -
    5295 }
    -
    5296
    -
    5297 virtual void invalidate()
    -
    5298 {
    -
    5299 value = 0;
    -
    5300 parser::invalidate();
    -
    5301 }
    -
    5302
    -
    5303 public:
    -
    5304 uint16_t value;
    -
    5305 };
    +
    5253
    +
    +
    5257 class http_url_port : public parser
    +
    5258 {
    +
    5259 public:
    +
    5260 http_url_port(_In_ const std::locale& locale = std::locale()) :
    +
    5261 parser(locale),
    +
    5262 value(0)
    +
    5263 {}
    +
    5264
    +
    5265 virtual bool match(
    +
    5266 _In_reads_or_z_(end) const char* text,
    +
    5267 _In_ size_t start = 0,
    +
    5268 _In_ size_t end = (size_t)-1,
    +
    5269 _In_ int flags = match_default)
    +
    5270 {
    +
    5271 assert(text || start >= end);
    +
    5272 value = 0;
    +
    5273 this->interval.end = start;
    +
    5274 for (;;) {
    +
    5275 if (this->interval.end < end && text[this->interval.end]) {
    +
    5276 if ('0' <= text[this->interval.end] && text[this->interval.end] <= '9') {
    +
    5277 size_t _value = (size_t)value * 10 + text[this->interval.end] - '0';
    +
    5278 if (_value > (uint16_t)-1) {
    +
    5279 value = 0;
    +
    5280 this->interval.start = (this->interval.end = start) + 1;
    +
    5281 return false;
    +
    5282 }
    +
    5283 value = (uint16_t)_value;
    +
    5284 this->interval.end++;
    +
    5285 }
    +
    5286 else
    +
    5287 break;
    +
    5288 }
    +
    5289 else
    +
    5290 break;
    +
    5291 }
    + +
    5293 this->interval.start = start;
    +
    5294 return true;
    +
    5295 }
    +
    5296 this->interval.start = (this->interval.end = start) + 1;
    +
    5297 return false;
    +
    5298 }
    +
    5299
    +
    5300 virtual void invalidate()
    +
    5301 {
    +
    5302 value = 0;
    +
    5303 parser::invalidate();
    +
    5304 }
    +
    5305
    +
    5306 public:
    +
    5307 uint16_t value;
    +
    5308 };
    -
    5306
    -
    - -
    5311 {
    -
    5312 public:
    -
    5313 virtual bool match(
    -
    5314 _In_reads_or_z_(end) const char* text,
    -
    5315 _In_ size_t start = 0,
    -
    5316 _In_ size_t end = (size_t)-1,
    -
    5317 _In_ int flags = match_default)
    -
    5318 {
    -
    5319 assert(text || start >= end);
    -
    5320 interval.end = start;
    -
    5321 for (;;) {
    -
    5322 if (interval.end < end && text[interval.end]) {
    -
    5323 if ((unsigned int)text[interval.end] < 0x20 ||
    -
    5324 (unsigned int)text[interval.end] == 0x7f ||
    -
    5325 text[interval.end] == '?' ||
    -
    5326 text[interval.end] == '/' ||
    - -
    5328 break;
    -
    5329 else
    -
    5330 interval.end++;
    -
    5331 }
    -
    5332 else
    -
    5333 break;
    -
    5334 }
    -
    5335 interval.start = start;
    -
    5336 return true;
    -
    5337 }
    -
    5338 };
    +
    5309
    +
    + +
    5314 {
    +
    5315 public:
    +
    5316 virtual bool match(
    +
    5317 _In_reads_or_z_(end) const char* text,
    +
    5318 _In_ size_t start = 0,
    +
    5319 _In_ size_t end = (size_t)-1,
    +
    5320 _In_ int flags = match_default)
    +
    5321 {
    +
    5322 assert(text || start >= end);
    +
    5323 this->interval.end = start;
    +
    5324 for (;;) {
    +
    5325 if (this->interval.end < end && text[this->interval.end]) {
    +
    5326 if ((unsigned int)text[this->interval.end] < 0x20 ||
    +
    5327 (unsigned int)text[this->interval.end] == 0x7f ||
    +
    5328 text[this->interval.end] == '?' ||
    +
    5329 text[this->interval.end] == '/' ||
    +
    5330 isspace(text[this->interval.end]))
    +
    5331 break;
    +
    5332 else
    +
    5333 this->interval.end++;
    +
    5334 }
    +
    5335 else
    +
    5336 break;
    +
    5337 }
    +
    5338 this->interval.start = start;
    +
    5339 return true;
    +
    5340 }
    +
    5341 };
    -
    5339
    -
    -
    5343 class http_url_path : public parser
    -
    5344 {
    -
    5345 public:
    -
    5346 virtual bool match(
    -
    5347 _In_reads_or_z_(end) const char* text,
    -
    5348 _In_ size_t start = 0,
    -
    5349 _In_ size_t end = (size_t)-1,
    -
    5350 _In_ int flags = match_default)
    -
    5351 {
    -
    5352 assert(text || start >= end);
    - -
    5354 interval.end = start;
    -
    5355 segments.clear();
    -
    5356 assert(text || interval.end >= end);
    -
    5357 if (interval.end < end && text[interval.end] != '/')
    -
    5358 goto error;
    -
    5359 interval.end++;
    -
    5360 s.match(text, interval.end, end, flags);
    -
    5361 segments.push_back(s);
    - -
    5363 for (;;) {
    -
    5364 if (interval.end < end && text[interval.end]) {
    -
    5365 if (text[interval.end] == '/') {
    -
    5366 interval.end++;
    -
    5367 s.match(text, interval.end, end, flags);
    -
    5368 segments.push_back(s);
    - -
    5370 }
    -
    5371 else
    -
    5372 break;
    -
    5373 }
    -
    5374 else
    -
    5375 break;
    -
    5376 }
    -
    5377 interval.start = start;
    -
    5378 return true;
    -
    5379
    -
    5380 error:
    -
    5381 segments.clear();
    -
    5382 interval.start = (interval.end = start) + 1;
    -
    5383 return false;
    -
    5384 }
    -
    5385
    -
    5386 virtual void invalidate()
    -
    5387 {
    -
    5388 segments.clear();
    -
    5389 parser::invalidate();
    -
    5390 }
    -
    5391
    -
    5392 public:
    -
    5393 std::vector<http_url_path_segment> segments;
    -
    5394 };
    +
    5342
    +
    +
    5346 class http_url_path : public parser
    +
    5347 {
    +
    5348 public:
    +
    5349 virtual bool match(
    +
    5350 _In_reads_or_z_(end) const char* text,
    +
    5351 _In_ size_t start = 0,
    +
    5352 _In_ size_t end = (size_t)-1,
    +
    5353 _In_ int flags = match_default)
    +
    5354 {
    +
    5355 assert(text || start >= end);
    + +
    5357 this->interval.end = start;
    +
    5358 segments.clear();
    +
    5359 assert(text || this->interval.end >= end);
    +
    5360 if (this->interval.end < end && text[this->interval.end] != '/')
    +
    5361 goto error;
    +
    5362 this->interval.end++;
    +
    5363 s.match(text, this->interval.end, end, flags);
    +
    5364 segments.push_back(s);
    +
    5365 this->interval.end = s.interval.end;
    +
    5366 for (;;) {
    +
    5367 if (this->interval.end < end && text[this->interval.end]) {
    +
    5368 if (text[this->interval.end] == '/') {
    +
    5369 this->interval.end++;
    +
    5370 s.match(text, this->interval.end, end, flags);
    +
    5371 segments.push_back(s);
    +
    5372 this->interval.end = s.interval.end;
    +
    5373 }
    +
    5374 else
    +
    5375 break;
    +
    5376 }
    +
    5377 else
    +
    5378 break;
    +
    5379 }
    +
    5380 this->interval.start = start;
    +
    5381 return true;
    +
    5382
    +
    5383 error:
    +
    5384 segments.clear();
    +
    5385 this->interval.start = (this->interval.end = start) + 1;
    +
    5386 return false;
    +
    5387 }
    +
    5388
    +
    5389 virtual void invalidate()
    +
    5390 {
    +
    5391 segments.clear();
    +
    5392 parser::invalidate();
    +
    5393 }
    +
    5394
    +
    5395 public:
    +
    5396 std::vector<http_url_path_segment> segments;
    +
    5397 };
    -
    5395
    -
    - -
    5400 {
    -
    5401 public:
    -
    5402 virtual bool match(
    -
    5403 _In_reads_or_z_(end) const char* text,
    -
    5404 _In_ size_t start = 0,
    -
    5405 _In_ size_t end = (size_t)-1,
    -
    5406 _In_ int flags = match_default)
    -
    5407 {
    -
    5408 assert(text || start >= end);
    -
    5409 interval.end = start;
    -
    5410 name.start = interval.end;
    -
    5411 for (;;) {
    -
    5412 if (interval.end < end && text[interval.end]) {
    -
    5413 if ((unsigned int)text[interval.end] < 0x20 ||
    -
    5414 (unsigned int)text[interval.end] == 0x7f ||
    -
    5415 text[interval.end] == '&' ||
    -
    5416 text[interval.end] == '=' ||
    - -
    5418 break;
    -
    5419 else
    -
    5420 interval.end++;
    -
    5421 }
    -
    5422 else
    -
    5423 break;
    -
    5424 }
    -
    5425 if (start < interval.end)
    -
    5426 name.end = interval.end;
    -
    5427 else
    -
    5428 goto error;
    -
    5429 if (text[interval.end] == '=') {
    -
    5430 interval.end++;
    -
    5431 value.start = interval.end;
    -
    5432 for (;;) {
    -
    5433 if (interval.end < end && text[interval.end]) {
    -
    5434 if ((unsigned int)text[interval.end] < 0x20 ||
    -
    5435 (unsigned int)text[interval.end] == 0x7f ||
    -
    5436 text[interval.end] == '&' ||
    - -
    5438 break;
    -
    5439 else
    -
    5440 interval.end++;
    -
    5441 }
    -
    5442 else
    -
    5443 break;
    -
    5444 }
    -
    5445 value.end = interval.end;
    -
    5446 }
    -
    5447 else {
    -
    5448 value.start = 1;
    -
    5449 value.end = 0;
    -
    5450 }
    -
    5451 interval.start = start;
    -
    5452 return true;
    -
    5453
    -
    5454 error:
    -
    5455 name.start = 1;
    -
    5456 name.end = 0;
    -
    5457 value.start = 1;
    -
    5458 value.end = 0;
    -
    5459 interval.start = (interval.end = start) + 1;
    -
    5460 return false;
    -
    5461 }
    -
    5462
    -
    5463 virtual void invalidate()
    -
    5464 {
    -
    5465 name.start = 1;
    -
    5466 name.end = 0;
    -
    5467 value.start = 1;
    -
    5468 value.end = 0;
    -
    5469 parser::invalidate();
    -
    5470 }
    -
    5471
    -
    5472 public:
    - - -
    5475 };
    +
    5398
    +
    + +
    5403 {
    +
    5404 public:
    +
    5405 virtual bool match(
    +
    5406 _In_reads_or_z_(end) const char* text,
    +
    5407 _In_ size_t start = 0,
    +
    5408 _In_ size_t end = (size_t)-1,
    +
    5409 _In_ int flags = match_default)
    +
    5410 {
    +
    5411 assert(text || start >= end);
    +
    5412 this->interval.end = start;
    +
    5413 name.start = this->interval.end;
    +
    5414 for (;;) {
    +
    5415 if (this->interval.end < end && text[this->interval.end]) {
    +
    5416 if ((unsigned int)text[this->interval.end] < 0x20 ||
    +
    5417 (unsigned int)text[this->interval.end] == 0x7f ||
    +
    5418 text[this->interval.end] == '&' ||
    +
    5419 text[this->interval.end] == '=' ||
    +
    5420 isspace(text[this->interval.end]))
    +
    5421 break;
    +
    5422 else
    +
    5423 this->interval.end++;
    +
    5424 }
    +
    5425 else
    +
    5426 break;
    +
    5427 }
    + +
    5429 name.end = this->interval.end;
    +
    5430 else
    +
    5431 goto error;
    +
    5432 if (text[this->interval.end] == '=') {
    +
    5433 this->interval.end++;
    +
    5434 value.start = this->interval.end;
    +
    5435 for (;;) {
    +
    5436 if (this->interval.end < end && text[this->interval.end]) {
    +
    5437 if ((unsigned int)text[this->interval.end] < 0x20 ||
    +
    5438 (unsigned int)text[this->interval.end] == 0x7f ||
    +
    5439 text[this->interval.end] == '&' ||
    +
    5440 isspace(text[this->interval.end]))
    +
    5441 break;
    +
    5442 else
    +
    5443 this->interval.end++;
    +
    5444 }
    +
    5445 else
    +
    5446 break;
    +
    5447 }
    +
    5448 value.end = this->interval.end;
    +
    5449 }
    +
    5450 else {
    +
    5451 value.start = 1;
    +
    5452 value.end = 0;
    +
    5453 }
    +
    5454 this->interval.start = start;
    +
    5455 return true;
    +
    5456
    +
    5457 error:
    +
    5458 name.start = 1;
    +
    5459 name.end = 0;
    +
    5460 value.start = 1;
    +
    5461 value.end = 0;
    +
    5462 this->interval.start = (this->interval.end = start) + 1;
    +
    5463 return false;
    +
    5464 }
    +
    5465
    +
    5466 virtual void invalidate()
    +
    5467 {
    +
    5468 name.start = 1;
    +
    5469 name.end = 0;
    +
    5470 value.start = 1;
    +
    5471 value.end = 0;
    +
    5472 parser::invalidate();
    +
    5473 }
    +
    5474
    +
    5475 public:
    + + +
    5478 };
    -
    5476
    -
    -
    5480 class http_url : public parser
    -
    5481 {
    -
    5482 public:
    -
    5483 http_url(_In_ const std::locale& locale = std::locale()) :
    -
    5484 parser(locale),
    -
    5485 port(locale)
    -
    5486 {}
    -
    5487
    -
    5488 virtual bool match(
    -
    5489 _In_reads_or_z_(end) const char* text,
    -
    5490 _In_ size_t start = 0,
    -
    5491 _In_ size_t end = (size_t)-1,
    -
    5492 _In_ int flags = match_default)
    -
    5493 {
    -
    5494 assert(text || start >= end);
    -
    5495 interval.end = start;
    -
    5496
    -
    5497 if (interval.end + 7 <= end && stdex::strnicmp(text + interval.end, 7, "http://", (size_t)-1, m_locale) == 0) {
    -
    5498 interval.end += 7;
    -
    5499 if (server.match(text, interval.end, end, flags))
    -
    5500 interval.end = server.interval.end;
    -
    5501 else
    -
    5502 goto error;
    -
    5503 if (interval.end < end && text[interval.end] == ':') {
    -
    5504 interval.end++;
    -
    5505 if (port.match(text, interval.end, end, flags))
    -
    5506 interval.end = port.interval.end;
    -
    5507 }
    -
    5508 else {
    -
    5509 port.invalidate();
    -
    5510 port.value = 80;
    -
    5511 }
    -
    5512 }
    -
    5513 else {
    -
    5514 server.invalidate();
    -
    5515 port.invalidate();
    -
    5516 port.value = 80;
    -
    5517 }
    -
    5518
    -
    5519 if (path.match(text, interval.end, end, flags))
    -
    5520 interval.end = path.interval.end;
    -
    5521 else
    -
    5522 goto error;
    -
    5523
    -
    5524 params.clear();
    -
    5525
    -
    5526 if (interval.end < end && text[interval.end] == '?') {
    -
    5527 interval.end++;
    -
    5528 for (;;) {
    -
    5529 if (interval.end < end && text[interval.end]) {
    -
    5530 if ((unsigned int)text[interval.end] < 0x20 ||
    -
    5531 (unsigned int)text[interval.end] == 0x7f ||
    - -
    5533 break;
    -
    5534 else if (text[interval.end] == '&')
    -
    5535 interval.end++;
    -
    5536 else {
    - -
    5538 if (param.match(text, interval.end, end, flags)) {
    - -
    5540 params.push_back(std::move(param));
    -
    5541 }
    -
    5542 else
    -
    5543 break;
    -
    5544 }
    -
    5545 }
    -
    5546 else
    -
    5547 break;
    -
    5548 }
    -
    5549 }
    -
    5550
    -
    5551 interval.start = start;
    -
    5552 return true;
    +
    5479
    +
    +
    5483 class http_url : public parser
    +
    5484 {
    +
    5485 public:
    +
    5486 http_url(_In_ const std::locale& locale = std::locale()) :
    +
    5487 parser(locale),
    +
    5488 port(locale)
    +
    5489 {}
    +
    5490
    +
    5491 virtual bool match(
    +
    5492 _In_reads_or_z_(end) const char* text,
    +
    5493 _In_ size_t start = 0,
    +
    5494 _In_ size_t end = (size_t)-1,
    +
    5495 _In_ int flags = match_default)
    +
    5496 {
    +
    5497 assert(text || start >= end);
    +
    5498 this->interval.end = start;
    +
    5499
    +
    5500 if (this->interval.end + 7 <= end && stdex::strnicmp(text + this->interval.end, 7, "http://", (size_t)-1, m_locale) == 0) {
    +
    5501 this->interval.end += 7;
    +
    5502 if (server.match(text, this->interval.end, end, flags))
    +
    5503 this->interval.end = server.interval.end;
    +
    5504 else
    +
    5505 goto error;
    +
    5506 if (this->interval.end < end && text[this->interval.end] == ':') {
    +
    5507 this->interval.end++;
    +
    5508 if (port.match(text, this->interval.end, end, flags))
    +
    5509 this->interval.end = port.interval.end;
    +
    5510 }
    +
    5511 else {
    +
    5512 port.invalidate();
    +
    5513 port.value = 80;
    +
    5514 }
    +
    5515 }
    +
    5516 else {
    +
    5517 server.invalidate();
    +
    5518 port.invalidate();
    +
    5519 port.value = 80;
    +
    5520 }
    +
    5521
    +
    5522 if (path.match(text, this->interval.end, end, flags))
    +
    5523 this->interval.end = path.interval.end;
    +
    5524 else
    +
    5525 goto error;
    +
    5526
    +
    5527 params.clear();
    +
    5528
    +
    5529 if (this->interval.end < end && text[this->interval.end] == '?') {
    +
    5530 this->interval.end++;
    +
    5531 for (;;) {
    +
    5532 if (this->interval.end < end && text[this->interval.end]) {
    +
    5533 if ((unsigned int)text[this->interval.end] < 0x20 ||
    +
    5534 (unsigned int)text[this->interval.end] == 0x7f ||
    +
    5535 isspace(text[this->interval.end]))
    +
    5536 break;
    +
    5537 else if (text[this->interval.end] == '&')
    +
    5538 this->interval.end++;
    +
    5539 else {
    + +
    5541 if (param.match(text, this->interval.end, end, flags)) {
    +
    5542 this->interval.end = param.interval.end;
    +
    5543 params.push_back(std::move(param));
    +
    5544 }
    +
    5545 else
    +
    5546 break;
    +
    5547 }
    +
    5548 }
    +
    5549 else
    +
    5550 break;
    +
    5551 }
    +
    5552 }
    5553
    -
    5554 error:
    -
    5555 server.invalidate();
    -
    5556 port.invalidate();
    -
    5557 path.invalidate();
    -
    5558 params.clear();
    -
    5559 interval.start = (interval.end = start) + 1;
    -
    5560 return false;
    -
    5561 }
    -
    5562
    -
    5563 virtual void invalidate()
    -
    5564 {
    -
    5565 server.invalidate();
    -
    5566 port.invalidate();
    -
    5567 path.invalidate();
    -
    5568 params.clear();
    -
    5569 parser::invalidate();
    -
    5570 }
    -
    5571
    -
    5572 public:
    -
    5573 http_url_server server;
    -
    5574 http_url_port port;
    -
    5575 http_url_path path;
    -
    5576 std::list<http_url_parameter> params;
    -
    5577 };
    +
    5554 this->interval.start = start;
    +
    5555 return true;
    +
    5556
    +
    5557 error:
    +
    5558 server.invalidate();
    +
    5559 port.invalidate();
    +
    5560 path.invalidate();
    +
    5561 params.clear();
    +
    5562 this->interval.start = (this->interval.end = start) + 1;
    +
    5563 return false;
    +
    5564 }
    +
    5565
    +
    5566 virtual void invalidate()
    +
    5567 {
    +
    5568 server.invalidate();
    +
    5569 port.invalidate();
    +
    5570 path.invalidate();
    +
    5571 params.clear();
    +
    5572 parser::invalidate();
    +
    5573 }
    +
    5574
    +
    5575 public:
    +
    5576 http_url_server server;
    +
    5577 http_url_port port;
    +
    5578 http_url_path path;
    +
    5579 std::list<http_url_parameter> params;
    +
    5580 };
    -
    5578
    -
    -
    5582 class http_language : public parser
    -
    5583 {
    -
    5584 public:
    -
    5585 virtual bool match(
    -
    5586 _In_reads_or_z_(end) const char* text,
    -
    5587 _In_ size_t start = 0,
    -
    5588 _In_ size_t end = (size_t)-1,
    -
    5589 _In_ int flags = match_default)
    -
    5590 {
    -
    5591 assert(text || start >= end);
    -
    5592 interval.end = start;
    -
    5593 components.clear();
    -
    5594 for (;;) {
    -
    5595 if (interval.end < end && text[interval.end]) {
    - -
    5597 k.end = interval.end;
    -
    5598 for (;;) {
    -
    5599 if (k.end < end && text[k.end]) {
    -
    5600 if (isalpha(text[k.end]))
    -
    5601 k.end++;
    -
    5602 else
    -
    5603 break;
    -
    5604 }
    -
    5605 else
    -
    5606 break;
    -
    5607 }
    -
    5608 if (interval.end < k.end) {
    -
    5609 k.start = interval.end;
    -
    5610 interval.end = k.end;
    -
    5611 components.push_back(k);
    -
    5612 }
    -
    5613 else
    -
    5614 break;
    -
    5615 if (interval.end < end && text[interval.end] == '-')
    -
    5616 interval.end++;
    -
    5617 else
    -
    5618 break;
    -
    5619 }
    -
    5620 else
    -
    5621 break;
    -
    5622 }
    -
    5623 if (!components.empty()) {
    -
    5624 interval.start = start;
    -
    5625 interval.end = components.back().end;
    -
    5626 return true;
    -
    5627 }
    -
    5628 interval.start = (interval.end = start) + 1;
    -
    5629 return false;
    -
    5630 }
    -
    5631
    -
    5632 virtual void invalidate()
    -
    5633 {
    -
    5634 components.clear();
    -
    5635 parser::invalidate();
    -
    5636 }
    -
    5637
    -
    5638 public:
    -
    5639 std::vector<stdex::interval<size_t>> components;
    -
    5640 };
    +
    5581
    +
    +
    5585 class http_language : public parser
    +
    5586 {
    +
    5587 public:
    +
    5588 virtual bool match(
    +
    5589 _In_reads_or_z_(end) const char* text,
    +
    5590 _In_ size_t start = 0,
    +
    5591 _In_ size_t end = (size_t)-1,
    +
    5592 _In_ int flags = match_default)
    +
    5593 {
    +
    5594 assert(text || start >= end);
    +
    5595 this->interval.end = start;
    +
    5596 components.clear();
    +
    5597 for (;;) {
    +
    5598 if (this->interval.end < end && text[this->interval.end]) {
    + +
    5600 k.end = this->interval.end;
    +
    5601 for (;;) {
    +
    5602 if (k.end < end && text[k.end]) {
    +
    5603 if (isalpha(text[k.end]))
    +
    5604 k.end++;
    +
    5605 else
    +
    5606 break;
    +
    5607 }
    +
    5608 else
    +
    5609 break;
    +
    5610 }
    +
    5611 if (this->interval.end < k.end) {
    +
    5612 k.start = this->interval.end;
    +
    5613 this->interval.end = k.end;
    +
    5614 components.push_back(k);
    +
    5615 }
    +
    5616 else
    +
    5617 break;
    +
    5618 if (this->interval.end < end && text[this->interval.end] == '-')
    +
    5619 this->interval.end++;
    +
    5620 else
    +
    5621 break;
    +
    5622 }
    +
    5623 else
    +
    5624 break;
    +
    5625 }
    +
    5626 if (!components.empty()) {
    +
    5627 this->interval.start = start;
    +
    5628 this->interval.end = components.back().end;
    +
    5629 return true;
    +
    5630 }
    +
    5631 this->interval.start = (this->interval.end = start) + 1;
    +
    5632 return false;
    +
    5633 }
    +
    5634
    +
    5635 virtual void invalidate()
    +
    5636 {
    +
    5637 components.clear();
    +
    5638 parser::invalidate();
    +
    5639 }
    +
    5640
    +
    5641 public:
    +
    5642 std::vector<stdex::interval<size_t>> components;
    +
    5643 };
    -
    5641
    -
    -
    5645 class http_weight : public parser
    -
    5646 {
    -
    5647 public:
    -
    5648 http_weight(_In_ const std::locale& locale = std::locale()) :
    -
    5649 parser(locale),
    -
    5650 value(1.0f)
    -
    5651 {}
    -
    5652
    -
    5653 virtual bool match(
    -
    5654 _In_reads_or_z_(end) const char* text,
    -
    5655 _In_ size_t start = 0,
    -
    5656 _In_ size_t end = (size_t)-1,
    -
    5657 _In_ int flags = match_default)
    -
    5658 {
    -
    5659 assert(text || start >= end);
    -
    5660 size_t celi_del = 0, decimalni_del = 0, decimalni_del_n = 1;
    -
    5661 interval.end = start;
    -
    5662 for (;;) {
    -
    5663 if (interval.end < end && text[interval.end]) {
    -
    5664 if ('0' <= text[interval.end] && text[interval.end] <= '9') {
    -
    5665 celi_del = celi_del * 10 + text[interval.end] - '0';
    -
    5666 interval.end++;
    -
    5667 }
    -
    5668 else if (text[interval.end] == '.') {
    -
    5669 interval.end++;
    -
    5670 for (;;) {
    -
    5671 if (interval.end < end && text[interval.end]) {
    -
    5672 if ('0' <= text[interval.end] && text[interval.end] <= '9') {
    - -
    5674 decimalni_del_n *= 10;
    -
    5675 interval.end++;
    -
    5676 }
    -
    5677 else
    -
    5678 break;
    -
    5679 }
    -
    5680 else
    -
    5681 break;
    -
    5682 }
    -
    5683 break;
    -
    5684 }
    -
    5685 else
    +
    5644
    +
    +
    5648 class http_weight : public parser
    +
    5649 {
    +
    5650 public:
    +
    5651 http_weight(_In_ const std::locale& locale = std::locale()) :
    +
    5652 parser(locale),
    +
    5653 value(1.0f)
    +
    5654 {}
    +
    5655
    +
    5656 virtual bool match(
    +
    5657 _In_reads_or_z_(end) const char* text,
    +
    5658 _In_ size_t start = 0,
    +
    5659 _In_ size_t end = (size_t)-1,
    +
    5660 _In_ int flags = match_default)
    +
    5661 {
    +
    5662 assert(text || start >= end);
    +
    5663 size_t celi_del = 0, decimalni_del = 0, decimalni_del_n = 1;
    +
    5664 this->interval.end = start;
    +
    5665 for (;;) {
    +
    5666 if (this->interval.end < end && text[this->interval.end]) {
    +
    5667 if ('0' <= text[this->interval.end] && text[this->interval.end] <= '9') {
    +
    5668 celi_del = celi_del * 10 + text[this->interval.end] - '0';
    +
    5669 this->interval.end++;
    +
    5670 }
    +
    5671 else if (text[this->interval.end] == '.') {
    +
    5672 this->interval.end++;
    +
    5673 for (;;) {
    +
    5674 if (this->interval.end < end && text[this->interval.end]) {
    +
    5675 if ('0' <= text[this->interval.end] && text[this->interval.end] <= '9') {
    +
    5676 decimalni_del = decimalni_del * 10 + text[this->interval.end] - '0';
    +
    5677 decimalni_del_n *= 10;
    +
    5678 this->interval.end++;
    +
    5679 }
    +
    5680 else
    +
    5681 break;
    +
    5682 }
    +
    5683 else
    +
    5684 break;
    +
    5685 }
    5686 break;
    -
    5687 }
    -
    5688 else
    -
    5689 break;
    -
    5690 }
    -
    5691 if (start < interval.end) {
    - -
    5693 interval.start = start;
    -
    5694 return true;
    -
    5695 }
    -
    5696 value = 1.0f;
    -
    5697 interval.start = (interval.end = start) + 1;
    -
    5698 return false;
    -
    5699 }
    -
    5700
    -
    5701 virtual void invalidate()
    -
    5702 {
    -
    5703 value = 1.0f;
    -
    5704 parser::invalidate();
    -
    5705 }
    -
    5706
    -
    5707 public:
    -
    5708 float value;
    -
    5709 };
    +
    5687 }
    +
    5688 else
    +
    5689 break;
    +
    5690 }
    +
    5691 else
    +
    5692 break;
    +
    5693 }
    + + +
    5696 this->interval.start = start;
    +
    5697 return true;
    +
    5698 }
    +
    5699 value = 1.0f;
    +
    5700 this->interval.start = (this->interval.end = start) + 1;
    +
    5701 return false;
    +
    5702 }
    +
    5703
    +
    5704 virtual void invalidate()
    +
    5705 {
    +
    5706 value = 1.0f;
    +
    5707 parser::invalidate();
    +
    5708 }
    +
    5709
    +
    5710 public:
    +
    5711 float value;
    +
    5712 };
    -
    5710
    -
    -
    5714 class http_asterisk : public parser
    -
    5715 {
    -
    5716 public:
    -
    5717 virtual bool match(
    -
    5718 _In_reads_or_z_(end) const char* text,
    -
    5719 _In_ size_t start = 0,
    -
    5720 _In_ size_t end = (size_t)-1,
    -
    5721 _In_ int flags = match_default)
    -
    5722 {
    -
    5723 assert(text || end <= start);
    -
    5724 if (start < end && text[start] == '*') {
    -
    5725 interval.end = (interval.start = start) + 1;
    -
    5726 return true;
    -
    5727 }
    -
    5728 interval.start = (interval.end = start) + 1;
    -
    5729 return false;
    -
    5730 }
    -
    5731 };
    +
    5713
    +
    +
    5717 class http_asterisk : public parser
    +
    5718 {
    +
    5719 public:
    +
    5720 virtual bool match(
    +
    5721 _In_reads_or_z_(end) const char* text,
    +
    5722 _In_ size_t start = 0,
    +
    5723 _In_ size_t end = (size_t)-1,
    +
    5724 _In_ int flags = match_default)
    +
    5725 {
    +
    5726 assert(text || end <= start);
    +
    5727 if (start < end && text[start] == '*') {
    +
    5728 this->interval.end = (this->interval.start = start) + 1;
    +
    5729 return true;
    +
    5730 }
    +
    5731 this->interval.start = (this->interval.end = start) + 1;
    +
    5732 return false;
    +
    5733 }
    +
    5734 };
    -
    5732
    -
    5736 template <class T, class T_asterisk = http_asterisk>
    -
    - -
    5738 {
    -
    5739 public:
    -
    5740 http_weighted_value(_In_ const std::locale& locale = std::locale()) :
    -
    5741 parser(locale),
    -
    5742 factor(locale)
    -
    5743 {}
    -
    5744
    -
    5745 virtual bool match(
    -
    5746 _In_reads_or_z_(end) const char* text,
    -
    5747 _In_ size_t start = 0,
    -
    5748 _In_ size_t end = (size_t)-1,
    -
    5749 _In_ int flags = match_default)
    -
    5750 {
    -
    5751 assert(text || start >= end);
    -
    5752 size_t konec_vrednosti;
    -
    5753 interval.end = start;
    -
    5754 if (asterisk.match(text, interval.end, end, flags)) {
    - -
    5756 value.invalidate();
    -
    5757 }
    -
    5758 else if (value.match(text, interval.end, end, flags)) {
    -
    5759 interval.end = konec_vrednosti = value.interval.end;
    -
    5760 asterisk.invalidate();
    -
    5761 }
    -
    5762 else {
    +
    5735
    +
    5739 template <class T, class T_asterisk = http_asterisk>
    +
    + +
    5741 {
    +
    5742 public:
    +
    5743 http_weighted_value(_In_ const std::locale& locale = std::locale()) :
    +
    5744 parser(locale),
    +
    5745 factor(locale)
    +
    5746 {}
    +
    5747
    +
    5748 virtual bool match(
    +
    5749 _In_reads_or_z_(end) const char* text,
    +
    5750 _In_ size_t start = 0,
    +
    5751 _In_ size_t end = (size_t)-1,
    +
    5752 _In_ int flags = match_default)
    +
    5753 {
    +
    5754 assert(text || start >= end);
    +
    5755 size_t konec_vrednosti;
    +
    5756 this->interval.end = start;
    +
    5757 if (asterisk.match(text, this->interval.end, end, flags)) {
    +
    5758 this->interval.end = konec_vrednosti = asterisk.interval.end;
    +
    5759 value.invalidate();
    +
    5760 }
    +
    5761 else if (value.match(text, this->interval.end, end, flags)) {
    +
    5762 this->interval.end = konec_vrednosti = value.interval.end;
    5763 asterisk.invalidate();
    -
    5764 value.invalidate();
    -
    5765 interval.start = (interval.end = start) + 1;
    -
    5766 return false;
    -
    5767 }
    -
    5768
    -
    5769 while (interval.end < end && text[interval.end] && isspace(text[interval.end])) interval.end++;
    -
    5770 if (interval.end < end && text[interval.end] == ';') {
    -
    5771 interval.end++;
    -
    5772 while (interval.end < end && text[interval.end] && isspace(text[interval.end])) interval.end++;
    -
    5773 if (interval.end < end && (text[interval.end] == 'q' || text[interval.end] == 'Q')) {
    -
    5774 interval.end++;
    -
    5775 while (interval.end < end && text[interval.end] && isspace(text[interval.end])) interval.end++;
    -
    5776 if (interval.end < end && text[interval.end] == '=') {
    -
    5777 interval.end++;
    -
    5778 while (interval.end < end && text[interval.end] && isspace(text[interval.end])) interval.end++;
    -
    5779 if (factor.match(text, interval.end, end, flags))
    -
    5780 interval.end = factor.interval.end;
    -
    5781 }
    -
    5782 }
    -
    5783 }
    -
    5784 if (!factor.interval) {
    -
    5785 factor.invalidate();
    - -
    5787 }
    -
    5788 interval.start = start;
    -
    5789 return true;
    -
    5790 }
    -
    5791
    -
    5792 virtual void invalidate()
    -
    5793 {
    -
    5794 asterisk.invalidate();
    -
    5795 value.invalidate();
    -
    5796 factor.invalidate();
    -
    5797 parser::invalidate();
    -
    5798 }
    -
    5799
    -
    5800 public:
    -
    5801 T_asterisk asterisk;
    -
    5802 T value;
    -
    5803 http_weight factor;
    -
    5804 };
    +
    5764 }
    +
    5765 else {
    +
    5766 asterisk.invalidate();
    +
    5767 value.invalidate();
    +
    5768 this->interval.start = (this->interval.end = start) + 1;
    +
    5769 return false;
    +
    5770 }
    +
    5771
    +
    5772 while (this->interval.end < end && text[this->interval.end] && isspace(text[this->interval.end])) this->interval.end++;
    +
    5773 if (this->interval.end < end && text[this->interval.end] == ';') {
    +
    5774 this->interval.end++;
    +
    5775 while (this->interval.end < end && text[this->interval.end] && isspace(text[this->interval.end])) this->interval.end++;
    +
    5776 if (this->interval.end < end && (text[this->interval.end] == 'q' || text[this->interval.end] == 'Q')) {
    +
    5777 this->interval.end++;
    +
    5778 while (this->interval.end < end && text[this->interval.end] && isspace(text[this->interval.end])) this->interval.end++;
    +
    5779 if (this->interval.end < end && text[this->interval.end] == '=') {
    +
    5780 this->interval.end++;
    +
    5781 while (this->interval.end < end && text[this->interval.end] && isspace(text[this->interval.end])) this->interval.end++;
    +
    5782 if (factor.match(text, this->interval.end, end, flags))
    +
    5783 this->interval.end = factor.interval.end;
    +
    5784 }
    +
    5785 }
    +
    5786 }
    +
    5787 if (!factor.interval) {
    +
    5788 factor.invalidate();
    + +
    5790 }
    +
    5791 this->interval.start = start;
    +
    5792 return true;
    +
    5793 }
    +
    5794
    +
    5795 virtual void invalidate()
    +
    5796 {
    +
    5797 asterisk.invalidate();
    +
    5798 value.invalidate();
    +
    5799 factor.invalidate();
    +
    5800 parser::invalidate();
    +
    5801 }
    +
    5802
    +
    5803 public:
    +
    5804 T_asterisk asterisk;
    +
    5805 T value;
    +
    5806 http_weight factor;
    +
    5807 };
    -
    5805
    -
    - -
    5810 {
    -
    5811 public:
    -
    5812 virtual bool match(
    -
    5813 _In_reads_or_z_(end) const char* text,
    -
    5814 _In_ size_t start = 0,
    -
    5815 _In_ size_t end = (size_t)-1,
    -
    5816 _In_ int flags = match_default)
    -
    5817 {
    -
    5818 assert(text || start >= end);
    -
    5819 interval.end = start;
    -
    5820 if (interval.end < end && text[interval.end] == '$')
    -
    5821 interval.end++;
    -
    5822 else
    -
    5823 goto error;
    -
    5824 if (name.match(text, interval.end, end, flags))
    -
    5825 interval.end = name.interval.end;
    -
    5826 else
    -
    5827 goto error;
    -
    5828 while (m_space.match(text, interval.end, end, flags))
    -
    5829 interval.end = m_space.interval.end;
    -
    5830 if (interval.end < end && text[interval.end] == '=')
    -
    5831 interval.end++;
    -
    5832 else
    -
    5833 goto error;
    -
    5834 while (m_space.match(text, interval.end, end, flags))
    -
    5835 interval.end = m_space.interval.end;
    -
    5836 if (value.match(text, interval.end, end, flags))
    -
    5837 interval.end = value.interval.end;
    -
    5838 else
    -
    5839 goto error;
    -
    5840 interval.start = start;
    -
    5841 return true;
    -
    5842
    -
    5843 error:
    -
    5844 name.invalidate();
    -
    5845 value.invalidate();
    -
    5846 interval.start = (interval.end = start) + 1;
    -
    5847 return false;
    -
    5848 }
    -
    5849
    -
    5850 virtual void invalidate()
    -
    5851 {
    -
    5852 name.invalidate();
    -
    5853 value.invalidate();
    -
    5854 parser::invalidate();
    -
    5855 }
    -
    5856
    -
    5857 public:
    -
    5858 http_token name;
    -
    5859 http_value value;
    -
    5860
    -
    5861 protected:
    -
    5862 http_space m_space;
    -
    5863 };
    +
    5808
    +
    + +
    5813 {
    +
    5814 public:
    +
    5815 virtual bool match(
    +
    5816 _In_reads_or_z_(end) const char* text,
    +
    5817 _In_ size_t start = 0,
    +
    5818 _In_ size_t end = (size_t)-1,
    +
    5819 _In_ int flags = match_default)
    +
    5820 {
    +
    5821 assert(text || start >= end);
    +
    5822 this->interval.end = start;
    +
    5823 if (this->interval.end < end && text[this->interval.end] == '$')
    +
    5824 this->interval.end++;
    +
    5825 else
    +
    5826 goto error;
    +
    5827 if (name.match(text, this->interval.end, end, flags))
    +
    5828 this->interval.end = name.interval.end;
    +
    5829 else
    +
    5830 goto error;
    +
    5831 while (m_space.match(text, this->interval.end, end, flags))
    +
    5832 this->interval.end = m_space.interval.end;
    +
    5833 if (this->interval.end < end && text[this->interval.end] == '=')
    +
    5834 this->interval.end++;
    +
    5835 else
    +
    5836 goto error;
    +
    5837 while (m_space.match(text, this->interval.end, end, flags))
    +
    5838 this->interval.end = m_space.interval.end;
    +
    5839 if (value.match(text, this->interval.end, end, flags))
    +
    5840 this->interval.end = value.interval.end;
    +
    5841 else
    +
    5842 goto error;
    +
    5843 this->interval.start = start;
    +
    5844 return true;
    +
    5845
    +
    5846 error:
    +
    5847 name.invalidate();
    +
    5848 value.invalidate();
    +
    5849 this->interval.start = (this->interval.end = start) + 1;
    +
    5850 return false;
    +
    5851 }
    +
    5852
    +
    5853 virtual void invalidate()
    +
    5854 {
    +
    5855 name.invalidate();
    +
    5856 value.invalidate();
    +
    5857 parser::invalidate();
    +
    5858 }
    +
    5859
    +
    5860 public:
    +
    5861 http_token name;
    +
    5862 http_value value;
    +
    5863
    +
    5864 protected:
    +
    5865 http_space m_space;
    +
    5866 };
    -
    5864
    -
    -
    5868 class http_cookie : public parser
    -
    5869 {
    -
    5870 public:
    -
    5871 virtual bool match(
    -
    5872 _In_reads_or_z_(end) const char* text,
    -
    5873 _In_ size_t start = 0,
    -
    5874 _In_ size_t end = (size_t)-1,
    -
    5875 _In_ int flags = match_default)
    -
    5876 {
    -
    5877 assert(text || start >= end);
    -
    5878 interval.end = start;
    -
    5879 if (name.match(text, interval.end, end, flags))
    - -
    5881 else
    -
    5882 goto error;
    -
    5883 while (m_space.match(text, interval.end, end, flags))
    -
    5884 interval.end = m_space.interval.end;
    -
    5885 if (interval.end < end && text[interval.end] == '=')
    -
    5886 interval.end++;
    -
    5887 else
    -
    5888 goto error;
    -
    5889 while (m_space.match(text, interval.end, end, flags))
    -
    5890 interval.end = m_space.interval.end;
    -
    5891 if (value.match(text, interval.end, end, flags))
    - -
    5893 else
    -
    5894 goto error;
    -
    5895 params.clear();
    -
    5896 for (;;) {
    -
    5897 if (interval.end < end && text[interval.end]) {
    -
    5898 if (m_space.match(text, interval.end, end, flags))
    -
    5899 interval.end = m_space.interval.end;
    -
    5900 else if (text[interval.end] == ';') {
    -
    5901 interval.end++;
    -
    5902 while (m_space.match(text, interval.end, end, flags))
    -
    5903 interval.end = m_space.interval.end;
    - -
    5905 if (param.match(text, interval.end, end, flags)) {
    - -
    5907 params.push_back(std::move(param));
    -
    5908 }
    -
    5909 else
    -
    5910 break;
    -
    5911 }
    -
    5912 else
    -
    5913 break;
    -
    5914 }
    -
    5915 else
    -
    5916 break;
    -
    5917 }
    -
    5918 interval.start = start;
    -
    5919 interval.end = params.empty() ? value.interval.end : params.back().interval.end;
    -
    5920 return true;
    -
    5921
    -
    5922 error:
    -
    5923 name.invalidate();
    -
    5924 value.invalidate();
    -
    5925 params.clear();
    -
    5926 interval.start = (interval.end = start) + 1;
    -
    5927 return false;
    -
    5928 }
    -
    5929
    -
    5930 virtual void invalidate()
    -
    5931 {
    -
    5932 name.invalidate();
    -
    5933 value.invalidate();
    -
    5934 params.clear();
    -
    5935 parser::invalidate();
    -
    5936 }
    -
    5937
    -
    5938 public:
    - - -
    5941 std::list<http_cookie_parameter> params;
    -
    5942
    -
    5943 protected:
    -
    5944 http_space m_space;
    -
    5945 };
    +
    5867
    +
    +
    5871 class http_cookie : public parser
    +
    5872 {
    +
    5873 public:
    +
    5874 virtual bool match(
    +
    5875 _In_reads_or_z_(end) const char* text,
    +
    5876 _In_ size_t start = 0,
    +
    5877 _In_ size_t end = (size_t)-1,
    +
    5878 _In_ int flags = match_default)
    +
    5879 {
    +
    5880 assert(text || start >= end);
    +
    5881 this->interval.end = start;
    +
    5882 if (name.match(text, this->interval.end, end, flags))
    +
    5883 this->interval.end = name.interval.end;
    +
    5884 else
    +
    5885 goto error;
    +
    5886 while (m_space.match(text, this->interval.end, end, flags))
    +
    5887 this->interval.end = m_space.interval.end;
    +
    5888 if (this->interval.end < end && text[this->interval.end] == '=')
    +
    5889 this->interval.end++;
    +
    5890 else
    +
    5891 goto error;
    +
    5892 while (m_space.match(text, this->interval.end, end, flags))
    +
    5893 this->interval.end = m_space.interval.end;
    +
    5894 if (value.match(text, this->interval.end, end, flags))
    +
    5895 this->interval.end = value.interval.end;
    +
    5896 else
    +
    5897 goto error;
    +
    5898 params.clear();
    +
    5899 for (;;) {
    +
    5900 if (this->interval.end < end && text[this->interval.end]) {
    +
    5901 if (m_space.match(text, this->interval.end, end, flags))
    +
    5902 this->interval.end = m_space.interval.end;
    +
    5903 else if (text[this->interval.end] == ';') {
    +
    5904 this->interval.end++;
    +
    5905 while (m_space.match(text, this->interval.end, end, flags))
    +
    5906 this->interval.end = m_space.interval.end;
    + +
    5908 if (param.match(text, this->interval.end, end, flags)) {
    +
    5909 this->interval.end = param.interval.end;
    +
    5910 params.push_back(std::move(param));
    +
    5911 }
    +
    5912 else
    +
    5913 break;
    +
    5914 }
    +
    5915 else
    +
    5916 break;
    +
    5917 }
    +
    5918 else
    +
    5919 break;
    +
    5920 }
    +
    5921 this->interval.start = start;
    +
    5922 this->interval.end = params.empty() ? value.interval.end : params.back().interval.end;
    +
    5923 return true;
    +
    5924
    +
    5925 error:
    +
    5926 name.invalidate();
    +
    5927 value.invalidate();
    +
    5928 params.clear();
    +
    5929 this->interval.start = (this->interval.end = start) + 1;
    +
    5930 return false;
    +
    5931 }
    +
    5932
    +
    5933 virtual void invalidate()
    +
    5934 {
    +
    5935 name.invalidate();
    +
    5936 value.invalidate();
    +
    5937 params.clear();
    +
    5938 parser::invalidate();
    +
    5939 }
    +
    5940
    +
    5941 public:
    + + +
    5944 std::list<http_cookie_parameter> params;
    +
    5945
    +
    5946 protected:
    +
    5947 http_space m_space;
    +
    5948 };
    -
    5946
    -
    -
    5950 class http_agent : public parser
    -
    5951 {
    -
    5952 public:
    -
    5953 virtual bool match(
    -
    5954 _In_reads_or_z_(end) const char* text,
    -
    5955 _In_ size_t start = 0,
    -
    5956 _In_ size_t end = (size_t)-1,
    -
    5957 _In_ int flags = match_default)
    -
    5958 {
    -
    5959 assert(text || start >= end);
    -
    5960 interval.end = start;
    -
    5961 type.start = interval.end;
    -
    5962 for (;;) {
    -
    5963 if (interval.end < end && text[interval.end]) {
    -
    5964 if (text[interval.end] == '/') {
    -
    5965 type.end = interval.end;
    -
    5966 interval.end++;
    -
    5967 version.start = interval.end;
    -
    5968 for (;;) {
    -
    5969 if (interval.end < end && text[interval.end]) {
    -
    5970 if (isspace(text[interval.end])) {
    -
    5971 version.end = interval.end;
    -
    5972 break;
    -
    5973 }
    -
    5974 else
    -
    5975 interval.end++;
    -
    5976 }
    -
    5977 else {
    -
    5978 version.end = interval.end;
    -
    5979 break;
    -
    5980 }
    -
    5981 }
    -
    5982 break;
    -
    5983 }
    -
    5984 else if (isspace(text[interval.end])) {
    -
    5985 type.end = interval.end;
    -
    5986 break;
    -
    5987 }
    -
    5988 else
    -
    5989 interval.end++;
    -
    5990 }
    -
    5991 else {
    -
    5992 type.end = interval.end;
    -
    5993 break;
    -
    5994 }
    -
    5995 }
    -
    5996 if (start < interval.end) {
    -
    5997 interval.start = start;
    -
    5998 return true;
    -
    5999 }
    -
    6000 type.start = 1;
    -
    6001 type.end = 0;
    -
    6002 version.start = 1;
    -
    6003 version.end = 0;
    -
    6004 interval.start = 1;
    -
    6005 interval.end = 0;
    -
    6006 return false;
    -
    6007 }
    -
    6008
    -
    6009 virtual void invalidate()
    -
    6010 {
    -
    6011 type.start = 1;
    -
    6012 type.end = 0;
    -
    6013 version.start = 1;
    -
    6014 version.end = 0;
    -
    6015 parser::invalidate();
    -
    6016 }
    -
    6017
    -
    6018 public:
    - - -
    6021 };
    +
    5949
    +
    +
    5953 class http_agent : public parser
    +
    5954 {
    +
    5955 public:
    +
    5956 virtual bool match(
    +
    5957 _In_reads_or_z_(end) const char* text,
    +
    5958 _In_ size_t start = 0,
    +
    5959 _In_ size_t end = (size_t)-1,
    +
    5960 _In_ int flags = match_default)
    +
    5961 {
    +
    5962 assert(text || start >= end);
    +
    5963 this->interval.end = start;
    +
    5964 type.start = this->interval.end;
    +
    5965 for (;;) {
    +
    5966 if (this->interval.end < end && text[this->interval.end]) {
    +
    5967 if (text[this->interval.end] == '/') {
    +
    5968 type.end = this->interval.end;
    +
    5969 this->interval.end++;
    +
    5970 version.start = this->interval.end;
    +
    5971 for (;;) {
    +
    5972 if (this->interval.end < end && text[this->interval.end]) {
    +
    5973 if (isspace(text[this->interval.end])) {
    +
    5974 version.end = this->interval.end;
    +
    5975 break;
    +
    5976 }
    +
    5977 else
    +
    5978 this->interval.end++;
    +
    5979 }
    +
    5980 else {
    +
    5981 version.end = this->interval.end;
    +
    5982 break;
    +
    5983 }
    +
    5984 }
    +
    5985 break;
    +
    5986 }
    +
    5987 else if (isspace(text[this->interval.end])) {
    +
    5988 type.end = this->interval.end;
    +
    5989 break;
    +
    5990 }
    +
    5991 else
    +
    5992 this->interval.end++;
    +
    5993 }
    +
    5994 else {
    +
    5995 type.end = this->interval.end;
    +
    5996 break;
    +
    5997 }
    +
    5998 }
    + +
    6000 this->interval.start = start;
    +
    6001 return true;
    +
    6002 }
    +
    6003 type.start = 1;
    +
    6004 type.end = 0;
    +
    6005 version.start = 1;
    +
    6006 version.end = 0;
    +
    6007 this->interval.start = 1;
    +
    6008 this->interval.end = 0;
    +
    6009 return false;
    +
    6010 }
    +
    6011
    +
    6012 virtual void invalidate()
    +
    6013 {
    +
    6014 type.start = 1;
    +
    6015 type.end = 0;
    +
    6016 version.start = 1;
    +
    6017 version.end = 0;
    +
    6018 parser::invalidate();
    +
    6019 }
    +
    6020
    +
    6021 public:
    + + +
    6024 };
    -
    6022
    -
    -
    6026 class http_protocol : public parser
    -
    6027 {
    -
    6028 public:
    -
    6029 http_protocol(_In_ const std::locale& locale = std::locale()) :
    -
    6030 parser(locale),
    -
    6031 version(0x009)
    -
    6032 {}
    -
    6033
    -
    6034 virtual bool match(
    -
    6035 _In_reads_or_z_(end) const char* text,
    -
    6036 _In_ size_t start = 0,
    -
    6037 _In_ size_t end = (size_t)-1,
    -
    6038 _In_ int flags = match_default)
    -
    6039 {
    -
    6040 assert(text || start >= end);
    -
    6041 interval.end = start;
    -
    6042 type.start = interval.end;
    -
    6043 for (;;) {
    -
    6044 if (interval.end < end && text[interval.end]) {
    -
    6045 if (text[interval.end] == '/') {
    -
    6046 type.end = interval.end;
    -
    6047 interval.end++;
    -
    6048 break;
    -
    6049 }
    -
    6050 else if (isspace(text[interval.end]))
    -
    6051 goto error;
    -
    6052 else
    -
    6053 interval.end++;
    -
    6054 }
    -
    6055 else {
    -
    6056 type.end = interval.end;
    -
    6057 goto error;
    -
    6058 }
    -
    6059 }
    -
    6060 version_maj.start = interval.end;
    -
    6061 for (;;) {
    -
    6062 if (interval.end < end && text[interval.end]) {
    -
    6063 if (text[interval.end] == '.') {
    -
    6064 version_maj.end = interval.end;
    -
    6065 interval.end++;
    -
    6066 version_min.start = interval.end;
    -
    6067 for (;;) {
    -
    6068 if (interval.end < end && text[interval.end]) {
    -
    6069 if (isspace(text[interval.end])) {
    -
    6070 version_min.end = interval.end;
    -
    6071 version =
    -
    6072 (uint16_t)strtoui(text + version_maj.start, version_maj.size(), nullptr, 10) * 0x100 +
    -
    6073 (uint16_t)strtoui(text + version_min.start, version_min.size(), nullptr, 10);
    -
    6074 break;
    -
    6075 }
    -
    6076 else
    -
    6077 interval.end++;
    -
    6078 }
    -
    6079 else
    -
    6080 goto error;
    -
    6081 }
    -
    6082 break;
    -
    6083 }
    -
    6084 else if (isspace(text[interval.end])) {
    -
    6085 version_maj.end = interval.end;
    -
    6086 version_min.start = 1;
    -
    6087 version_min.end = 0;
    -
    6088 version = (uint16_t)strtoui(text + version_maj.start, version_maj.size(), nullptr, 10) * 0x100;
    -
    6089 break;
    -
    6090 }
    -
    6091 else
    -
    6092 interval.end++;
    -
    6093 }
    -
    6094 else
    -
    6095 goto error;
    -
    6096 }
    -
    6097 interval.start = start;
    -
    6098 return true;
    -
    6099
    -
    6100 error:
    -
    6101 type.start = 1;
    -
    6102 type.end = 0;
    -
    6103 version_maj.start = 1;
    -
    6104 version_maj.end = 0;
    -
    6105 version_min.start = 1;
    -
    6106 version_min.end = 0;
    -
    6107 version = 0x009;
    -
    6108 interval.start = 1;
    -
    6109 interval.end = 0;
    -
    6110 return false;
    -
    6111 }
    -
    6112
    -
    6113 virtual void invalidate()
    -
    6114 {
    -
    6115 type.start = 1;
    -
    6116 type.end = 0;
    -
    6117 version_maj.start = 1;
    -
    6118 version_maj.end = 0;
    -
    6119 version_min.start = 1;
    -
    6120 version_min.end = 0;
    -
    6121 version = 0x009;
    -
    6122 parser::invalidate();
    -
    6123 }
    -
    6124
    -
    6125 public:
    - -
    6127 stdex::interval<size_t> version_maj;
    -
    6128 stdex::interval<size_t> version_min;
    - -
    6130 };
    +
    6025
    +
    +
    6029 class http_protocol : public parser
    +
    6030 {
    +
    6031 public:
    +
    6032 http_protocol(_In_ const std::locale& locale = std::locale()) :
    +
    6033 parser(locale),
    +
    6034 version(0x009)
    +
    6035 {}
    +
    6036
    +
    6037 virtual bool match(
    +
    6038 _In_reads_or_z_(end) const char* text,
    +
    6039 _In_ size_t start = 0,
    +
    6040 _In_ size_t end = (size_t)-1,
    +
    6041 _In_ int flags = match_default)
    +
    6042 {
    +
    6043 assert(text || start >= end);
    +
    6044 this->interval.end = start;
    +
    6045 type.start = this->interval.end;
    +
    6046 for (;;) {
    +
    6047 if (this->interval.end < end && text[this->interval.end]) {
    +
    6048 if (text[this->interval.end] == '/') {
    +
    6049 type.end = this->interval.end;
    +
    6050 this->interval.end++;
    +
    6051 break;
    +
    6052 }
    +
    6053 else if (isspace(text[this->interval.end]))
    +
    6054 goto error;
    +
    6055 else
    +
    6056 this->interval.end++;
    +
    6057 }
    +
    6058 else {
    +
    6059 type.end = this->interval.end;
    +
    6060 goto error;
    +
    6061 }
    +
    6062 }
    +
    6063 version_maj.start = this->interval.end;
    +
    6064 for (;;) {
    +
    6065 if (this->interval.end < end && text[this->interval.end]) {
    +
    6066 if (text[this->interval.end] == '.') {
    +
    6067 version_maj.end = this->interval.end;
    +
    6068 this->interval.end++;
    +
    6069 version_min.start = this->interval.end;
    +
    6070 for (;;) {
    +
    6071 if (this->interval.end < end && text[this->interval.end]) {
    +
    6072 if (isspace(text[this->interval.end])) {
    +
    6073 version_min.end = this->interval.end;
    +
    6074 version =
    +
    6075 (uint16_t)strtoui(text + version_maj.start, version_maj.size(), nullptr, 10) * 0x100 +
    +
    6076 (uint16_t)strtoui(text + version_min.start, version_min.size(), nullptr, 10);
    +
    6077 break;
    +
    6078 }
    +
    6079 else
    +
    6080 this->interval.end++;
    +
    6081 }
    +
    6082 else
    +
    6083 goto error;
    +
    6084 }
    +
    6085 break;
    +
    6086 }
    +
    6087 else if (isspace(text[this->interval.end])) {
    +
    6088 version_maj.end = this->interval.end;
    +
    6089 version_min.start = 1;
    +
    6090 version_min.end = 0;
    +
    6091 version = (uint16_t)strtoui(text + version_maj.start, version_maj.size(), nullptr, 10) * 0x100;
    +
    6092 break;
    +
    6093 }
    +
    6094 else
    +
    6095 this->interval.end++;
    +
    6096 }
    +
    6097 else
    +
    6098 goto error;
    +
    6099 }
    +
    6100 this->interval.start = start;
    +
    6101 return true;
    +
    6102
    +
    6103 error:
    +
    6104 type.start = 1;
    +
    6105 type.end = 0;
    +
    6106 version_maj.start = 1;
    +
    6107 version_maj.end = 0;
    +
    6108 version_min.start = 1;
    +
    6109 version_min.end = 0;
    +
    6110 version = 0x009;
    +
    6111 this->interval.start = 1;
    +
    6112 this->interval.end = 0;
    +
    6113 return false;
    +
    6114 }
    +
    6115
    +
    6116 virtual void invalidate()
    +
    6117 {
    +
    6118 type.start = 1;
    +
    6119 type.end = 0;
    +
    6120 version_maj.start = 1;
    +
    6121 version_maj.end = 0;
    +
    6122 version_min.start = 1;
    +
    6123 version_min.end = 0;
    +
    6124 version = 0x009;
    +
    6125 parser::invalidate();
    +
    6126 }
    +
    6127
    +
    6128 public:
    + +
    6130 stdex::interval<size_t> version_maj;
    +
    6131 stdex::interval<size_t> version_min;
    + +
    6133 };
    -
    6131
    -
    -
    6135 class http_request : public parser
    -
    6136 {
    -
    6137 public:
    -
    6138 http_request(_In_ const std::locale& locale = std::locale()) :
    -
    6139 parser(locale),
    -
    6140 url(locale),
    -
    6141 protocol(locale)
    -
    6142 {}
    -
    6143
    -
    6144 virtual bool match(
    -
    6145 _In_reads_or_z_(end) const char* text,
    -
    6146 _In_ size_t start = 0,
    -
    6147 _In_ size_t end = (size_t)-1,
    -
    6148 _In_ int flags = match_default)
    -
    6149 {
    -
    6150 assert(text || start >= end);
    -
    6151 interval.end = start;
    -
    6152
    -
    6153 for (;;) {
    -
    6154 if (m_line_break.match(text, interval.end, end, flags))
    -
    6155 goto error;
    -
    6156 else if (interval.end < end && text[interval.end]) {
    -
    6157 if (isspace(text[interval.end]))
    -
    6158 interval.end++;
    -
    6159 else
    -
    6160 break;
    -
    6161 }
    -
    6162 else
    -
    6163 goto error;
    -
    6164 }
    -
    6165 verb.start = interval.end;
    -
    6166 for (;;) {
    -
    6167 if (m_line_break.match(text, interval.end, end, flags))
    -
    6168 goto error;
    -
    6169 else if (interval.end < end && text[interval.end]) {
    -
    6170 if (isspace(text[interval.end])) {
    -
    6171 verb.end = interval.end;
    -
    6172 interval.end++;
    -
    6173 break;
    -
    6174 }
    -
    6175 else
    -
    6176 interval.end++;
    -
    6177 }
    -
    6178 else
    -
    6179 goto error;
    -
    6180 }
    -
    6181
    -
    6182 for (;;) {
    -
    6183 if (m_line_break.match(text, interval.end, end, flags))
    -
    6184 goto error;
    -
    6185 else if (interval.end < end && text[interval.end]) {
    -
    6186 if (isspace(text[interval.end]))
    -
    6187 interval.end++;
    -
    6188 else
    -
    6189 break;
    -
    6190 }
    -
    6191 else
    -
    6192 goto error;
    -
    6193 }
    -
    6194 if (url.match(text, interval.end, end, flags))
    - -
    6196 else
    -
    6197 goto error;
    -
    6198
    -
    6199 protocol.invalidate();
    -
    6200 for (;;) {
    -
    6201 if (m_line_break.match(text, interval.end, end, flags)) {
    -
    6202 interval.end = m_line_break.interval.end;
    -
    6203 goto end;
    -
    6204 }
    -
    6205 else if (interval.end < end && text[interval.end]) {
    -
    6206 if (isspace(text[interval.end]))
    -
    6207 interval.end++;
    -
    6208 else
    -
    6209 break;
    -
    6210 }
    -
    6211 else
    -
    6212 goto end;
    -
    6213 }
    -
    6214 for (;;) {
    -
    6215 if (m_line_break.match(text, interval.end, end, flags)) {
    -
    6216 interval.end = m_line_break.interval.end;
    -
    6217 goto end;
    -
    6218 }
    -
    6219 else if (protocol.match(text, interval.end, end, flags)) {
    -
    6220 interval.end = protocol.interval.end;
    -
    6221 break;
    -
    6222 }
    -
    6223 else
    -
    6224 goto end;
    -
    6225 }
    -
    6226
    -
    6227 for (;;) {
    -
    6228 if (m_line_break.match(text, interval.end, end, flags)) {
    -
    6229 interval.end = m_line_break.interval.end;
    -
    6230 break;
    -
    6231 }
    -
    6232 else if (interval.end < end && text[interval.end])
    -
    6233 interval.end++;
    -
    6234 else
    -
    6235 goto end;
    -
    6236 }
    -
    6237
    -
    6238 end:
    -
    6239 interval.start = start;
    -
    6240 return true;
    -
    6241
    -
    6242 error:
    -
    6243 verb.start = 1;
    -
    6244 verb.end = 0;
    -
    6245 url.invalidate();
    -
    6246 protocol.invalidate();
    -
    6247 interval.start = 1;
    -
    6248 interval.end = 0;
    -
    6249 return false;
    -
    6250 }
    -
    6251
    -
    6252 virtual void invalidate()
    -
    6253 {
    -
    6254 verb.start = 1;
    -
    6255 verb.end = 0;
    -
    6256 url.invalidate();
    -
    6257 protocol.invalidate();
    -
    6258 parser::invalidate();
    -
    6259 }
    -
    6260
    -
    6261 public:
    - -
    6263 http_url url;
    -
    6264 http_protocol protocol;
    -
    6265
    -
    6266 protected:
    -
    6267 http_line_break m_line_break;
    -
    6268 };
    +
    6134
    +
    +
    6138 class http_request : public parser
    +
    6139 {
    +
    6140 public:
    +
    6141 http_request(_In_ const std::locale& locale = std::locale()) :
    +
    6142 parser(locale),
    +
    6143 url(locale),
    +
    6144 protocol(locale)
    +
    6145 {}
    +
    6146
    +
    6147 virtual bool match(
    +
    6148 _In_reads_or_z_(end) const char* text,
    +
    6149 _In_ size_t start = 0,
    +
    6150 _In_ size_t end = (size_t)-1,
    +
    6151 _In_ int flags = match_default)
    +
    6152 {
    +
    6153 assert(text || start >= end);
    +
    6154 this->interval.end = start;
    +
    6155
    +
    6156 for (;;) {
    +
    6157 if (m_line_break.match(text, this->interval.end, end, flags))
    +
    6158 goto error;
    +
    6159 else if (this->interval.end < end && text[this->interval.end]) {
    +
    6160 if (isspace(text[this->interval.end]))
    +
    6161 this->interval.end++;
    +
    6162 else
    +
    6163 break;
    +
    6164 }
    +
    6165 else
    +
    6166 goto error;
    +
    6167 }
    +
    6168 verb.start = this->interval.end;
    +
    6169 for (;;) {
    +
    6170 if (m_line_break.match(text, this->interval.end, end, flags))
    +
    6171 goto error;
    +
    6172 else if (this->interval.end < end && text[this->interval.end]) {
    +
    6173 if (isspace(text[this->interval.end])) {
    +
    6174 verb.end = this->interval.end;
    +
    6175 this->interval.end++;
    +
    6176 break;
    +
    6177 }
    +
    6178 else
    +
    6179 this->interval.end++;
    +
    6180 }
    +
    6181 else
    +
    6182 goto error;
    +
    6183 }
    +
    6184
    +
    6185 for (;;) {
    +
    6186 if (m_line_break.match(text, this->interval.end, end, flags))
    +
    6187 goto error;
    +
    6188 else if (this->interval.end < end && text[this->interval.end]) {
    +
    6189 if (isspace(text[this->interval.end]))
    +
    6190 this->interval.end++;
    +
    6191 else
    +
    6192 break;
    +
    6193 }
    +
    6194 else
    +
    6195 goto error;
    +
    6196 }
    +
    6197 if (url.match(text, this->interval.end, end, flags))
    +
    6198 this->interval.end = url.interval.end;
    +
    6199 else
    +
    6200 goto error;
    +
    6201
    +
    6202 protocol.invalidate();
    +
    6203 for (;;) {
    +
    6204 if (m_line_break.match(text, this->interval.end, end, flags)) {
    +
    6205 this->interval.end = m_line_break.interval.end;
    +
    6206 goto end;
    +
    6207 }
    +
    6208 else if (this->interval.end < end && text[this->interval.end]) {
    +
    6209 if (isspace(text[this->interval.end]))
    +
    6210 this->interval.end++;
    +
    6211 else
    +
    6212 break;
    +
    6213 }
    +
    6214 else
    +
    6215 goto end;
    +
    6216 }
    +
    6217 for (;;) {
    +
    6218 if (m_line_break.match(text, this->interval.end, end, flags)) {
    +
    6219 this->interval.end = m_line_break.interval.end;
    +
    6220 goto end;
    +
    6221 }
    +
    6222 else if (protocol.match(text, this->interval.end, end, flags)) {
    +
    6223 this->interval.end = protocol.interval.end;
    +
    6224 break;
    +
    6225 }
    +
    6226 else
    +
    6227 goto end;
    +
    6228 }
    +
    6229
    +
    6230 for (;;) {
    +
    6231 if (m_line_break.match(text, this->interval.end, end, flags)) {
    +
    6232 this->interval.end = m_line_break.interval.end;
    +
    6233 break;
    +
    6234 }
    +
    6235 else if (this->interval.end < end && text[this->interval.end])
    +
    6236 this->interval.end++;
    +
    6237 else
    +
    6238 goto end;
    +
    6239 }
    +
    6240
    +
    6241 end:
    +
    6242 this->interval.start = start;
    +
    6243 return true;
    +
    6244
    +
    6245 error:
    +
    6246 verb.start = 1;
    +
    6247 verb.end = 0;
    +
    6248 url.invalidate();
    +
    6249 protocol.invalidate();
    +
    6250 this->interval.start = 1;
    +
    6251 this->interval.end = 0;
    +
    6252 return false;
    +
    6253 }
    +
    6254
    +
    6255 virtual void invalidate()
    +
    6256 {
    +
    6257 verb.start = 1;
    +
    6258 verb.end = 0;
    +
    6259 url.invalidate();
    +
    6260 protocol.invalidate();
    +
    6261 parser::invalidate();
    +
    6262 }
    +
    6263
    +
    6264 public:
    + +
    6266 http_url url;
    +
    6267 http_protocol protocol;
    +
    6268
    +
    6269 protected:
    +
    6270 http_line_break m_line_break;
    +
    6271 };
    -
    6269
    -
    -
    6273 class http_header : public parser
    -
    6274 {
    -
    6275 public:
    -
    6276 virtual bool match(
    -
    6277 _In_reads_or_z_(end) const char* text,
    -
    6278 _In_ size_t start = 0,
    -
    6279 _In_ size_t end = (size_t)-1,
    -
    6280 _In_ int flags = match_default)
    -
    6281 {
    -
    6282 assert(text || start >= end);
    -
    6283 interval.end = start;
    -
    6284
    -
    6285 if (m_line_break.match(text, interval.end, end, flags) ||
    - -
    6287 goto error;
    -
    6288 name.start = interval.end;
    -
    6289 for (;;) {
    -
    6290 if (m_line_break.match(text, interval.end, end, flags))
    -
    6291 goto error;
    -
    6292 else if (interval.end < end && text[interval.end]) {
    -
    6293 if (isspace(text[interval.end])) {
    -
    6294 name.end = interval.end;
    -
    6295 interval.end++;
    -
    6296 for (;;) {
    -
    6297 if (m_line_break.match(text, interval.end, end, flags))
    -
    6298 goto error;
    -
    6299 else if (interval.end < end && text[interval.end]) {
    -
    6300 if (isspace(text[interval.end]))
    -
    6301 interval.end++;
    -
    6302 else
    -
    6303 break;
    -
    6304 }
    -
    6305 else
    -
    6306 goto error;
    -
    6307 }
    -
    6308 if (interval.end < end && text[interval.end] == ':') {
    -
    6309 interval.end++;
    -
    6310 break;
    -
    6311 }
    -
    6312 else
    -
    6313 goto error;
    -
    6314 break;
    -
    6315 }
    -
    6316 else if (text[interval.end] == ':') {
    -
    6317 name.end = interval.end;
    -
    6318 interval.end++;
    -
    6319 break;
    -
    6320 }
    -
    6321 else
    -
    6322 interval.end++;
    -
    6323 }
    -
    6324 else
    -
    6325 goto error;
    -
    6326 }
    -
    6327 value.start = (size_t)-1;
    -
    6328 value.end = 0;
    -
    6329 for (;;) {
    -
    6330 if (m_line_break.match(text, interval.end, end, flags)) {
    -
    6331 interval.end = m_line_break.interval.end;
    -
    6332 if (!m_line_break.match(text, interval.end, end, flags) &&
    - -
    6334 interval.end++;
    -
    6335 else
    -
    6336 break;
    -
    6337 }
    -
    6338 else if (interval.end < end && text[interval.end]) {
    -
    6339 if (isspace(text[interval.end]))
    -
    6340 interval.end++;
    -
    6341 else {
    -
    6342 if (value.start == (size_t)-1) value.start = interval.end;
    -
    6343 value.end = ++interval.end;
    -
    6344 }
    -
    6345 }
    -
    6346 else
    -
    6347 break;
    -
    6348 }
    -
    6349 interval.start = start;
    -
    6350 return true;
    -
    6351
    -
    6352 error:
    -
    6353 name.start = 1;
    -
    6354 name.end = 0;
    -
    6355 value.start = 1;
    -
    6356 value.end = 0;
    -
    6357 interval.start = 1;
    -
    6358 interval.end = 0;
    -
    6359 return false;
    -
    6360 }
    -
    6361
    -
    6362 virtual void invalidate()
    -
    6363 {
    -
    6364 name.start = 1;
    -
    6365 name.end = 0;
    -
    6366 value.start = 1;
    -
    6367 value.end = 0;
    -
    6368 parser::invalidate();
    -
    6369 }
    -
    6370
    -
    6371 public:
    - - -
    6374
    -
    6375 protected:
    -
    6376 http_line_break m_line_break;
    -
    6377 };
    +
    6272
    +
    +
    6276 class http_header : public parser
    +
    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 assert(text || start >= end);
    +
    6286 this->interval.end = start;
    +
    6287
    +
    6288 if (m_line_break.match(text, this->interval.end, end, flags) ||
    +
    6289 (this->interval.end < end && text[this->interval.end] && isspace(text[this->interval.end])))
    +
    6290 goto error;
    +
    6291 name.start = this->interval.end;
    +
    6292 for (;;) {
    +
    6293 if (m_line_break.match(text, this->interval.end, end, flags))
    +
    6294 goto error;
    +
    6295 else if (this->interval.end < end && text[this->interval.end]) {
    +
    6296 if (isspace(text[this->interval.end])) {
    +
    6297 name.end = this->interval.end;
    +
    6298 this->interval.end++;
    +
    6299 for (;;) {
    +
    6300 if (m_line_break.match(text, this->interval.end, end, flags))
    +
    6301 goto error;
    +
    6302 else if (this->interval.end < end && text[this->interval.end]) {
    +
    6303 if (isspace(text[this->interval.end]))
    +
    6304 this->interval.end++;
    +
    6305 else
    +
    6306 break;
    +
    6307 }
    +
    6308 else
    +
    6309 goto error;
    +
    6310 }
    +
    6311 if (this->interval.end < end && text[this->interval.end] == ':') {
    +
    6312 this->interval.end++;
    +
    6313 break;
    +
    6314 }
    +
    6315 else
    +
    6316 goto error;
    +
    6317 break;
    +
    6318 }
    +
    6319 else if (text[this->interval.end] == ':') {
    +
    6320 name.end = this->interval.end;
    +
    6321 this->interval.end++;
    +
    6322 break;
    +
    6323 }
    +
    6324 else
    +
    6325 this->interval.end++;
    +
    6326 }
    +
    6327 else
    +
    6328 goto error;
    +
    6329 }
    +
    6330 value.start = (size_t)-1;
    +
    6331 value.end = 0;
    +
    6332 for (;;) {
    +
    6333 if (m_line_break.match(text, this->interval.end, end, flags)) {
    +
    6334 this->interval.end = m_line_break.interval.end;
    +
    6335 if (!m_line_break.match(text, this->interval.end, end, flags) &&
    +
    6336 this->interval.end < end && text[this->interval.end] && isspace(text[this->interval.end]))
    +
    6337 this->interval.end++;
    +
    6338 else
    +
    6339 break;
    +
    6340 }
    +
    6341 else if (this->interval.end < end && text[this->interval.end]) {
    +
    6342 if (isspace(text[this->interval.end]))
    +
    6343 this->interval.end++;
    +
    6344 else {
    +
    6345 if (value.start == (size_t)-1) value.start = this->interval.end;
    +
    6346 value.end = ++this->interval.end;
    +
    6347 }
    +
    6348 }
    +
    6349 else
    +
    6350 break;
    +
    6351 }
    +
    6352 this->interval.start = start;
    +
    6353 return true;
    +
    6354
    +
    6355 error:
    +
    6356 name.start = 1;
    +
    6357 name.end = 0;
    +
    6358 value.start = 1;
    +
    6359 value.end = 0;
    +
    6360 this->interval.start = 1;
    +
    6361 this->interval.end = 0;
    +
    6362 return false;
    +
    6363 }
    +
    6364
    +
    6365 virtual void invalidate()
    +
    6366 {
    +
    6367 name.start = 1;
    +
    6368 name.end = 0;
    +
    6369 value.start = 1;
    +
    6370 value.end = 0;
    +
    6371 parser::invalidate();
    +
    6372 }
    +
    6373
    +
    6374 public:
    + + +
    6377
    +
    6378 protected:
    +
    6379 http_line_break m_line_break;
    +
    6380 };
    -
    6378
    -
    6382 template <class T>
    -
    -
    6383 class http_value_collection : public T
    -
    6384 {
    -
    6385 public:
    -
    6386 void insert(
    -
    6387 _In_reads_or_z_(end) const char* text,
    -
    6388 _In_ size_t start = 0,
    -
    6389 _In_ size_t end = (size_t)-1,
    -
    6390 _In_ int flags = match_default)
    -
    6391 {
    -
    6392 while (start < end) {
    -
    6393 while (start < end && text[start] && isspace(text[start])) start++;
    -
    6394 if (start < end && text[start] == ',') {
    -
    6395 start++;
    -
    6396 while (start < end&& text[start] && isspace(text[start])) start++;
    -
    6397 }
    -
    6398 T::key_type el;
    -
    6399 if (el.match(text, start, end, flags)) {
    -
    6400 start = el.interval.end;
    -
    6401 T::insert(std::move(el));
    -
    6402 }
    -
    6403 else
    -
    6404 break;
    -
    6405 }
    -
    6406 }
    -
    6407 };
    +
    6381
    +
    6385 template <class _Key, class T>
    +
    +
    6386 class http_value_collection : public T
    +
    6387 {
    +
    6388 public:
    +
    6389 void insert(
    +
    6390 _In_reads_or_z_(end) const char* text,
    +
    6391 _In_ size_t start = 0,
    +
    6392 _In_ size_t end = (size_t)-1,
    +
    6393 _In_ int flags = match_default)
    +
    6394 {
    +
    6395 while (start < end) {
    +
    6396 while (start < end && text[start] && isspace(text[start])) start++;
    +
    6397 if (start < end && text[start] == ',') {
    +
    6398 start++;
    +
    6399 while (start < end&& text[start] && isspace(text[start])) start++;
    +
    6400 }
    +
    6401 _Key el;
    +
    6402 if (el.match(text, start, end, flags)) {
    +
    6403 start = el.interval.end;
    +
    6404 T::insert(std::move(el));
    +
    6405 }
    +
    6406 else
    +
    6407 break;
    +
    6408 }
    +
    6409 }
    +
    6410 };
    -
    6408
    -
    6409 template <class T>
    -
    - -
    6411 constexpr bool operator()(const T& a, const T& b) const noexcept
    -
    6412 {
    -
    6413 return a.factor.value > b.factor.value;
    -
    6414 }
    -
    6415 };
    +
    6411
    +
    6412 template <class T>
    +
    + +
    6414 constexpr bool operator()(const T& a, const T& b) const noexcept
    +
    6415 {
    +
    6416 return a.factor.value > b.factor.value;
    +
    6417 }
    +
    6418 };
    -
    6416
    -
    6420 template <class T, class _Alloc = std::allocator<T>>
    - -
    6422
    -
    6426 template <class T>
    -
    - -
    6428 {
    -
    6429 public:
    - -
    6431 _In_ const std::shared_ptr<basic_parser<T>>& quote,
    -
    6432 _In_ const std::shared_ptr<basic_parser<T>>& chr,
    -
    6433 _In_ const std::shared_ptr<basic_parser<T>>& escape,
    -
    6434 _In_ const std::shared_ptr<basic_parser<T>>& sol,
    -
    6435 _In_ const std::shared_ptr<basic_parser<T>>& bs,
    -
    6436 _In_ const std::shared_ptr<basic_parser<T>>& ff,
    -
    6437 _In_ const std::shared_ptr<basic_parser<T>>& lf,
    -
    6438 _In_ const std::shared_ptr<basic_parser<T>>& cr,
    -
    6439 _In_ const std::shared_ptr<basic_parser<T>>& htab,
    -
    6440 _In_ const std::shared_ptr<basic_parser<T>>& uni,
    -
    6441 _In_ const std::shared_ptr<basic_integer16<T>>& hex,
    -
    6442 _In_ const std::locale& locale = std::locale()) :
    -
    6443 basic_parser<T>(locale),
    -
    6444 m_quote(quote),
    -
    6445 m_chr(chr),
    -
    6446 m_escape(escape),
    -
    6447 m_sol(sol),
    -
    6448 m_bs(bs),
    -
    6449 m_ff(ff),
    -
    6450 m_lf(lf),
    -
    6451 m_cr(cr),
    -
    6452 m_htab(htab),
    -
    6453 m_uni(uni),
    -
    6454 m_hex(hex)
    -
    6455 {}
    -
    6456
    -
    6457 virtual bool match(
    -
    6458 _In_reads_or_z_(end) const T* text,
    -
    6459 _In_ size_t start = 0,
    -
    6460 _In_ size_t end = (size_t)-1,
    -
    6461 _In_ int flags = match_default)
    -
    6462 {
    -
    6463 assert(text || start >= end);
    -
    6464 interval.end = start;
    -
    6465 if (m_quote->match(text, interval.end, end, flags)) {
    -
    6466 interval.end = m_quote->interval.end;
    -
    6467 value.clear();
    -
    6468 for (;;) {
    -
    6469 if (m_quote->match(text, interval.end, end, flags)) {
    -
    6470 interval.start = start;
    -
    6471 interval.end = m_quote->interval.end;
    -
    6472 return true;
    -
    6473 }
    -
    6474 if (m_escape->match(text, interval.end, end, flags)) {
    -
    6475 if (m_quote->match(text, m_escape->interval.end, end, flags)) {
    -
    6476 value += '"'; interval.end = m_quote->interval.end;
    -
    6477 continue;
    -
    6478 }
    -
    6479 if (m_sol->match(text, m_escape->interval.end, end, flags)) {
    -
    6480 value += '/'; interval.end = m_sol->interval.end;
    -
    6481 continue;
    -
    6482 }
    -
    6483 if (m_bs->match(text, m_escape->interval.end, end, flags)) {
    -
    6484 value += '\b'; interval.end = m_bs->interval.end;
    -
    6485 continue;
    -
    6486 }
    -
    6487 if (m_ff->match(text, m_escape->interval.end, end, flags)) {
    -
    6488 value += '\f'; interval.end = m_ff->interval.end;
    -
    6489 continue;
    -
    6490 }
    -
    6491 if (m_lf->match(text, m_escape->interval.end, end, flags)) {
    -
    6492 value += '\n'; interval.end = m_lf->interval.end;
    -
    6493 continue;
    -
    6494 }
    -
    6495 if (m_cr->match(text, m_escape->interval.end, end, flags)) {
    -
    6496 value += '\r'; interval.end = m_cr->interval.end;
    -
    6497 continue;
    -
    6498 }
    -
    6499 if (m_htab->match(text, m_escape->interval.end, end, flags)) {
    -
    6500 value += '\t'; interval.end = m_htab->interval.end;
    -
    6501 continue;
    -
    6502 }
    -
    6503 if (
    -
    6504 m_uni->match(text, m_escape->interval.end, end, flags) &&
    -
    6505 m_hex->match(text, m_uni->interval.end, std::min(m_uni->interval.end + 4, end), flags | match_case_insensitive) &&
    -
    6506 m_hex->interval.size() == 4 /* JSON requests 4-digit Unicode sequneces: \u.... */)
    -
    6507 {
    -
    6508 assert(m_hex->value <= 0xffff);
    -
    6509 if (sizeof(T) == 1) {
    -
    6510 if (m_hex->value > 0x7ff) {
    -
    6511 value += (T)(0xe0 | (m_hex->value >> 12) & 0x0f);
    -
    6512 value += (T)(0x80 | (m_hex->value >> 6) & 0x3f);
    -
    6513 value += (T)(0x80 | m_hex->value & 0x3f);
    -
    6514 }
    -
    6515 else if (m_hex->value > 0x7f) {
    -
    6516 value += (T)(0xc0 | (m_hex->value >> 6) & 0x1f);
    -
    6517 value += (T)(0x80 | m_hex->value & 0x3f);
    -
    6518 }
    -
    6519 else
    -
    6520 value += (T)(m_hex->value & 0x7f);
    -
    6521 }
    -
    6522 else
    -
    6523 value += (T)m_hex->value;
    -
    6524 interval.end = m_hex->interval.end;
    -
    6525 continue;
    -
    6526 }
    -
    6527 if (m_escape->match(text, m_escape->interval.end, end, flags)) {
    -
    6528 value += '\\'; interval.end = m_escape->interval.end;
    -
    6529 continue;
    -
    6530 }
    -
    6531 }
    -
    6532 if (m_chr->match(text, interval.end, end, flags)) {
    -
    6533 value.Prilepi(text + m_chr->interval.start, m_chr->interval.size());
    -
    6534 interval.end = m_chr->interval.end;
    -
    6535 continue;
    -
    6536 }
    -
    6537 break;
    -
    6538 }
    -
    6539 }
    -
    6540 value.clear();
    -
    6541 interval.start = (interval.end = start) + 1;
    -
    6542 return false;
    -
    6543 }
    -
    6544
    -
    6545 virtual void invalidate()
    -
    6546 {
    -
    6547 value.clear();
    - -
    6549 }
    -
    6550
    -
    6551 public:
    -
    6552 std::basic_string<T> value;
    +
    6419
    +
    6423 template <class T, class _Alloc = std::allocator<T>>
    + +
    6425
    +
    6429 template <class T>
    +
    + +
    6431 {
    +
    6432 public:
    + +
    6434 _In_ const std::shared_ptr<basic_parser<T>>& quote,
    +
    6435 _In_ const std::shared_ptr<basic_parser<T>>& chr,
    +
    6436 _In_ const std::shared_ptr<basic_parser<T>>& escape,
    +
    6437 _In_ const std::shared_ptr<basic_parser<T>>& sol,
    +
    6438 _In_ const std::shared_ptr<basic_parser<T>>& bs,
    +
    6439 _In_ const std::shared_ptr<basic_parser<T>>& ff,
    +
    6440 _In_ const std::shared_ptr<basic_parser<T>>& lf,
    +
    6441 _In_ const std::shared_ptr<basic_parser<T>>& cr,
    +
    6442 _In_ const std::shared_ptr<basic_parser<T>>& htab,
    +
    6443 _In_ const std::shared_ptr<basic_parser<T>>& uni,
    +
    6444 _In_ const std::shared_ptr<basic_integer16<T>>& hex,
    +
    6445 _In_ const std::locale& locale = std::locale()) :
    +
    6446 basic_parser<T>(locale),
    +
    6447 m_quote(quote),
    +
    6448 m_chr(chr),
    +
    6449 m_escape(escape),
    +
    6450 m_sol(sol),
    +
    6451 m_bs(bs),
    +
    6452 m_ff(ff),
    +
    6453 m_lf(lf),
    +
    6454 m_cr(cr),
    +
    6455 m_htab(htab),
    +
    6456 m_uni(uni),
    +
    6457 m_hex(hex)
    +
    6458 {}
    +
    6459
    +
    6460 virtual bool match(
    +
    6461 _In_reads_or_z_(end) const T* text,
    +
    6462 _In_ size_t start = 0,
    +
    6463 _In_ size_t end = (size_t)-1,
    +
    6464 _In_ int flags = match_default)
    +
    6465 {
    +
    6466 assert(text || start >= end);
    +
    6467 this->interval.end = start;
    +
    6468 if (m_quote->match(text, this->interval.end, end, flags)) {
    +
    6469 this->interval.end = m_quote->interval.end;
    +
    6470 value.clear();
    +
    6471 for (;;) {
    +
    6472 if (m_quote->match(text, this->interval.end, end, flags)) {
    +
    6473 this->interval.start = start;
    +
    6474 this->interval.end = m_quote->interval.end;
    +
    6475 return true;
    +
    6476 }
    +
    6477 if (m_escape->match(text, this->interval.end, end, flags)) {
    +
    6478 if (m_quote->match(text, m_escape->interval.end, end, flags)) {
    +
    6479 value += '"'; this->interval.end = m_quote->interval.end;
    +
    6480 continue;
    +
    6481 }
    +
    6482 if (m_sol->match(text, m_escape->interval.end, end, flags)) {
    +
    6483 value += '/'; this->interval.end = m_sol->interval.end;
    +
    6484 continue;
    +
    6485 }
    +
    6486 if (m_bs->match(text, m_escape->interval.end, end, flags)) {
    +
    6487 value += '\b'; this->interval.end = m_bs->interval.end;
    +
    6488 continue;
    +
    6489 }
    +
    6490 if (m_ff->match(text, m_escape->interval.end, end, flags)) {
    +
    6491 value += '\f'; this->interval.end = m_ff->interval.end;
    +
    6492 continue;
    +
    6493 }
    +
    6494 if (m_lf->match(text, m_escape->interval.end, end, flags)) {
    +
    6495 value += '\n'; this->interval.end = m_lf->interval.end;
    +
    6496 continue;
    +
    6497 }
    +
    6498 if (m_cr->match(text, m_escape->interval.end, end, flags)) {
    +
    6499 value += '\r'; this->interval.end = m_cr->interval.end;
    +
    6500 continue;
    +
    6501 }
    +
    6502 if (m_htab->match(text, m_escape->interval.end, end, flags)) {
    +
    6503 value += '\t'; this->interval.end = m_htab->interval.end;
    +
    6504 continue;
    +
    6505 }
    +
    6506 if (
    +
    6507 m_uni->match(text, m_escape->interval.end, end, flags) &&
    +
    6508 m_hex->match(text, m_uni->interval.end, std::min(m_uni->interval.end + 4, end), flags | match_case_insensitive) &&
    +
    6509 m_hex->interval.size() == 4 /* JSON requests 4-digit Unicode sequneces: \u.... */)
    +
    6510 {
    +
    6511 assert(m_hex->value <= 0xffff);
    +
    6512 if (sizeof(T) == 1) {
    +
    6513 if (m_hex->value > 0x7ff) {
    +
    6514 value += (T)(0xe0 | ((m_hex->value >> 12) & 0x0f));
    +
    6515 value += (T)(0x80 | ((m_hex->value >> 6) & 0x3f));
    +
    6516 value += (T)(0x80 | (m_hex->value & 0x3f));
    +
    6517 }
    +
    6518 else if (m_hex->value > 0x7f) {
    +
    6519 value += (T)(0xc0 | ((m_hex->value >> 6) & 0x1f));
    +
    6520 value += (T)(0x80 | (m_hex->value & 0x3f));
    +
    6521 }
    +
    6522 else
    +
    6523 value += (T)(m_hex->value & 0x7f);
    +
    6524 }
    +
    6525 else
    +
    6526 value += (T)m_hex->value;
    +
    6527 this->interval.end = m_hex->interval.end;
    +
    6528 continue;
    +
    6529 }
    +
    6530 if (m_escape->match(text, m_escape->interval.end, end, flags)) {
    +
    6531 value += '\\'; this->interval.end = m_escape->interval.end;
    +
    6532 continue;
    +
    6533 }
    +
    6534 }
    +
    6535 if (m_chr->match(text, this->interval.end, end, flags)) {
    +
    6536 value.Prilepi(text + m_chr->interval.start, m_chr->interval.size());
    +
    6537 this->interval.end = m_chr->interval.end;
    +
    6538 continue;
    +
    6539 }
    +
    6540 break;
    +
    6541 }
    +
    6542 }
    +
    6543 value.clear();
    +
    6544 this->interval.start = (this->interval.end = start) + 1;
    +
    6545 return false;
    +
    6546 }
    +
    6547
    +
    6548 virtual void invalidate()
    +
    6549 {
    +
    6550 value.clear();
    + +
    6552 }
    6553
    -
    6554 protected:
    -
    6555 std::shared_ptr<basic_parser<T>> m_quote;
    -
    6556 std::shared_ptr<basic_parser<T>> m_chr;
    -
    6557 std::shared_ptr<basic_parser<T>> m_escape;
    -
    6558 std::shared_ptr<basic_parser<T>> m_sol;
    -
    6559 std::shared_ptr<basic_parser<T>> m_bs;
    -
    6560 std::shared_ptr<basic_parser<T>> m_ff;
    -
    6561 std::shared_ptr<basic_parser<T>> m_lf;
    -
    6562 std::shared_ptr<basic_parser<T>> m_cr;
    -
    6563 std::shared_ptr<basic_parser<T>> m_htab;
    -
    6564 std::shared_ptr<basic_parser<T>> m_uni;
    -
    6565 std::shared_ptr<basic_integer16<T>> m_hex;
    -
    6566 };
    +
    6554 public:
    +
    6555 std::basic_string<T> value;
    +
    6556
    +
    6557 protected:
    +
    6558 std::shared_ptr<basic_parser<T>> m_quote;
    +
    6559 std::shared_ptr<basic_parser<T>> m_chr;
    +
    6560 std::shared_ptr<basic_parser<T>> m_escape;
    +
    6561 std::shared_ptr<basic_parser<T>> m_sol;
    +
    6562 std::shared_ptr<basic_parser<T>> m_bs;
    +
    6563 std::shared_ptr<basic_parser<T>> m_ff;
    +
    6564 std::shared_ptr<basic_parser<T>> m_lf;
    +
    6565 std::shared_ptr<basic_parser<T>> m_cr;
    +
    6566 std::shared_ptr<basic_parser<T>> m_htab;
    +
    6567 std::shared_ptr<basic_parser<T>> m_uni;
    +
    6568 std::shared_ptr<basic_integer16<T>> m_hex;
    +
    6569 };
    -
    6567
    - - -
    6570#ifdef _UNICODE
    -
    6571 using tjson_string = wjson_string;
    -
    6572#else
    -
    6573 using tjson_string = json_string;
    -
    6574#endif
    -
    6575 }
    -
    6576}
    -
    6577
    -
    6578#undef ENUM_FLAG_OPERATOR
    -
    6579#undef ENUM_FLAGS
    +
    6570
    + + +
    6573#ifdef _UNICODE
    +
    6574 using tjson_string = wjson_string;
    +
    6575#else
    +
    6576 using tjson_string = json_string;
    +
    6577#endif
    +
    6578 }
    +
    6579}
    6580
    -
    6581#ifdef _MSC_VER
    -
    6582#pragma warning(pop)
    -
    6583#endif
    -
    Test for angle in d°mm'ss.dddd form.
    Definition parser.hpp:4392
    -
    Test for any code unit.
    Definition parser.hpp:219
    -
    Test for beginning of line.
    Definition parser.hpp:613
    -
    Test for any.
    Definition parser.hpp:1055
    -
    Test for chemical formula.
    Definition parser.hpp:4666
    -
    Test for any code unit from a given string of code units.
    Definition parser.hpp:718
    -
    Test for specific code unit.
    Definition parser.hpp:289
    -
    Test for date.
    Definition parser.hpp:4022
    -
    Test for valid DNS domain character.
    Definition parser.hpp:2803
    -
    bool allow_on_edge
    Is character allowed at the beginning or an end of a DNS domain?
    Definition parser.hpp:2841
    -
    Test for DNS domain/hostname.
    Definition parser.hpp:2903
    -
    bool m_allow_absolute
    May DNS names end with a dot (absolute name)?
    Definition parser.hpp:2967
    -
    Test for e-mail address.
    Definition parser.hpp:3791
    -
    Test for emoticon.
    Definition parser.hpp:3899
    -
    std::shared_ptr< basic_parser< T > > apex
    apex/eyebrows/halo (e.g. O, 0)
    Definition parser.hpp:3988
    -
    std::shared_ptr< basic_parser< T > > eyes
    eyes (e.g. :, ;, >, |, B)
    Definition parser.hpp:3989
    -
    std::shared_ptr< basic_set< T > > mouth
    mouth (e.g. ), ), (, (, |, P, D, p, d)
    Definition parser.hpp:3991
    -
    std::shared_ptr< basic_parser< T > > nose
    nose (e.g. -, o)
    Definition parser.hpp:3990
    -
    std::shared_ptr< basic_parser< T > > emoticon
    emoticon as a whole (e.g. 😀, 🤔, 😶)
    Definition parser.hpp:3987
    -
    Test for end of line.
    Definition parser.hpp:651
    -
    Test for fraction.
    Definition parser.hpp:1684
    -
    Test for decimal integer.
    Definition parser.hpp:1293
    -
    Test for decimal integer possibly containing thousand separators.
    Definition parser.hpp:1378
    -
    bool has_separators
    Did integer have any separators?
    Definition parser.hpp:1438
    -
    size_t digit_count
    Total number of digits in integer.
    Definition parser.hpp:1437
    -
    Test for hexadecimal integer.
    Definition parser.hpp:1459
    -
    Base class for integer testing.
    Definition parser.hpp:1271
    -
    size_t value
    Calculated value of the numeral.
    Definition parser.hpp:1285
    -
    Test for IPv4 address.
    Definition parser.hpp:2343
    -
    stdex::interval< size_t > components[4]
    Individual component intervals.
    Definition parser.hpp:2458
    -
    struct in_addr value
    IPv4 address value.
    Definition parser.hpp:2459
    -
    Test for IPv6 address.
    Definition parser.hpp:2562
    -
    std::shared_ptr< basic_parser< T > > scope_id
    Scope ID (e.g. NIC index with link-local addresses)
    Definition parser.hpp:2766
    -
    stdex::interval< size_t > components[8]
    Individual component intervals.
    Definition parser.hpp:2764
    -
    struct in6_addr value
    IPv6 address value.
    Definition parser.hpp:2765
    -
    Test for valid IPv6 address scope ID character.
    Definition parser.hpp:2490
    -
    Test for repeating.
    Definition parser.hpp:908
    -
    bool m_greedy
    try to match as long sequence as possible
    Definition parser.hpp:947
    -
    std::shared_ptr< basic_parser< T > > m_el
    repeating element
    Definition parser.hpp:944
    -
    size_t m_min_iterations
    minimum number of iterations
    Definition parser.hpp:945
    -
    size_t m_max_iterations
    maximum number of iterations
    Definition parser.hpp:946
    -
    Test for JSON string.
    Definition parser.hpp:6428
    -
    Test for mixed numeral.
    Definition parser.hpp:1919
    -
    std::shared_ptr< basic_parser< T > > fraction
    fraction
    Definition parser.hpp:2025
    -
    std::shared_ptr< basic_parser< T > > special_sign
    Special sign (e.g. plus-minus '±')
    Definition parser.hpp:2023
    -
    std::shared_ptr< basic_parser< T > > negative_sign
    Negative sign.
    Definition parser.hpp:2022
    -
    std::shared_ptr< basic_parser< T > > positive_sign
    Positive sign.
    Definition parser.hpp:2021
    -
    std::shared_ptr< basic_parser< T > > integer
    Integer part.
    Definition parser.hpp:2024
    -
    Test for monetary numeral.
    Definition parser.hpp:2214
    -
    std::shared_ptr< basic_parser< T > > positive_sign
    Positive sign.
    Definition parser.hpp:2320
    -
    std::shared_ptr< basic_parser< T > > decimal_separator
    Decimal separator.
    Definition parser.hpp:2325
    -
    std::shared_ptr< basic_parser< T > > currency
    Currency part.
    Definition parser.hpp:2323
    -
    std::shared_ptr< basic_parser< T > > decimal
    Decimal part.
    Definition parser.hpp:2326
    -
    std::shared_ptr< basic_parser< T > > integer
    Integer part.
    Definition parser.hpp:2324
    -
    std::shared_ptr< basic_parser< T > > negative_sign
    Negative sign.
    Definition parser.hpp:2321
    -
    std::shared_ptr< basic_parser< T > > special_sign
    Special sign (e.g. plus-minus '±')
    Definition parser.hpp:2322
    -
    "No-op" match
    Definition parser.hpp:187
    -
    Base template for all parsers.
    Definition parser.hpp:68
    -
    interval< size_t > interval
    Region of the last match.
    Definition parser.hpp:167
    -
    Test for permutation.
    Definition parser.hpp:1195
    -
    Test for phone number.
    Definition parser.hpp:4515
    -
    std::basic_string< T > value
    Normalized phone number.
    Definition parser.hpp:4641
    -
    Test for any punctuation code unit.
    Definition parser.hpp:461
    -
    Test for Roman numeral.
    Definition parser.hpp:1568
    -
    Test for scientific numeral.
    Definition parser.hpp:2045
    -
    std::shared_ptr< basic_parser< T > > special_sign
    Special sign (e.g. plus-minus '±')
    Definition parser.hpp:2189
    -
    std::shared_ptr< basic_parser< T > > exponent_symbol
    Exponent symbol (e.g. 'e')
    Definition parser.hpp:2193
    -
    std::shared_ptr< basic_parser< T > > positive_sign
    Positive sign.
    Definition parser.hpp:2187
    -
    std::shared_ptr< basic_parser< T > > negative_sign
    Negative sign.
    Definition parser.hpp:2188
    -
    double value
    Calculated value of the numeral.
    Definition parser.hpp:2197
    -
    std::shared_ptr< basic_parser< T > > negative_exp_sign
    Negative exponent sign (e.g. '-')
    Definition parser.hpp:2195
    -
    std::shared_ptr< basic_integer< T > > decimal
    Decimal part.
    Definition parser.hpp:2192
    -
    std::shared_ptr< basic_parser< T > > positive_exp_sign
    Positive exponent sign (e.g. '+')
    Definition parser.hpp:2194
    -
    std::shared_ptr< basic_integer< T > > exponent
    Exponent part.
    Definition parser.hpp:2196
    -
    std::shared_ptr< basic_parser< T > > decimal_separator
    Decimal separator.
    Definition parser.hpp:2191
    -
    std::shared_ptr< basic_integer< T > > integer
    Integer part.
    Definition parser.hpp:2190
    -
    Test for match score.
    Definition parser.hpp:1747
    -
    Test for sequence.
    Definition parser.hpp:1004
    -
    Definition parser.hpp:686
    -
    Test for signed numeral.
    Definition parser.hpp:1833
    -
    std::shared_ptr< basic_parser< T > > special_sign
    Special sign (e.g. plus-minus '±')
    Definition parser.hpp:1901
    -
    std::shared_ptr< basic_parser< T > > negative_sign
    Negative sign.
    Definition parser.hpp:1900
    -
    std::shared_ptr< basic_parser< T > > positive_sign
    Positive sign.
    Definition parser.hpp:1899
    -
    std::shared_ptr< basic_parser< T > > number
    Number.
    Definition parser.hpp:1902
    -
    Test for any space code unit.
    Definition parser.hpp:382
    -
    Test for any space or punctuation code unit.
    Definition parser.hpp:535
    -
    Test for any string.
    Definition parser.hpp:1123
    -
    Test for given string.
    Definition parser.hpp:813
    -
    Test for time.
    Definition parser.hpp:4289
    -
    Test for valid URL password character.
    Definition parser.hpp:3085
    -
    Test for valid URL path character.
    Definition parser.hpp:3185
    -
    Test for URL path.
    Definition parser.hpp:3293
    -
    Test for valid URL username character.
    Definition parser.hpp:2986
    -
    Test for URL.
    Definition parser.hpp:3434
    -
    Test for HTTP agent.
    Definition parser.hpp:5951
    -
    Test for HTTP any type.
    Definition parser.hpp:5073
    -
    Test for HTTP asterisk.
    Definition parser.hpp:5715
    - - - - - -
    Test for HTTP header.
    Definition parser.hpp:6274
    -
    Test for HTTP language (RFC1766)
    Definition parser.hpp:5583
    -
    Test for HTTP line break (RFC2616: CRLF | LF)
    Definition parser.hpp:4747
    -
    Test for HTTP media range (RFC2616: media-range)
    Definition parser.hpp:5105
    -
    Test for HTTP media type (RFC2616: media-type)
    Definition parser.hpp:5160
    -
    Test for HTTP parameter (RFC2616: parameter)
    Definition parser.hpp:5018
    -
    http_token name
    Parameter name.
    Definition parser.hpp:5062
    -
    http_value value
    Parameter value.
    Definition parser.hpp:5063
    -
    Test for HTTP protocol.
    Definition parser.hpp:6027
    -
    uint16_t version
    HTTP protocol version: 0x100 = 1.0, 0x101 = 1.1...
    Definition parser.hpp:6129
    -
    Test for HTTP quoted string (RFC2616: quoted-string)
    Definition parser.hpp:4908
    -
    stdex::interval< size_t > content
    String content (without quotes)
    Definition parser.hpp:4964
    -
    Test for HTTP request.
    Definition parser.hpp:6136
    -
    Test for HTTP space (RFC2616: LWS)
    Definition parser.hpp:4783
    -
    Test for HTTP text character (RFC2616: TEXT)
    Definition parser.hpp:4820
    -
    Test for HTTP token (RFC2616: token - tolerates non-ASCII)
    Definition parser.hpp:4854
    -
    Test for HTTP URL parameter.
    Definition parser.hpp:5400
    -
    Test for HTTP URL path segment.
    Definition parser.hpp:5311
    -
    Test for HTTP URL path segment.
    Definition parser.hpp:5344
    -
    std::vector< http_url_path_segment > segments
    Path segments.
    Definition parser.hpp:5393
    -
    Test for HTTP URL port.
    Definition parser.hpp:5255
    -
    Test for HTTP URL server.
    Definition parser.hpp:5218
    -
    Test for HTTP URL.
    Definition parser.hpp:5481
    -
    Collection of HTTP values.
    Definition parser.hpp:6384
    -
    Test for HTTP value (RFC2616: value)
    Definition parser.hpp:4974
    -
    http_quoted_string string
    Value when matched as quoted string.
    Definition parser.hpp:5010
    -
    http_token token
    Value when matched as token.
    Definition parser.hpp:5011
    -
    Test for HTTP weight factor.
    Definition parser.hpp:5646
    -
    float value
    Calculated value of the weight factor.
    Definition parser.hpp:5708
    -
    Test for HTTP weighted value.
    Definition parser.hpp:5738
    -
    Base template for collection-holding parsers.
    Definition parser.hpp:964
    -
    Test for any SGML code point.
    Definition parser.hpp:251
    -
    Test for any SGML code point from a given string of SGML code points.
    Definition parser.hpp:770
    -
    Test for specific SGML code point.
    Definition parser.hpp:338
    -
    Test for valid DNS domain SGML character.
    Definition parser.hpp:2859
    -
    Test for valid IPv6 address scope ID SGML character.
    Definition parser.hpp:2528
    -
    Test for any SGML punctuation code point.
    Definition parser.hpp:502
    -
    Test for any SGML space code point.
    Definition parser.hpp:425
    -
    Test for any SGML space or punctuation code point.
    Definition parser.hpp:578
    -
    Test for SGML given string.
    Definition parser.hpp:860
    -
    Test for valid URL password SGML character.
    Definition parser.hpp:3137
    -
    Test for valid URL path SGML character.
    Definition parser.hpp:3241
    -
    Test for valid URL username SGML character.
    Definition parser.hpp:3037
    +
    6581#undef ENUM_FLAG_OPERATOR
    +
    6582#undef ENUM_FLAGS
    +
    6583
    +
    6584#ifdef _MSC_VER
    +
    6585#pragma warning(pop)
    +
    6586#endif
    +
    Test for angle in d°mm'ss.dddd form.
    Definition parser.hpp:4395
    +
    Test for any code unit.
    Definition parser.hpp:221
    +
    Test for beginning of line.
    Definition parser.hpp:615
    +
    Test for any.
    Definition parser.hpp:1057
    +
    Test for chemical formula.
    Definition parser.hpp:4669
    +
    Test for any code unit from a given string of code units.
    Definition parser.hpp:720
    +
    Test for specific code unit.
    Definition parser.hpp:291
    +
    Test for date.
    Definition parser.hpp:4025
    +
    Test for valid DNS domain character.
    Definition parser.hpp:2806
    +
    bool allow_on_edge
    Is character allowed at the beginning or an end of a DNS domain?
    Definition parser.hpp:2844
    +
    Test for DNS domain/hostname.
    Definition parser.hpp:2906
    +
    bool m_allow_absolute
    May DNS names end with a dot (absolute name)?
    Definition parser.hpp:2970
    +
    Test for e-mail address.
    Definition parser.hpp:3794
    +
    Test for emoticon.
    Definition parser.hpp:3902
    +
    std::shared_ptr< basic_parser< T > > apex
    apex/eyebrows/halo (e.g. O, 0)
    Definition parser.hpp:3991
    +
    std::shared_ptr< basic_parser< T > > eyes
    eyes (e.g. :, ;, >, |, B)
    Definition parser.hpp:3992
    +
    std::shared_ptr< basic_set< T > > mouth
    mouth (e.g. ), ), (, (, |, P, D, p, d)
    Definition parser.hpp:3994
    +
    std::shared_ptr< basic_parser< T > > nose
    nose (e.g. -, o)
    Definition parser.hpp:3993
    +
    std::shared_ptr< basic_parser< T > > emoticon
    emoticon as a whole (e.g. 😀, 🤔, 😶)
    Definition parser.hpp:3990
    +
    Test for end of line.
    Definition parser.hpp:653
    +
    Test for fraction.
    Definition parser.hpp:1686
    +
    Test for decimal integer.
    Definition parser.hpp:1295
    +
    Test for decimal integer possibly containing thousand separators.
    Definition parser.hpp:1380
    +
    bool has_separators
    Did integer have any separators?
    Definition parser.hpp:1440
    +
    size_t digit_count
    Total number of digits in integer.
    Definition parser.hpp:1439
    +
    Test for hexadecimal integer.
    Definition parser.hpp:1461
    +
    Base class for integer testing.
    Definition parser.hpp:1273
    +
    size_t value
    Calculated value of the numeral.
    Definition parser.hpp:1287
    +
    Test for IPv4 address.
    Definition parser.hpp:2346
    +
    stdex::interval< size_t > components[4]
    Individual component intervals.
    Definition parser.hpp:2461
    +
    struct in_addr value
    IPv4 address value.
    Definition parser.hpp:2462
    +
    Test for IPv6 address.
    Definition parser.hpp:2565
    +
    std::shared_ptr< basic_parser< T > > scope_id
    Scope ID (e.g. NIC index with link-local addresses)
    Definition parser.hpp:2769
    +
    stdex::interval< size_t > components[8]
    Individual component intervals.
    Definition parser.hpp:2767
    +
    struct in6_addr value
    IPv6 address value.
    Definition parser.hpp:2768
    +
    Test for valid IPv6 address scope ID character.
    Definition parser.hpp:2493
    +
    Test for repeating.
    Definition parser.hpp:910
    +
    bool m_greedy
    try to match as long sequence as possible
    Definition parser.hpp:949
    +
    std::shared_ptr< basic_parser< T > > m_el
    repeating element
    Definition parser.hpp:946
    +
    size_t m_min_iterations
    minimum number of iterations
    Definition parser.hpp:947
    +
    size_t m_max_iterations
    maximum number of iterations
    Definition parser.hpp:948
    +
    Test for JSON string.
    Definition parser.hpp:6431
    +
    Test for mixed numeral.
    Definition parser.hpp:1922
    +
    std::shared_ptr< basic_parser< T > > fraction
    fraction
    Definition parser.hpp:2028
    +
    std::shared_ptr< basic_parser< T > > special_sign
    Special sign (e.g. plus-minus '±')
    Definition parser.hpp:2026
    +
    std::shared_ptr< basic_parser< T > > negative_sign
    Negative sign.
    Definition parser.hpp:2025
    +
    std::shared_ptr< basic_parser< T > > positive_sign
    Positive sign.
    Definition parser.hpp:2024
    +
    std::shared_ptr< basic_parser< T > > integer
    Integer part.
    Definition parser.hpp:2027
    +
    Test for monetary numeral.
    Definition parser.hpp:2217
    +
    std::shared_ptr< basic_parser< T > > positive_sign
    Positive sign.
    Definition parser.hpp:2323
    +
    std::shared_ptr< basic_parser< T > > decimal_separator
    Decimal separator.
    Definition parser.hpp:2328
    +
    std::shared_ptr< basic_parser< T > > currency
    Currency part.
    Definition parser.hpp:2326
    +
    std::shared_ptr< basic_parser< T > > decimal
    Decimal part.
    Definition parser.hpp:2329
    +
    std::shared_ptr< basic_parser< T > > integer
    Integer part.
    Definition parser.hpp:2327
    +
    std::shared_ptr< basic_parser< T > > negative_sign
    Negative sign.
    Definition parser.hpp:2324
    +
    std::shared_ptr< basic_parser< T > > special_sign
    Special sign (e.g. plus-minus '±')
    Definition parser.hpp:2325
    +
    "No-op" match
    Definition parser.hpp:189
    +
    Base template for all parsers.
    Definition parser.hpp:70
    +
    interval< size_t > interval
    Region of the last match.
    Definition parser.hpp:169
    +
    Test for permutation.
    Definition parser.hpp:1197
    +
    Test for phone number.
    Definition parser.hpp:4518
    +
    std::basic_string< T > value
    Normalized phone number.
    Definition parser.hpp:4644
    +
    Test for any punctuation code unit.
    Definition parser.hpp:463
    +
    Test for Roman numeral.
    Definition parser.hpp:1570
    +
    Test for scientific numeral.
    Definition parser.hpp:2048
    +
    std::shared_ptr< basic_parser< T > > special_sign
    Special sign (e.g. plus-minus '±')
    Definition parser.hpp:2192
    +
    std::shared_ptr< basic_parser< T > > exponent_symbol
    Exponent symbol (e.g. 'e')
    Definition parser.hpp:2196
    +
    std::shared_ptr< basic_parser< T > > positive_sign
    Positive sign.
    Definition parser.hpp:2190
    +
    std::shared_ptr< basic_parser< T > > negative_sign
    Negative sign.
    Definition parser.hpp:2191
    +
    double value
    Calculated value of the numeral.
    Definition parser.hpp:2200
    +
    std::shared_ptr< basic_parser< T > > negative_exp_sign
    Negative exponent sign (e.g. '-')
    Definition parser.hpp:2198
    +
    std::shared_ptr< basic_integer< T > > decimal
    Decimal part.
    Definition parser.hpp:2195
    +
    std::shared_ptr< basic_parser< T > > positive_exp_sign
    Positive exponent sign (e.g. '+')
    Definition parser.hpp:2197
    +
    std::shared_ptr< basic_integer< T > > exponent
    Exponent part.
    Definition parser.hpp:2199
    +
    std::shared_ptr< basic_parser< T > > decimal_separator
    Decimal separator.
    Definition parser.hpp:2194
    +
    std::shared_ptr< basic_integer< T > > integer
    Integer part.
    Definition parser.hpp:2193
    +
    Test for match score.
    Definition parser.hpp:1749
    +
    Test for sequence.
    Definition parser.hpp:1006
    +
    Definition parser.hpp:688
    +
    Test for signed numeral.
    Definition parser.hpp:1836
    +
    std::shared_ptr< basic_parser< T > > special_sign
    Special sign (e.g. plus-minus '±')
    Definition parser.hpp:1904
    +
    std::shared_ptr< basic_parser< T > > negative_sign
    Negative sign.
    Definition parser.hpp:1903
    +
    std::shared_ptr< basic_parser< T > > positive_sign
    Positive sign.
    Definition parser.hpp:1902
    +
    std::shared_ptr< basic_parser< T > > number
    Number.
    Definition parser.hpp:1905
    +
    Test for any space code unit.
    Definition parser.hpp:384
    +
    Test for any space or punctuation code unit.
    Definition parser.hpp:537
    +
    Test for any string.
    Definition parser.hpp:1125
    +
    Test for given string.
    Definition parser.hpp:815
    +
    Test for time.
    Definition parser.hpp:4292
    +
    Test for valid URL password character.
    Definition parser.hpp:3088
    +
    Test for valid URL path character.
    Definition parser.hpp:3188
    +
    Test for URL path.
    Definition parser.hpp:3296
    +
    Test for valid URL username character.
    Definition parser.hpp:2989
    +
    Test for URL.
    Definition parser.hpp:3437
    +
    Test for HTTP agent.
    Definition parser.hpp:5954
    +
    Test for HTTP any type.
    Definition parser.hpp:5076
    +
    Test for HTTP asterisk.
    Definition parser.hpp:5718
    + + + + + +
    Test for HTTP header.
    Definition parser.hpp:6277
    +
    Test for HTTP language (RFC1766)
    Definition parser.hpp:5586
    +
    Test for HTTP line break (RFC2616: CRLF | LF)
    Definition parser.hpp:4750
    +
    Test for HTTP media range (RFC2616: media-range)
    Definition parser.hpp:5108
    +
    Test for HTTP media type (RFC2616: media-type)
    Definition parser.hpp:5163
    +
    Test for HTTP parameter (RFC2616: parameter)
    Definition parser.hpp:5021
    +
    http_token name
    Parameter name.
    Definition parser.hpp:5065
    +
    http_value value
    Parameter value.
    Definition parser.hpp:5066
    +
    Test for HTTP protocol.
    Definition parser.hpp:6030
    +
    uint16_t version
    HTTP protocol version: 0x100 = 1.0, 0x101 = 1.1...
    Definition parser.hpp:6132
    +
    Test for HTTP quoted string (RFC2616: quoted-string)
    Definition parser.hpp:4911
    +
    stdex::interval< size_t > content
    String content (without quotes)
    Definition parser.hpp:4967
    +
    Test for HTTP request.
    Definition parser.hpp:6139
    +
    Test for HTTP space (RFC2616: LWS)
    Definition parser.hpp:4786
    +
    Test for HTTP text character (RFC2616: TEXT)
    Definition parser.hpp:4823
    +
    Test for HTTP token (RFC2616: token - tolerates non-ASCII)
    Definition parser.hpp:4857
    +
    Test for HTTP URL parameter.
    Definition parser.hpp:5403
    +
    Test for HTTP URL path segment.
    Definition parser.hpp:5314
    +
    Test for HTTP URL path segment.
    Definition parser.hpp:5347
    +
    std::vector< http_url_path_segment > segments
    Path segments.
    Definition parser.hpp:5396
    +
    Test for HTTP URL port.
    Definition parser.hpp:5258
    +
    Test for HTTP URL server.
    Definition parser.hpp:5221
    +
    Test for HTTP URL.
    Definition parser.hpp:5484
    +
    Collection of HTTP values.
    Definition parser.hpp:6387
    +
    Test for HTTP value (RFC2616: value)
    Definition parser.hpp:4977
    +
    http_quoted_string string
    Value when matched as quoted string.
    Definition parser.hpp:5013
    +
    http_token token
    Value when matched as token.
    Definition parser.hpp:5014
    +
    Test for HTTP weight factor.
    Definition parser.hpp:5649
    +
    float value
    Calculated value of the weight factor.
    Definition parser.hpp:5711
    +
    Test for HTTP weighted value.
    Definition parser.hpp:5741
    +
    Base template for collection-holding parsers.
    Definition parser.hpp:966
    +
    Test for any SGML code point.
    Definition parser.hpp:253
    +
    Test for any SGML code point from a given string of SGML code points.
    Definition parser.hpp:772
    +
    Test for specific SGML code point.
    Definition parser.hpp:340
    +
    Test for valid DNS domain SGML character.
    Definition parser.hpp:2862
    +
    Test for valid IPv6 address scope ID SGML character.
    Definition parser.hpp:2531
    +
    Test for any SGML punctuation code point.
    Definition parser.hpp:504
    +
    Test for any SGML space code point.
    Definition parser.hpp:427
    +
    Test for any SGML space or punctuation code point.
    Definition parser.hpp:580
    +
    Test for SGML given string.
    Definition parser.hpp:862
    +
    Test for valid URL password SGML character.
    Definition parser.hpp:3140
    +
    Test for valid URL path SGML character.
    Definition parser.hpp:3244
    +
    Test for valid URL username SGML character.
    Definition parser.hpp:3040
    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:6410
    +
    Definition parser.hpp:6413
    diff --git a/pch_8h_source.html b/pch_8h_source.html index 378219520..2054bb3e1 100644 --- a/pch_8h_source.html +++ b/pch_8h_source.html @@ -5,7 +5,7 @@ -stdex: win/UnitTests/pch.h Source File +stdex: UnitTests/pch.h Source File @@ -75,7 +75,7 @@ $(document).ready(function() { init_codefold(0); });
    @@ -90,17 +90,17 @@ $(document).ready(function() { init_codefold(0); });
    6#pragma once
    7
    8#include <stdex/base64.hpp>
    -
    9#include <stdex/errno.hpp>
    -
    10#include <stdex/exception.hpp>
    -
    11#include <stdex/hex.hpp>
    -
    12#include <stdex/idrec.hpp>
    -
    13#include <stdex/interval.hpp>
    -
    14#include <stdex/mapping.hpp>
    -
    15#include <stdex/math.hpp>
    -
    16#include <stdex/parser.hpp>
    -
    17#include <stdex/progress.hpp>
    -
    18#include <stdex/ring.hpp>
    -
    19#include <stdex/sal.hpp>
    +
    9#include <stdex/compat.hpp>
    +
    10#include <stdex/errno.hpp>
    +
    11#include <stdex/exception.hpp>
    +
    12#include <stdex/hex.hpp>
    +
    13#include <stdex/idrec.hpp>
    +
    14#include <stdex/interval.hpp>
    +
    15#include <stdex/mapping.hpp>
    +
    16#include <stdex/math.hpp>
    +
    17#include <stdex/parser.hpp>
    +
    18#include <stdex/progress.hpp>
    +
    19#include <stdex/ring.hpp>
    20#include <stdex/sgml.hpp>
    21#include <stdex/stream.hpp>
    22#include <stdex/string.hpp>
    @@ -108,7 +108,7 @@ $(document).ready(function() { init_codefold(0); });
    24#include <stdex/unicode.hpp>
    25#include <stdex/vector_queue.hpp>
    26
    -
    27#include <CppUnitTest.h>
    +
    27#include "compat.hpp"
    28
    29#include <cstdlib>
    30#include <filesystem>
    @@ -116,7 +116,7 @@ $(document).ready(function() { init_codefold(0); });
    diff --git a/progress_8hpp_source.html b/progress_8hpp_source.html index ae76109e3..2b34f855e 100644 --- a/progress_8hpp_source.html +++ b/progress_8hpp_source.html @@ -89,7 +89,7 @@ $(document).ready(function() { init_codefold(0); });
    5
    6#pragma once
    7
    -
    8#include "sal.hpp"
    +
    8#include "compat.hpp"
    9#include "interval.hpp"
    10#include <chrono>
    11
    @@ -103,7 +103,7 @@ $(document).ready(function() { init_codefold(0); });
    26 virtual void set_text(_In_z_ const char* msg)
    27 {
    -
    28 msg;
    +
    28 _Unreferenced_(msg);
    29 }
    30
    @@ -124,7 +124,7 @@ $(document).ready(function() { init_codefold(0); });
    57 virtual void show(_In_ bool show = true)
    58 {
    -
    59 show;
    +
    59 _Unreferenced_(show);
    60 }
    61
    @@ -207,7 +207,7 @@ $(document).ready(function() { init_codefold(0); });
    170 {
    -
    171 progress* k = m_host;
    +
    171 progress<T>* k = m_host;
    172 m_host = NULL;
    173 return k;
    174 }
    @@ -219,7 +219,7 @@ $(document).ready(function() { init_codefold(0); });
    184 m_global.start = start;
    185 m_global.end = end;
    186 if (m_host)
    -
    187 m_host->set_range(m_global.start, m_global.end);
    +
    187 m_host->set_range(m_global.start, m_global.end);
    188 }
    189
    @@ -235,7 +235,7 @@ $(document).ready(function() { init_codefold(0); });
    207 virtual void set_text(_In_ const char* msg)
    208 {
    209 if (m_host)
    -
    210 m_host->set_text(msg);
    +
    210 m_host->set_text(msg);
    211 }
    212
    @@ -254,7 +254,7 @@ $(document).ready(function() { init_codefold(0); });
    233 T size = m_local.size();
    234 if (size != 0) {
    235 // TODO: Implement with muldiv.
    -
    236 m_host->set(((value - m_local.start) * m_section.size() / size) + m_section.start);
    +
    236 m_host->set(((value - m_local.start) * m_section.size() / size) + m_section.start);
    237 }
    238 }
    239 }
    @@ -264,19 +264,19 @@ $(document).ready(function() { init_codefold(0); });
    246 virtual void show(_In_ bool show = true)
    247 {
    248 if (m_host)
    -
    249 m_host->show(show);
    +
    249 m_host->show(show);
    250 }
    251
    255 virtual bool cancel()
    256 {
    -
    257 return m_host && m_host->cancel();
    +
    257 return m_host && m_host->cancel();
    258 }
    259
    260 protected:
    -
    261 progress* m_host;
    +
    261 progress<T>* m_host;
    262 interval<T> m_local, m_global, m_section;
    263 };
    @@ -296,7 +296,7 @@ $(document).ready(function() { init_codefold(0); });
    281
    283 {
    -
    284 m_host_ref = detach();
    +
    284 m_host_ref = this->detach();
    285 }
    286
    287 protected:
    @@ -331,7 +331,7 @@ $(document).ready(function() { init_codefold(0); });
    diff --git a/ring_8cpp_source.html b/ring_8cpp_source.html new file mode 100644 index 000000000..440ec39e9 --- /dev/null +++ b/ring_8cpp_source.html @@ -0,0 +1,150 @@ + + + + + + + +stdex: UnitTests/ring.cpp Source File + + + + + + + + + +
    +
    + + + + + + +
    +
    stdex +
    +
    Additional custom or not Standard C++ covered algorithms
    +
    +
    + + + + + + + + + +
    +
    + + +
    +
    +
    +
    +
    +
    Loading...
    +
    Searching...
    +
    No Matches
    +
    +
    +
    +
    + + +
    +
    +
    ring.cpp
    +
    +
    +
    1/*
    +
    2 SPDX-License-Identifier: MIT
    +
    3 Copyright © 2023 Amebis
    +
    4*/
    +
    5
    +
    6#include "pch.h"
    +
    7
    +
    8using namespace std;
    +
    9#ifdef _WIN32
    +
    10using namespace Microsoft::VisualStudio::CppUnitTestFramework;
    +
    11#endif
    +
    12
    +
    13namespace UnitTests
    +
    14{
    +
    15 constexpr size_t capacity = 50;
    +
    16
    +
    17 TEST_CLASS(ring)
    +
    18 {
    +
    19 public:
    +
    20 TEST_METHOD(test)
    +
    21 {
    +
    22 using ring_t = stdex::ring<int, capacity>;
    +
    23 ring_t ring;
    +
    24 thread writer([](_Inout_ ring_t& ring)
    +
    25 {
    +
    26 int seed = 0;
    +
    27 for (size_t retries = 1000; retries--;) {
    +
    28 for (auto to_write = static_cast<size_t>(static_cast<uint64_t>(::rand()) * capacity / 5 / RAND_MAX); to_write;) {
    +
    29 int* ptr; size_t num_write;
    +
    30 tie(ptr, num_write) = ring.back();
    +
    31 if (to_write < num_write)
    +
    32 num_write = to_write;
    +
    33 for (size_t i = 0; i < num_write; i++)
    +
    34 ptr[i] = seed++;
    +
    35 ring.push(num_write);
    +
    36 to_write -= num_write;
    +
    37 }
    +
    38 }
    +
    39 ring.quit();
    +
    40 }, ref(ring));
    +
    41
    +
    42 int seed = 0;
    +
    43 for (;;) {
    +
    44 int* ptr; size_t num_read;
    +
    45 tie(ptr, num_read) = ring.front();
    +
    46 if (!ptr) _Unlikely_
    +
    47 break;
    +
    48 if (num_read > 7)
    +
    49 num_read = 7;
    +
    50 for (size_t i = 0; i < num_read; ++i)
    +
    51 Assert::AreEqual(seed++, ptr[i]);
    +
    52 ring.pop(num_read);
    +
    53 }
    +
    54 writer.join();
    +
    55 }
    +
    56 };
    +
    57}
    +
    Ring buffer.
    Definition ring.hpp:24
    +
    std::tuple< T *, size_t > front()
    Peeks the data at the ring head. Use pop() after the data was consumed.
    Definition ring.hpp:73
    +
    + + + + diff --git a/ring_8hpp_source.html b/ring_8hpp_source.html index 187ff61a6..2db70a0da 100644 --- a/ring_8hpp_source.html +++ b/ring_8hpp_source.html @@ -89,7 +89,7 @@ $(document).ready(function() { init_codefold(0); });
    5
    6#pragma once
    7
    -
    8#include "sal.hpp"
    +
    8#include "compat.hpp"
    9#include <assert.h>
    10#include <condition_variable>
    11#include <mutex>
    @@ -224,7 +224,7 @@ $(document).ready(function() { init_codefold(0); });
    diff --git a/sal_8hpp_source.html b/sal_8hpp_source.html deleted file mode 100644 index 59c9b7923..000000000 --- a/sal_8hpp_source.html +++ /dev/null @@ -1,191 +0,0 @@ - - - - - - - -stdex: include/stdex/sal.hpp Source File - - - - - - - - - -
    -
    - - - - - - -
    -
    stdex -
    -
    Additional custom or not Standard C++ covered algorithms
    -
    -
    - - - - - - - - - -
    -
    - - -
    -
    -
    -
    -
    -
    Loading...
    -
    Searching...
    -
    No Matches
    -
    -
    -
    -
    - - -
    -
    -
    sal.hpp
    -
    -
    -
    1/*
    -
    2 SPDX-License-Identifier: MIT
    -
    3 Copyright © 2022-2023 Amebis
    -
    4*/
    -
    5
    -
    6#pragma once
    -
    7
    -
    8#ifdef _WIN32
    -
    9#include <sal.h>
    -
    10#endif
    -
    11
    -
    12#ifndef _In_
    -
    13#define _In_
    -
    14#endif
    -
    15#ifndef _In_bytecount_
    -
    16#define _In_bytecount_(p)
    -
    17#endif
    -
    18#ifndef _In_count_
    -
    19#define _In_count_(p)
    -
    20#endif
    -
    21#ifndef _In_opt_
    -
    22#define _In_opt_
    -
    23#endif
    -
    24#ifndef _In_opt_count_
    -
    25#define _In_opt_count_(p)
    -
    26#endif
    -
    27#ifndef _In_opt_z_count_
    -
    28#define _In_opt_z_count_(p)
    -
    29#endif
    -
    30#ifndef _In_z_
    -
    31#define _In_z_
    -
    32#endif
    -
    33#ifndef _In_z_count_
    -
    34#define _In_z_count_(p)
    -
    35#endif
    -
    36#ifndef _In_reads_or_z_
    -
    37#define _In_reads_or_z_(p)
    -
    38#endif
    -
    39#ifndef _In_reads_or_z_opt_
    -
    40#define _In_reads_or_z_opt_(p)
    -
    41#endif
    -
    42#ifndef _Printf_format_string_params_
    -
    43#define _Printf_format_string_params_(n)
    -
    44#endif
    -
    45
    -
    46#ifndef _Inout_
    -
    47#define _Inout_
    -
    48#endif
    -
    49
    -
    50#ifndef _Use_decl_annotations_
    -
    51#define _Use_decl_annotations_
    -
    52#endif
    -
    53
    -
    54#ifndef _Out_
    -
    55#define _Out_
    -
    56#endif
    -
    57#ifndef _Out_opt_
    -
    58#define _Out_opt_
    -
    59#endif
    -
    60#ifndef _Out_writes_z_
    -
    61#define _Out_writes_z_(p)
    -
    62#endif
    -
    63
    -
    64#ifndef _Success_
    -
    65#define _Success_(p)
    -
    66#endif
    -
    67#ifndef _Ret_notnull_
    -
    68#define _Ret_notnull_
    -
    69#endif
    -
    70#ifndef _Must_inspect_result_
    -
    71#define _Must_inspect_result_
    -
    72#endif
    -
    73
    -
    74#ifndef _Likely_
    -
    75#if _HAS_CXX20
    -
    76#define _Likely_ [[likely]]
    -
    77#else
    -
    78#define _Likely_
    -
    79#endif
    -
    80#endif
    -
    81
    -
    82#ifndef _Unlikely_
    -
    83#if _HAS_CXX20
    -
    84#define _Unlikely_ [[unlikely]]
    -
    85#else
    -
    86#define _Unlikely_
    -
    87#endif
    -
    88#endif
    -
    89
    -
    90#ifdef _MSC_VER
    -
    91#define _Deprecated_(message) __declspec(deprecated(message))
    -
    92#else
    -
    93#define _Deprecated_(message) [[deprecated(message)]]
    -
    94#endif
    -
    95
    -
    96#ifdef _WIN32
    -
    97#define _Unreferenced_(x) UNREFERENCED_PARAMETER(x)
    -
    98#else
    -
    99#define _Unreferenced_(x)
    -
    100#endif
    -
    - - - - diff --git a/search/all_8.js b/search/all_8.js index 89e7d722d..5e286deed 100644 --- a/search/all_8.js +++ b/search/all_8.js @@ -1,8 +1,9 @@ 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']]], - ['interval_2',['interval',['../structstdex_1_1interval.html',1,'stdex::interval< T >'],['../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'],['../structstdex_1_1interval.html#a41ac8e9fdb33a2dfaae6113006b792d8',1,'stdex::interval::interval(T _start, T _end) noexcept']]], - ['interval_3c_20fpos_5ft_20_3e_3',['interval< fpos_t >',['../structstdex_1_1interval.html',1,'stdex']]], - ['interval_3c_20size_5ft_20_3e_4',['interval< size_t >',['../structstdex_1_1interval.html',1,'stdex']]] + ['iconverter_0',['iconverter',['../classstdex_1_1iconverter.html',1,'stdex']]], + ['id_1',['id',['../classstdex_1_1idrec_1_1record.html#a24e54541a476b01e332290c57a495926',1,'stdex::idrec::record']]], + ['integer_2',['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']]], + ['interval_3',['interval',['../structstdex_1_1interval.html',1,'stdex::interval< T >'],['../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'],['../structstdex_1_1interval.html#a41ac8e9fdb33a2dfaae6113006b792d8',1,'stdex::interval::interval(T _start, T _end) 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']]] ]; diff --git a/search/all_a.js b/search/all_a.js index 22aed961d..497f98580 100644 --- a/search/all_a.js +++ b/search/all_a.js @@ -10,13 +10,12 @@ var searchData= ['m_5fmax_5fiterations_7',['m_max_iterations',['../classstdex_1_1parser_1_1basic__iterations.html#aca0b8e1f9522a5306db5fe173269e8b1',1,'stdex::parser::basic_iterations']]], ['m_5fmin_5fiterations_8',['m_min_iterations',['../classstdex_1_1parser_1_1basic__iterations.html#aab86447331f306ff85c49764a5d0d646',1,'stdex::parser::basic_iterations']]], ['m_5fnum_9',['m_num',['../classstdex_1_1errno__error.html#a3712510d0659db4ad2ef4082a5980575',1,'stdex::errno_error']]], - ['m_5foffset_10',['m_offset',['../classstdex_1_1stream_1_1memory__file.html#a91ca49273fc49d70b98180fc828d5b5d',1,'stdex::stream::memory_file::m_offset'],['../classstdex_1_1stream_1_1cache.html#a1132b6554bec05e4da1d493d18516640',1,'stdex::stream::cache::m_offset']]], + ['m_5foffset_10',['m_offset',['../classstdex_1_1stream_1_1cache.html#a1132b6554bec05e4da1d493d18516640',1,'stdex::stream::cache::m_offset'],['../classstdex_1_1stream_1_1memory__file.html#a91ca49273fc49d70b98180fc828d5b5d',1,'stdex::stream::memory_file::m_offset']]], ['m_5freserved_11',['m_reserved',['../classstdex_1_1stream_1_1memory__file.html#a6aa8c2deeabc66f065c858ba399d911c',1,'stdex::stream::memory_file']]], ['m_5fsize_12',['m_size',['../classstdex_1_1stream_1_1memory__file.html#a41121ff122745e109c1b9851632abce3',1,'stdex::stream::memory_file']]], ['m_5fsize_5fmax_13',['m_size_max',['../classstdex_1_1vector__queue.html#a7192dc2991d690b04a2fb24dd6fdc325',1,'stdex::vector_queue']]], - ['mapping_14',['mapping',['../structstdex_1_1mapping.html#a9634b5ef182398e24b61c2ca78cc8e46',1,'stdex::mapping::mapping()'],['../structstdex_1_1mapping.html#a48069d4eb38c276e856d650075f6c3bd',1,'stdex::mapping::mapping(T x)'],['../structstdex_1_1mapping.html#ae72436dbc2b54e2062822cd7772de830',1,'stdex::mapping::mapping(T _from, T _to)'],['../structstdex_1_1mapping.html',1,'stdex::mapping< T >']]], - ['math_15',['math',['../class_unit_tests_1_1math.html',1,'UnitTests']]], - ['memory_5ffile_16',['memory_file',['../classstdex_1_1stream_1_1memory__file.html',1,'stdex::stream::memory_file'],['../classstdex_1_1stream_1_1memory__file.html#a6b4b9daa088fb20678a502e81553c745',1,'stdex::stream::memory_file::memory_file(size_t size, state_t state=state_t::ok)'],['../classstdex_1_1stream_1_1memory__file.html#af7fdc0b7ffcd3713487a75cfd9c1704f',1,'stdex::stream::memory_file::memory_file(void *data, size_t size, size_t reserved, bool manage=false, state_t state=state_t::ok)'],['../classstdex_1_1stream_1_1memory__file.html#ad0da8c8758672af312026957e2556b60',1,'stdex::stream::memory_file::memory_file(void *data, size_t size, bool manage=false, state_t state=state_t::ok)'],['../classstdex_1_1stream_1_1memory__file.html#a0bb7b9759667e810c91b3e58c1771d91',1,'stdex::stream::memory_file::memory_file(const schar_t *filename, int mode)']]], - ['mouth_17',['mouth',['../classstdex_1_1parser_1_1basic__emoticon.html#a43d0de6a54546e509807c7c888bb8dc8',1,'stdex::parser::basic_emoticon']]], - ['mtime_18',['mtime',['../classstdex_1_1stream_1_1basic__file.html#ae10432137e01b7ce7c254c2a455c719e',1,'stdex::stream::basic_file::mtime()'],['../classstdex_1_1stream_1_1cache.html#a8350e6c158982e5511da18ed122bf24d',1,'stdex::stream::cache::mtime()'],['../classstdex_1_1stream_1_1file.html#a23e1061f6a9473241ef8af99f6a3f08f',1,'stdex::stream::file::mtime()']]] + ['mapping_14',['mapping',['../structstdex_1_1mapping.html',1,'stdex::mapping< T >'],['../structstdex_1_1mapping.html#a48069d4eb38c276e856d650075f6c3bd',1,'stdex::mapping::mapping(T x)'],['../structstdex_1_1mapping.html#ae72436dbc2b54e2062822cd7772de830',1,'stdex::mapping::mapping(T _from, T _to)'],['../structstdex_1_1mapping.html#a9634b5ef182398e24b61c2ca78cc8e46',1,'stdex::mapping::mapping()']]], + ['memory_5ffile_15',['memory_file',['../classstdex_1_1stream_1_1memory__file.html',1,'stdex::stream::memory_file'],['../classstdex_1_1stream_1_1memory__file.html#a0bb7b9759667e810c91b3e58c1771d91',1,'stdex::stream::memory_file::memory_file(const schar_t *filename, int mode)'],['../classstdex_1_1stream_1_1memory__file.html#ad0da8c8758672af312026957e2556b60',1,'stdex::stream::memory_file::memory_file(void *data, size_t size, bool manage=false, state_t state=state_t::ok)'],['../classstdex_1_1stream_1_1memory__file.html#af7fdc0b7ffcd3713487a75cfd9c1704f',1,'stdex::stream::memory_file::memory_file(void *data, size_t size, size_t reserved, bool manage=false, state_t state=state_t::ok)'],['../classstdex_1_1stream_1_1memory__file.html#a6b4b9daa088fb20678a502e81553c745',1,'stdex::stream::memory_file::memory_file(size_t size, state_t state=state_t::ok)']]], + ['mouth_16',['mouth',['../classstdex_1_1parser_1_1basic__emoticon.html#a43d0de6a54546e509807c7c888bb8dc8',1,'stdex::parser::basic_emoticon']]], + ['mtime_17',['mtime',['../classstdex_1_1stream_1_1basic__file.html#ae10432137e01b7ce7c254c2a455c719e',1,'stdex::stream::basic_file::mtime()'],['../classstdex_1_1stream_1_1cache.html#a8350e6c158982e5511da18ed122bf24d',1,'stdex::stream::cache::mtime()'],['../classstdex_1_1stream_1_1file.html#a23e1061f6a9473241ef8af99f6a3f08f',1,'stdex::stream::file::mtime()']]] ]; diff --git a/search/all_f.js b/search/all_f.js index 154d456e1..cc9b40578 100644 --- a/search/all_f.js +++ b/search/all_f.js @@ -3,7 +3,7 @@ var searchData= ['read_0',['read',['../classstdex_1_1stream_1_1diag__file.html#ac1eaf4a0cfce7e4426cff5f32fc33e6e',1,'stdex::stream::diag_file::read()'],['../classstdex_1_1stream_1_1basic.html#aa5d4693fd583cd7ef0ffa9b846136a5a',1,'stdex::stream::basic::read()'],['../classstdex_1_1stream_1_1converter.html#abdca66af4847c6f8b6d87a0909fc061f',1,'stdex::stream::converter::read()'],['../classstdex_1_1stream_1_1async__reader.html#a841c1e3cb01cb96df94701465086a529',1,'stdex::stream::async_reader::read()'],['../classstdex_1_1stream_1_1buffer.html#a2ef05f2df784dce1d1c4319a98cd22e0',1,'stdex::stream::buffer::read()'],['../classstdex_1_1stream_1_1limiter.html#a80b68f1b4a8fb8c72c09b1313e9d02ed',1,'stdex::stream::limiter::read()'],['../classstdex_1_1stream_1_1window.html#a45f2420dfc94c07e101186ae2e541e13',1,'stdex::stream::window::read()'],['../classstdex_1_1stream_1_1file__window.html#a9cdfe9f40ccb1f84e121b1b949a21246',1,'stdex::stream::file_window::read()'],['../classstdex_1_1stream_1_1cache.html#a43dd464dd032888de79f5cd606adffa9',1,'stdex::stream::cache::read()'],['../classstdex_1_1stream_1_1basic__sys.html#ad5daf3c776b615dcfbb0b0891afdb9d0',1,'stdex::stream::basic_sys::read()'],['../classstdex_1_1stream_1_1memory__file.html#a62a05e7dfb1f374dff881f922543e601',1,'stdex::stream::memory_file::read()'],['../classstdex_1_1stream_1_1fifo.html#a84357513740c64a8317370b289c34e40',1,'stdex::stream::fifo::read()']]], ['read_5farray_1',['read_array',['../classstdex_1_1stream_1_1basic.html#a7723ae23bc35c2ffb74380eab5b0a9ba',1,'stdex::stream::basic']]], ['read_5fbyte_2',['read_byte',['../classstdex_1_1stream_1_1basic.html#a600e123c10d6f0604d58ae0e9be95f0b',1,'stdex::stream::basic']]], - ['read_5fcharset_3',['read_charset',['../classstdex_1_1stream_1_1basic__file.html#a688cd1e67a5802cdb5c37a7e9691f7e3',1,'stdex::stream::basic_file']]], + ['read_5fcharset_3',['read_charset',['../classstdex_1_1stream_1_1basic__file.html#a6a3bc2c76e78363a2232eff12dd5e370',1,'stdex::stream::basic_file']]], ['read_5fdata_4',['read_data',['../classstdex_1_1stream_1_1basic.html#afd5a1268365027ed8c5108183dc498df',1,'stdex::stream::basic::read_data()'],['../classstdex_1_1stream_1_1memory__file.html#a4aa784758856b70a2b6f2b7ca0ffa72b',1,'stdex::stream::memory_file::read_data()']]], ['read_5flimit_5',['read_limit',['../classstdex_1_1stream_1_1limiter.html#a455a9e38efe1e7473e501dd00fb3d7f0',1,'stdex::stream::limiter']]], ['read_5foffset_6',['read_offset',['../classstdex_1_1stream_1_1window.html#acff67a2931b8f1a85f12806002e7e131',1,'stdex::stream::window']]], diff --git a/search/classes_8.js b/search/classes_8.js index 33252d03c..8f363fe61 100644 --- a/search/classes_8.js +++ b/search/classes_8.js @@ -1,6 +1,7 @@ var searchData= [ - ['interval_0',['interval',['../structstdex_1_1interval.html',1,'stdex']]], - ['interval_3c_20fpos_5ft_20_3e_1',['interval< fpos_t >',['../structstdex_1_1interval.html',1,'stdex']]], - ['interval_3c_20size_5ft_20_3e_2',['interval< size_t >',['../structstdex_1_1interval.html',1,'stdex']]] + ['iconverter_0',['iconverter',['../classstdex_1_1iconverter.html',1,'stdex']]], + ['interval_1',['interval',['../structstdex_1_1interval.html',1,'stdex']]], + ['interval_3c_20fpos_5ft_20_3e_2',['interval< fpos_t >',['../structstdex_1_1interval.html',1,'stdex']]], + ['interval_3c_20size_5ft_20_3e_3',['interval< size_t >',['../structstdex_1_1interval.html',1,'stdex']]] ]; diff --git a/search/classes_a.js b/search/classes_a.js index afb3d73e8..fac6d5bce 100644 --- a/search/classes_a.js +++ b/search/classes_a.js @@ -1,6 +1,5 @@ var searchData= [ ['mapping_0',['mapping',['../structstdex_1_1mapping.html',1,'stdex']]], - ['math_1',['math',['../class_unit_tests_1_1math.html',1,'UnitTests']]], - ['memory_5ffile_2',['memory_file',['../classstdex_1_1stream_1_1memory__file.html',1,'stdex::stream']]] + ['memory_5ffile_1',['memory_file',['../classstdex_1_1stream_1_1memory__file.html',1,'stdex::stream']]] ]; diff --git a/search/functions_f.js b/search/functions_f.js index 346ec6edd..fff3cf485 100644 --- a/search/functions_f.js +++ b/search/functions_f.js @@ -3,7 +3,7 @@ var searchData= ['read_0',['read',['../classstdex_1_1stream_1_1converter.html#abdca66af4847c6f8b6d87a0909fc061f',1,'stdex::stream::converter::read()'],['../classstdex_1_1stream_1_1async__reader.html#a841c1e3cb01cb96df94701465086a529',1,'stdex::stream::async_reader::read()'],['../classstdex_1_1stream_1_1buffer.html#a2ef05f2df784dce1d1c4319a98cd22e0',1,'stdex::stream::buffer::read()'],['../classstdex_1_1stream_1_1limiter.html#a80b68f1b4a8fb8c72c09b1313e9d02ed',1,'stdex::stream::limiter::read()'],['../classstdex_1_1stream_1_1window.html#a45f2420dfc94c07e101186ae2e541e13',1,'stdex::stream::window::read()'],['../classstdex_1_1stream_1_1file__window.html#a9cdfe9f40ccb1f84e121b1b949a21246',1,'stdex::stream::file_window::read()'],['../classstdex_1_1stream_1_1cache.html#a43dd464dd032888de79f5cd606adffa9',1,'stdex::stream::cache::read()'],['../classstdex_1_1stream_1_1basic__sys.html#ad5daf3c776b615dcfbb0b0891afdb9d0',1,'stdex::stream::basic_sys::read()'],['../classstdex_1_1stream_1_1memory__file.html#a62a05e7dfb1f374dff881f922543e601',1,'stdex::stream::memory_file::read()'],['../classstdex_1_1stream_1_1fifo.html#a84357513740c64a8317370b289c34e40',1,'stdex::stream::fifo::read()'],['../classstdex_1_1stream_1_1diag__file.html#ac1eaf4a0cfce7e4426cff5f32fc33e6e',1,'stdex::stream::diag_file::read()'],['../classstdex_1_1stream_1_1basic.html#aa5d4693fd583cd7ef0ffa9b846136a5a',1,'stdex::stream::basic::read(_Out_writes_bytes_to_opt_(length, return) void *data, size_t length)']]], ['read_5farray_1',['read_array',['../classstdex_1_1stream_1_1basic.html#a7723ae23bc35c2ffb74380eab5b0a9ba',1,'stdex::stream::basic']]], ['read_5fbyte_2',['read_byte',['../classstdex_1_1stream_1_1basic.html#a600e123c10d6f0604d58ae0e9be95f0b',1,'stdex::stream::basic']]], - ['read_5fcharset_3',['read_charset',['../classstdex_1_1stream_1_1basic__file.html#a688cd1e67a5802cdb5c37a7e9691f7e3',1,'stdex::stream::basic_file']]], + ['read_5fcharset_3',['read_charset',['../classstdex_1_1stream_1_1basic__file.html#a6a3bc2c76e78363a2232eff12dd5e370',1,'stdex::stream::basic_file']]], ['read_5fdata_4',['read_data',['../classstdex_1_1stream_1_1basic.html#afd5a1268365027ed8c5108183dc498df',1,'stdex::stream::basic::read_data()'],['../classstdex_1_1stream_1_1memory__file.html#a4aa784758856b70a2b6f2b7ca0ffa72b',1,'stdex::stream::memory_file::read_data()']]], ['read_5fremainder_5',['read_remainder',['../classstdex_1_1stream_1_1basic.html#a6148810b1d873b9f5a3496b06b1aa90b',1,'stdex::stream::basic::read_remainder()'],['../classstdex_1_1stream_1_1basic__file.html#a72aa16169eea2156e83053ba9bd91cd8',1,'stdex::stream::basic_file::read_remainder()']]], ['read_5fstr_6',['read_str',['../classstdex_1_1stream_1_1basic.html#a2fece103fa6ca15dfe093fe90ceae65e',1,'stdex::stream::basic::read_str()'],['../classstdex_1_1stream_1_1memory__file.html#a7a8abbdd7f86e10ffb711621015645f6',1,'stdex::stream::memory_file::read_str()']]], diff --git a/sgml_8cpp_source.html b/sgml_8cpp_source.html new file mode 100644 index 000000000..e20c6b405 --- /dev/null +++ b/sgml_8cpp_source.html @@ -0,0 +1,159 @@ + + + + + + + +stdex: UnitTests/sgml.cpp Source File + + + + + + + + + +
    +
    + + + + + + +
    +
    stdex +
    +
    Additional custom or not Standard C++ covered algorithms
    +
    +
    + + + + + + + + + +
    +
    + + +
    +
    +
    +
    +
    +
    Loading...
    +
    Searching...
    +
    No Matches
    +
    +
    +
    +
    + + +
    +
    +
    sgml.cpp
    +
    +
    +
    1/*
    +
    2 SPDX-License-Identifier: MIT
    +
    3 Copyright © 2023 Amebis
    +
    4*/
    +
    5
    +
    6#include "pch.h"
    +
    7
    +
    8using namespace std;
    +
    9#ifdef _WIN32
    +
    10using namespace Microsoft::VisualStudio::CppUnitTestFramework;
    +
    11#endif
    +
    12
    +
    13namespace UnitTests
    +
    14{
    +
    15 TEST_CLASS(sgml)
    +
    16 {
    +
    17 public:
    +
    18 TEST_METHOD(sgml2wstr)
    +
    19 {
    +
    20 Assert::AreEqual(L"This is a test.", stdex::sgml2wstr("This is a test.", (size_t)-1).c_str());
    +
    21 Assert::AreEqual(L"Th\u00ed\u0161 i\u22c5 a te\u0073\u0304t.&unknown;😀😅", stdex::sgml2wstr("Th&iacute;&scaron; i&sdot; &#97; te&smacr;t.&unknown;&#x1F600;&#X1f605;", (size_t)-1).c_str());
    +
    22 Assert::AreEqual(L"This", stdex::sgml2wstr("This is a test.", 4).c_str());
    +
    23 Assert::AreEqual(L"T\u0068\u0301", stdex::sgml2wstr("T&hacute;is is a test.", 9).c_str());
    +
    24 Assert::AreEqual(L"T&hac", stdex::sgml2wstr("T&hacute;is is a test.", 5).c_str());
    +
    25 Assert::AreEqual(L"The &quot;quoted&quot; &amp; text.", stdex::sgml2wstr("The &quot;quoted&quot; &amp; text.", (size_t)-1, stdex::sgml_c).c_str());
    +
    26
    +
    27 stdex::mapping_vector<size_t> map;
    +
    28 constexpr size_t i = 0;
    +
    29 constexpr size_t j = 0;
    +
    30 stdex::sgml2wstr("Th&iacute;&scaron; i&sdot; &#97; te&smacr;t.&unknown;&#x1F600;&#X1f605;", (size_t)-1, 0, stdex::mapping<size_t>(i, j), &map);
    +
    31 Assert::IsTrue(stdex::mapping_vector<size_t>{
    +
    32 { i + 2, j + 2 },
    +
    33 { i + 10, j + 3 },
    +
    34 { i + 10, j + 3 },
    +
    35 { i + 18, j + 4 },
    +
    36 { i + 20, j + 6 },
    +
    37 { i + 26, j + 7 },
    +
    38 { i + 27, j + 8 },
    +
    39 { i + 32, j + 9 },
    +
    40 { i + 35, j + 12 },
    +
    41 { i + 42, j + 14 },
    +
    42 { i + 53, j + 25 },
    +
    43#ifdef _WIN32 // wchar_t* is UTF-16
    +
    44 { i + 62, j + 27 },
    +
    45 { i + 62, j + 27 },
    +
    46 { i + 71, j + 29 },
    +
    47#else // wchar_t* is UTF-32
    +
    48 { i + 62, j + 26 },
    +
    49 { i + 62, j + 26 },
    +
    50 { i + 71, j + 27 },
    +
    51#endif
    +
    52 } == map);
    +
    53 }
    +
    54
    +
    55 TEST_METHOD(wstr2sgml)
    +
    56 {
    +
    57 Assert::AreEqual("This is a test.", stdex::wstr2sgml(L"This is a test.", (size_t)-1).c_str());
    +
    58 Assert::AreEqual("Th&iacute;&scaron; i&sdot; a te&smacr;t.&amp;unknown;&#x1f600;&#x1f605;", stdex::wstr2sgml(L"Th\u00ed\u0161 i\u22c5 a te\u0073\u0304t.&unknown;😀😅", (size_t)-1).c_str());
    +
    59 Assert::AreEqual("This", stdex::wstr2sgml(L"This is a test.", 4).c_str());
    +
    60 Assert::AreEqual("te&smacr;", stdex::wstr2sgml(L"te\u0073\u0304t", 4).c_str());
    +
    61 Assert::AreEqual("tes", stdex::wstr2sgml(L"te\u0073\u0304t", 3).c_str());
    +
    62 Assert::AreEqual("&#x2318;&permil;&#x362;", stdex::wstr2sgml(L"⌘‰͢", (size_t)-1).c_str());
    +
    63 Assert::AreEqual("$\"<>&amp;", stdex::wstr2sgml(L"$\"<>&", (size_t)-1).c_str());
    +
    64 Assert::AreEqual("$&quot;<>&amp;", stdex::wstr2sgml(L"$\"<>&", (size_t)-1, stdex::sgml_c).c_str());
    +
    65 }
    +
    66 };
    +
    67}
    +
    Maps index in source string to index in destination string.
    Definition mapping.hpp:17
    +
    + + + + diff --git a/sgml_8hpp_source.html b/sgml_8hpp_source.html index 857960dfc..34cff39b0 100644 --- a/sgml_8hpp_source.html +++ b/sgml_8hpp_source.html @@ -89,8 +89,8 @@ $(document).ready(function() { init_codefold(0); });
    5
    6#pragma once
    7
    -
    8#include "mapping.hpp"
    -
    9#include "sal.hpp"
    +
    8#include "compat.hpp"
    +
    9#include "mapping.hpp"
    10#include "sgml_unicode.hpp"
    11#include "string.hpp"
    12#include <assert.h>
    @@ -245,29 +245,31 @@ $(document).ready(function() { init_codefold(0); });
    173 }
    174
    175 template <class T>
    -
    176 inline _Deprecated_("Use stdex::sgml2wstrcat") 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
    -
    197 template <class T>
    -
    198 inline void sgml2wstrcat(
    -
    199 _Inout_ std::wstring& dst,
    -
    200 _In_ const std::basic_string<T>& src,
    -
    201 _In_ int skip = 0,
    -
    202 _In_ const mapping<size_t>& offset = mapping<size_t>(0, 0),
    -
    203 _Inout_opt_ mapping_vector<size_t>* map = nullptr)
    -
    204 {
    -
    205 sgml2wstrcat(dst, src.data(), src.size(), skip, offset, map);
    -
    206 }
    -
    207
    -
    208 template <class T>
    -
    209 inline _Deprecated_("Use stdex::sgml2wstrcat") void sgml2wstr(
    +
    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,
    @@ -372,402 +374,406 @@ $(document).ready(function() { init_codefold(0); });
    324 }
    325
    326 template <class T>
    -
    327 inline _Deprecated_("Use stdex::sgml2wstrcat") 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 assert(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 assert(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 assert(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 inline _Deprecated_("Use stdex::wstr2sgmlcat") void wstr2sgml(
    -
    586 _Inout_ std::string& dst,
    -
    587 _In_reads_or_z_opt_(count_src) const wchar_t* src, _In_ size_t count_src,
    -
    588 _In_ size_t what = 0)
    -
    589 {
    -
    590 wstr2sgmlcat(dst, src, count_src, what);
    -
    591 }
    -
    592
    -
    600 inline void wstr2sgmlcat(
    -
    601 _Inout_ std::string& dst,
    -
    602 _In_ const std::wstring& src,
    -
    603 _In_ size_t what = 0)
    -
    604 {
    -
    605 wstr2sgmlcat(dst, src.c_str(), src.size(), what);
    -
    606 }
    -
    607
    -
    608 inline _Deprecated_("Use stdex::wstr2sgmlcat") void wstr2sgml(
    -
    609 _Inout_ std::string& dst,
    -
    610 _In_ const std::wstring& src,
    -
    611 _In_ size_t what = 0)
    -
    612 {
    -
    613 wstr2sgmlcat(dst, src, what);
    -
    614 }
    -
    615
    -
    627 inline size_t wstr2sgmlcat(
    -
    628 _Inout_cap_(count_dst) char* dst, _In_ size_t count_dst,
    -
    629 _In_reads_or_z_opt_(count_src) const wchar_t* src, _In_ size_t count_src,
    -
    630 _In_ size_t what = 0)
    -
    631 {
    -
    632 assert(dst || !count_dst);
    -
    633 assert(src || !count_src);
    -
    634
    -
    635 static const std::invalid_argument buffer_overrun("buffer overrun");
    -
    636 const bool
    -
    637 do_ascii = (what & sgml_full) == 0,
    -
    638 do_quot = (what & sgml_quot) == 0,
    -
    639 do_apos = (what & sgml_apos) == 0,
    -
    640 do_lt_gt = (what & sgml_lt_gt) == 0,
    -
    641 do_bsol = (what & sgml_bsol) == 0,
    -
    642 do_dollar = (what & sgml_dollar) == 0,
    -
    643 do_percnt = (what & sgml_percnt) == 0,
    -
    644 do_commat = (what & sgml_commat) == 0,
    -
    645 do_num = (what & sgml_num) == 0,
    -
    646 do_lpar_rpar = (what & sgml_lpar_rpar) == 0,
    -
    647 do_lcub_rcub = (what & sgml_lcub_rcub) == 0,
    -
    648 do_lsqb_rsqb = (what & sgml_lsqb_rsqb) == 0;
    -
    649
    -
    650 size_t j = strnlen(dst, count_dst);
    -
    651 count_src = wcsnlen(src, count_src);
    -
    652 for (size_t i = 0; i < count_src;) {
    -
    653 size_t n = glyphlen(src + i, count_src - i);
    -
    654 if (n == 1 &&
    -
    655 do_ascii && (unsigned int)src[i] < 128 &&
    -
    656 src[i] != L'&' &&
    -
    657 (do_quot || (src[i] != L'"')) &&
    -
    658 (do_apos || (src[i] != L'\'')) &&
    -
    659 (do_lt_gt || (src[i] != L'<' && src[i] != L'>')) &&
    -
    660 (do_bsol || (src[i] != L'\\')) &&
    -
    661 (do_dollar || (src[i] != L'$')) &&
    -
    662 (do_percnt || (src[i] != L'%')) &&
    -
    663 (do_commat || (src[i] != L'@')) &&
    -
    664 (do_num || (src[i] != L'#')) &&
    -
    665 (do_lpar_rpar || (src[i] != L'(' && src[i] != L')')) &&
    -
    666 (do_lcub_rcub || (src[i] != L'{' && src[i] != L'}')) &&
    -
    667 (do_lsqb_rsqb || (src[i] != L'[' && src[i] != L']')))
    -
    668 {
    -
    669 // 7-bit ASCII and no desire to encode it as an SGML entity.
    -
    670 if (j + 1 >= count_dst)
    -
    671 throw buffer_overrun;
    -
    672 dst[j++] = static_cast<char>(src[i++]);
    -
    673 }
    -
    674 else {
    -
    675 const char* entity = chr2sgml(src + i, n);
    -
    676 if (entity) {
    -
    677 size_t m = strlen(entity);
    -
    678 if (j + m + 2 >= count_dst)
    -
    679 throw buffer_overrun;
    -
    680 dst[j++] = '&';
    -
    681 memcpy(dst + j, entity, m * sizeof(char)); j += m;
    -
    682 dst[j++] = ';';
    -
    683 i += n;
    -
    684 }
    -
    685 else if (n == 1) {
    -
    686 // Trivial character (1 code unit, 1 glyph), no entity available.
    -
    687 if ((unsigned int)src[i] < 128) {
    -
    688 if (j + 1 >= count_dst)
    -
    689 throw buffer_overrun;
    -
    690 dst[j++] = static_cast<char>(src[i++]);
    -
    691 }
    -
    692 else {
    -
    693 char tmp[3 + 8 + 1 + 1];
    -
    694 int m = snprintf(tmp, _countof(tmp), "&#x%x;", src[i++]);
    -
    695 assert(m >= 0);
    -
    696 if (static_cast<size_t>(m) >= count_dst)
    -
    697 throw buffer_overrun;
    -
    698 memcpy(dst + j, tmp, m * sizeof(char)); j += m;
    -
    699 }
    -
    700 }
    -
    701 else {
    -
    702 // Non-trivial character. Decompose.
    -
    703 const size_t end = i + n;
    -
    704 while (i < end) {
    -
    705 if ((entity = chr2sgml(src + i, 1)) != nullptr) {
    -
    706 size_t m = strlen(entity);
    -
    707 if (j + m + 2 >= count_dst)
    -
    708 throw buffer_overrun;
    -
    709 dst[j++] = '&';
    -
    710 memcpy(dst + j, entity, m * sizeof(char)); j += m;
    -
    711 dst[j++] = ';';
    -
    712 i++;
    -
    713 }
    -
    714 else if ((unsigned int)src[i] < 128) {
    -
    715 if (j + 1 >= count_dst)
    -
    716 throw buffer_overrun;
    -
    717 dst[j++] = static_cast<char>(src[i++]);
    -
    718 }
    -
    719 else {
    -
    720 uint32_t unicode;
    -
    721#ifdef _WIN32
    -
    722 if (i + 1 < end && is_surrogate_pair(src + i)) {
    -
    723 unicode = surrogate_pair_to_ucs4(src + i);
    -
    724 i += 2;
    -
    725 }
    -
    726 else
    -
    727#endif
    -
    728 {
    -
    729 unicode = src[i++];
    -
    730 }
    -
    731 char tmp[3 + 8 + 1 + 1];
    -
    732 int m = snprintf(tmp, _countof(tmp), "&#x%x;", unicode);
    -
    733 assert(m >= 0);
    -
    734 if (static_cast<size_t>(m) >= count_dst)
    -
    735 throw buffer_overrun;
    -
    736 memcpy(dst + j, tmp, m * sizeof(char)); j += m;
    -
    737 }
    -
    738 }
    -
    739 }
    -
    740 }
    -
    741 }
    -
    742 if (j >= count_dst)
    -
    743 throw buffer_overrun;
    -
    744 dst[j] = 0;
    -
    745 return j;
    -
    746 }
    -
    747
    -
    748 inline _Deprecated_("Use stdex::wstr2sgmlcat") size_t wstr2sgml(
    -
    749 _Inout_cap_(count_dst) char* dst, _In_ size_t count_dst,
    -
    750 _In_reads_or_z_opt_(count_src) const wchar_t* src, _In_ size_t count_src,
    -
    751 _In_ size_t what = 0)
    -
    752 {
    -
    753 return wstr2sgmlcat(dst, count_dst, src, count_src, what);
    -
    754 }
    -
    755
    -
    764 inline void wstr2sgmlcpy(
    -
    765 _Inout_ std::string& dst,
    -
    766 _In_reads_or_z_opt_(count_src) const wchar_t* src, _In_ size_t count_src,
    -
    767 _In_ size_t what = 0)
    -
    768 {
    -
    769 dst.clear();
    -
    770 wstr2sgmlcat(dst, src, count_src, what);
    -
    771 }
    -
    772
    -
    780 inline void wstr2sgmlcpy(
    -
    781 _Inout_ std::string& dst,
    -
    782 _In_ const std::wstring& src,
    -
    783 _In_ size_t what = 0)
    -
    784 {
    -
    785 wstr2sgmlcpy(dst, src.data(), src.size(), what);
    -
    786 }
    -
    787
    -
    799 inline size_t wstr2sgmlcpy(
    -
    800 _Inout_cap_(count_dst) char* dst, _In_ size_t count_dst,
    -
    801 _In_reads_or_z_opt_(count_src) const wchar_t* src, _In_ size_t count_src,
    -
    802 _In_ size_t what = 0)
    -
    803 {
    -
    804 assert(dst || !count_dst);
    -
    805 if (count_dst)
    -
    806 dst[0] = 0;
    -
    807 return wstr2sgmlcat(dst, count_dst, src, count_src, what);
    -
    808 }
    -
    809
    -
    819 inline std::string wstr2sgml(
    -
    820 _In_reads_or_z_opt_(count_src) const wchar_t* src, _In_ size_t count_src,
    -
    821 _In_ size_t what = 0)
    -
    822 {
    -
    823 std::string dst;
    -
    824 wstr2sgmlcat(dst, src, count_src, what);
    -
    825 return dst;
    -
    826 }
    -
    827
    -
    836 inline std::string wstr2sgml(
    -
    837 _In_ const std::wstring& src,
    -
    838 _In_ size_t what = 0)
    -
    839 {
    -
    840 return wstr2sgml(src.c_str(), src.size(), what);
    -
    841 }
    -
    842}
    +
    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 assert(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 assert(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 assert(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 assert(dst || !count_dst);
    +
    636 assert(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 assert(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 assert(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 assert(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 82775e56a..b068f1e75 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 new file mode 100644 index 000000000..05c077d37 --- /dev/null +++ b/stream_8cpp_source.html @@ -0,0 +1,254 @@ + + + + + + + +stdex: UnitTests/stream.cpp Source File + + + + + + + + + +
    +
    + + + + + + +
    +
    stdex +
    +
    Additional custom or not Standard C++ covered algorithms
    +
    +
    + + + + + + + + + +
    +
    + + +
    +
    +
    +
    +
    +
    Loading...
    +
    Searching...
    +
    No Matches
    +
    +
    +
    +
    + + +
    +
    +
    stream.cpp
    +
    +
    +
    1/*
    +
    2 SPDX-License-Identifier: MIT
    +
    3 Copyright © 2023 Amebis
    +
    4*/
    +
    5
    +
    6#include "pch.h"
    +
    7
    +
    8using namespace std;
    +
    9using namespace stdex;
    +
    10using namespace stdex::stream;
    +
    11#ifdef _WIN32
    +
    12using namespace Microsoft::VisualStudio::CppUnitTestFramework;
    +
    13#endif
    +
    14
    +
    15namespace UnitTests
    +
    16{
    +
    17 TEST_CLASS(stream)
    +
    18 {
    +
    19 public:
    +
    20 TEST_METHOD(async)
    +
    21 {
    +
    22 constexpr uint32_t total = 1000;
    +
    23 memory_file source(mul(total, sizeof(uint32_t)));
    +
    24 {
    +
    25 async_writer<70> writer(source);
    +
    26 for (uint32_t i = 0; i < total; ++i) {
    +
    27 Assert::IsTrue(writer.ok());
    +
    28 writer << i;
    +
    29 }
    +
    30 }
    +
    31 Assert::AreEqual<stdex::stream::fpos_t>(0, source.seekbeg(0));
    +
    32 {
    +
    33 async_reader<50> reader(source);
    +
    34 uint32_t x;
    +
    35 for (uint32_t i = 0; i < total; ++i) {
    +
    36 reader >> x;
    +
    37 Assert::IsTrue(reader.ok());
    +
    38 Assert::AreEqual(i, x);
    +
    39 }
    +
    40 reader >> x;
    +
    41 Assert::IsFalse(reader.ok());
    +
    42 }
    +
    43 }
    +
    44
    +
    45 TEST_METHOD(replicator)
    +
    46 {
    +
    47 constexpr uint32_t total = 1000;
    +
    48
    +
    49 memory_file f1(mul(total, sizeof(uint32_t)));
    +
    50
    +
    51 sstring filename2, filename3;
    +
    52 filename2 = filename3 = temp_path();
    +
    53 filename2 += _T("stdex-stream-replicator-2.tmp");
    +
    54 file f2(
    +
    55 filename2.c_str(),
    +
    56 mode_for_reading | mode_for_writing | mode_create | mode_binary);
    +
    57
    +
    58 filename3 += _T("stdex-stream-replicator-3.tmp");
    +
    59 cached_file f3(
    +
    60 filename3.c_str(),
    +
    61 mode_for_reading | mode_for_writing | mode_create | mode_binary,
    +
    62 128);
    +
    63
    +
    64 {
    + +
    66 buffer f2_buf(f2, 0, 32);
    +
    67 writer.push_back(&f1);
    +
    68 writer.push_back(&f2_buf);
    +
    69 writer.push_back(&f3);
    +
    70 for (uint32_t i = 0; i < total; ++i) {
    +
    71 Assert::IsTrue(writer.ok());
    +
    72 writer << i;
    +
    73 }
    +
    74 }
    +
    75
    +
    76 f1.seekbeg(0);
    +
    77 f2.seekbeg(0);
    +
    78 f3.seekbeg(0);
    +
    79 {
    +
    80 buffer f2_buf(f2, 64, 0);
    +
    81 uint32_t x;
    +
    82 for (uint32_t i = 0; i < total; ++i) {
    +
    83 f1 >> x;
    +
    84 Assert::IsTrue(f1.ok());
    +
    85 Assert::AreEqual(i, x);
    +
    86 f2_buf >> x;
    +
    87 Assert::IsTrue(f2_buf.ok());
    +
    88 Assert::AreEqual(i, x);
    +
    89 f3 >> x;
    +
    90 Assert::IsTrue(f3.ok());
    +
    91 Assert::AreEqual(i, x);
    +
    92 }
    +
    93 f1 >> x;
    +
    94 Assert::IsFalse(f1.ok());
    +
    95 f2_buf >> x;
    +
    96 Assert::IsFalse(f2_buf.ok());
    +
    97 f3 >> x;
    +
    98 Assert::IsFalse(f3.ok());
    +
    99 }
    +
    100
    +
    101 f2.close();
    +
    102 std::filesystem::remove(filename2);
    +
    103 f3.close();
    +
    104 std::filesystem::remove(filename3);
    +
    105 }
    +
    106
    +
    107 TEST_METHOD(open_close)
    +
    108 {
    +
    109 cached_file dat(invalid_handle, state_t::fail, 4096);
    +
    110 const sstring filepath = temp_path();
    +
    111 constexpr uint32_t count = 3;
    +
    112 sstring filename[count];
    +
    113 stdex::stream::fpos_t start[count];
    +
    114 for (uint32_t i = 0; i < count; ++i) {
    +
    115 filename[i] = filepath + sprintf(_T("stdex-stream-open_close%zu.tmp"), NULL, i);
    +
    116 dat.open(filename[i].c_str(), mode_for_reading | mode_for_writing | share_none | mode_preserve_existing | mode_binary);
    +
    117 Assert::IsTrue(dat.ok());
    +
    118 start[i] = dat.tell();
    +
    119 Assert::AreNotEqual(fpos_max, start[i]);
    +
    120 for (uint32_t j = 0; j < 31 + 11 * i; ++j) {
    +
    121 dat << j * count + i;
    +
    122 Assert::IsTrue(dat.ok());
    +
    123 }
    +
    124 dat.close();
    +
    125 }
    +
    126 for (uint32_t i = 0; i < count; ++i) {
    +
    127 dat.open(filename[i].c_str(), mode_for_reading | share_none | mode_binary);
    +
    128 Assert::IsTrue(dat.ok());
    +
    129 for (;;) {
    +
    130 uint32_t x;
    +
    131 dat >> x;
    +
    132 if (!dat.ok())
    +
    133 break;
    +
    134 Assert::AreEqual(i, x % count);
    +
    135 }
    +
    136 }
    +
    137 dat.close();
    +
    138 for (uint32_t i = 0; i < count; ++i)
    +
    139 std::filesystem::remove(filename[i]);
    +
    140 }
    +
    141
    +
    142 protected:
    +
    143 static sstring temp_path()
    +
    144 {
    +
    145#ifdef _WIN32
    +
    146 TCHAR temp_path[MAX_PATH];
    +
    147 Assert::IsTrue(ExpandEnvironmentStrings(_T("%TEMP%\\"), temp_path, _countof(temp_path)) < MAX_PATH);
    +
    148 return temp_path;
    +
    149#else
    +
    150 return "/tmp/";
    +
    151#endif
    +
    152 }
    +
    153 };
    +
    154}
    +
    Provides read-ahead stream capability.
    Definition stream.hpp:1118
    +
    Provides write-back stream capability.
    Definition stream.hpp:1186
    +
    bool ok() const
    Returns true if the stream state is clean i.e. previous operation was succesful.
    Definition stream.hpp:170
    +
    Buffered read/write stream.
    Definition stream.hpp:1257
    +
    Cached file-system file.
    Definition stream.hpp:2751
    +
    File-system file.
    Definition stream.hpp:2434
    +
    In-memory file.
    Definition stream.hpp:2813
    +
    Replicates writing of the same data to multiple streams.
    Definition stream.hpp:949
    +
    void push_back(basic *source)
    Adds stream on the list.
    Definition stream.hpp:968
    +
    + + + + diff --git a/stream_8hpp_source.html b/stream_8hpp_source.html index 49d22bb15..68c0ae6ca 100644 --- a/stream_8hpp_source.html +++ b/stream_8hpp_source.html @@ -89,11 +89,11 @@ $(document).ready(function() { init_codefold(0); });
    5
    6#pragma once
    7
    -
    8#include "endian.hpp"
    -
    9#include "interval.hpp"
    -
    10#include "math.hpp"
    -
    11#include "ring.hpp"
    -
    12#include "sal.hpp"
    +
    8#include "compat.hpp"
    +
    9#include "endian.hpp"
    +
    10#include "interval.hpp"
    +
    11#include "math.hpp"
    +
    12#include "ring.hpp"
    13#include "string.hpp"
    14#include "system.hpp"
    15#include "unicode.hpp"
    @@ -103,484 +103,484 @@ $(document).ready(function() { init_codefold(0); });
    19#if defined(_WIN32)
    20#include <asptlb.h>
    21#include <objidl.h>
    -
    22#endif
    -
    23#include <chrono>
    -
    24#include <condition_variable>
    -
    25#include <list>
    -
    26#include <memory>
    -
    27#include <string>
    -
    28#include <thread>
    -
    29#include <vector>
    -
    30
    -
    31#if !defined(SET_FILE_OP_TIMES) && defined(RDAT_BELEZI_CAS_DOSTOPA_VER)
    -
    32#define SET_FILE_OP_TIMES 1
    -
    33#pragma message("RDAT_BELEZI_CAS_DOSTOPA_VER is deprecated. Use SET_FILE_OP_TIMES instead.")
    -
    34#elif !defined(SET_FILE_OP_TIMES)
    -
    35#define SET_FILE_OP_TIMES 0
    -
    36#endif
    -
    37#if !defined(CHECK_STREAM_STATE) && defined(RDAT_NE_PREVERJAJ_STANJA_VER)
    -
    38#define CHECK_STREAM_STATE 0
    -
    39#pragma message("RDAT_NE_PREVERJAJ_EOF_VER is deprecated. Use CHECK_STREAM_STATE=0 instead.")
    -
    40#else
    -
    41#define CHECK_STREAM_STATE 1
    -
    42#endif
    -
    43
    -
    44namespace stdex
    -
    45{
    -
    46 namespace stream
    -
    47 {
    -
    51 enum class state_t {
    -
    52 ok = 0,
    -
    53 eof,
    -
    54 fail,
    -
    55 };
    -
    56
    -
    60 using fsize_t = uint64_t;
    -
    61 constexpr fsize_t fsize_max = UINT64_MAX;
    -
    62
    -
    63 constexpr size_t iterate_count = 0x10;
    -
    64 constexpr size_t default_block_size = 0x10000;
    -
    65 constexpr wchar_t utf16_bom = L'\ufeff';
    -
    66 constexpr const char utf8_bom[3] = { '\xef', '\xbb', '\xbf' };
    -
    67
    -
    -
    71 class basic
    -
    72 {
    -
    73 public:
    -
    74 basic(_In_ state_t state = state_t::ok) : m_state(state) {}
    -
    75
    -
    -
    87 virtual _Success_(return != 0 || length == 0) size_t read(
    -
    88 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
    -
    89 {
    -
    90 _Unreferenced_(data);
    -
    91 _Unreferenced_(length);
    -
    92 m_state = state_t::fail;
    -
    93 return 0;
    -
    94 }
    +
    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 <string>
    +
    32#include <thread>
    +
    33#include <vector>
    +
    34
    +
    35#if !defined(SET_FILE_OP_TIMES) && defined(RDAT_BELEZI_CAS_DOSTOPA_VER)
    +
    36#define SET_FILE_OP_TIMES 1
    +
    37#pragma message("RDAT_BELEZI_CAS_DOSTOPA_VER is deprecated. Use SET_FILE_OP_TIMES instead.")
    +
    38#elif !defined(SET_FILE_OP_TIMES)
    +
    39#define SET_FILE_OP_TIMES 0
    +
    40#endif
    +
    41#if !defined(CHECK_STREAM_STATE) && defined(RDAT_NE_PREVERJAJ_STANJA_VER)
    +
    42#define CHECK_STREAM_STATE 0
    +
    43#pragma message("RDAT_NE_PREVERJAJ_EOF_VER is deprecated. Use CHECK_STREAM_STATE=0 instead.")
    +
    44#else
    +
    45#define CHECK_STREAM_STATE 1
    +
    46#endif
    +
    47
    +
    48namespace stdex
    +
    49{
    +
    50 namespace stream
    +
    51 {
    +
    55 enum class state_t {
    +
    56 ok = 0,
    +
    57 eof,
    +
    58 fail,
    +
    59 };
    +
    60
    +
    64 using fsize_t = uint64_t;
    +
    65 constexpr fsize_t fsize_max = UINT64_MAX;
    +
    66
    +
    67 constexpr size_t iterate_count = 0x10;
    +
    68 constexpr size_t default_block_size = 0x10000;
    +
    69 constexpr wchar_t utf16_bom = L'\ufeff';
    +
    70 constexpr const char utf8_bom[3] = { '\xef', '\xbb', '\xbf' };
    +
    71
    +
    +
    75 class basic
    +
    76 {
    +
    77 public:
    +
    78 basic(_In_ state_t state = state_t::ok) : m_state(state) {}
    +
    79
    +
    +
    91 virtual _Success_(return != 0 || length == 0) size_t read(
    +
    92 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
    +
    93 {
    +
    94 _Unreferenced_(data);
    +
    95 _Unreferenced_(length);
    +
    96 m_state = state_t::fail;
    +
    97 return 0;
    +
    98 }
    -
    95
    -
    -
    105 virtual _Success_(return != 0) size_t write(
    -
    106 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
    -
    107 {
    -
    108 _Unreferenced_(data);
    -
    109 _Unreferenced_(length);
    -
    110 m_state = state_t::fail;
    -
    111 return 0;
    -
    112 }
    +
    99
    +
    +
    109 virtual _Success_(return != 0) size_t write(
    +
    110 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
    +
    111 {
    +
    112 _Unreferenced_(data);
    +
    113 _Unreferenced_(length);
    +
    114 m_state = state_t::fail;
    +
    115 return 0;
    +
    116 }
    -
    113
    -
    -
    117 virtual void flush()
    -
    118 {
    -
    119 m_state = state_t::ok;
    -
    120 }
    +
    117
    +
    +
    121 virtual void flush()
    +
    122 {
    +
    123 m_state = state_t::ok;
    +
    124 }
    -
    121
    -
    -
    125 virtual void close()
    -
    126 {
    -
    127 m_state = state_t::ok;
    -
    128 }
    +
    125
    +
    +
    129 virtual void close()
    +
    130 {
    +
    131 m_state = state_t::ok;
    +
    132 }
    -
    129
    -
    -
    133 virtual void skip(_In_ fsize_t amount)
    -
    134 {
    -
    135 if (amount == 1)
    -
    136 read_byte();
    -
    137 else if (amount < iterate_count) {
    -
    138 for (size_t i = 0; i < static_cast<size_t>(amount); i++) {
    -
    139 read_byte();
    -
    140 if (!ok()) _Unlikely_
    -
    141 break;
    -
    142 }
    -
    143 }
    -
    144 else {
    -
    145 size_t block = static_cast<size_t>(std::min<fsize_t>(amount, default_block_size));
    -
    146 try {
    -
    147 std::unique_ptr<uint8_t[]> dummy(new uint8_t[block]);
    -
    148 while (amount) {
    -
    149 amount -= read_array(dummy.get(), sizeof(uint8_t), static_cast<size_t>(std::min<fsize_t>(amount, block)));
    -
    150 if (!ok()) _Unlikely_
    -
    151 break;
    -
    152 }
    -
    153 }
    -
    154 catch (const std::bad_alloc&) { m_state = state_t::fail; }
    -
    155 }
    -
    156 }
    +
    133
    +
    +
    137 virtual void skip(_In_ fsize_t amount)
    +
    138 {
    +
    139 if (amount == 1)
    +
    140 read_byte();
    +
    141 else if (amount < iterate_count) {
    +
    142 for (size_t i = 0; i < static_cast<size_t>(amount); i++) {
    +
    143 read_byte();
    +
    144 if (!ok()) _Unlikely_
    +
    145 break;
    +
    146 }
    +
    147 }
    +
    148 else {
    +
    149 size_t block = static_cast<size_t>(std::min<fsize_t>(amount, default_block_size));
    +
    150 try {
    +
    151 std::unique_ptr<uint8_t[]> dummy(new uint8_t[block]);
    +
    152 while (amount) {
    +
    153 amount -= read_array(dummy.get(), sizeof(uint8_t), static_cast<size_t>(std::min<fsize_t>(amount, block)));
    +
    154 if (!ok()) _Unlikely_
    +
    155 break;
    +
    156 }
    +
    157 }
    +
    158 catch (const std::bad_alloc&) { m_state = state_t::fail; }
    +
    159 }
    +
    160 }
    -
    157
    -
    161 inline state_t state() const { return m_state; };
    -
    162
    -
    166 inline bool ok() const { return m_state == state_t::ok; };
    -
    167
    -
    -
    175 virtual std::vector<uint8_t> read_remainder(_In_ size_t max_length = SIZE_MAX)
    -
    176 {
    -
    177 std::vector<uint8_t> result;
    -
    178 size_t offset, length;
    -
    179 offset = 0;
    -
    180 length = default_block_size;
    -
    181 while (offset < max_length) {
    -
    182 length = std::min(length, max_length);
    -
    183 try { result.resize(length); }
    -
    184 catch (const std::bad_alloc&) {
    -
    185 m_state = state_t::fail;
    -
    186 return result;
    -
    187 }
    -
    188 auto num_read = read_array(result.data() + offset, sizeof(uint8_t), length - offset);
    -
    189 offset += num_read;
    -
    190 if (!ok()) _Unlikely_
    -
    191 break;
    -
    192 length += default_block_size;
    -
    193 }
    -
    194 result.resize(offset);
    -
    195 return result;
    -
    196 }
    +
    161
    +
    165 inline state_t state() const { return m_state; };
    +
    166
    +
    170 inline bool ok() const { return m_state == state_t::ok; };
    +
    171
    +
    +
    179 virtual std::vector<uint8_t> read_remainder(_In_ size_t max_length = SIZE_MAX)
    +
    180 {
    +
    181 std::vector<uint8_t> result;
    +
    182 size_t offset, length;
    +
    183 offset = 0;
    +
    184 length = default_block_size;
    +
    185 while (offset < max_length) {
    +
    186 length = std::min(length, max_length);
    +
    187 try { result.resize(length); }
    +
    188 catch (const std::bad_alloc&) {
    +
    189 m_state = state_t::fail;
    +
    190 return result;
    +
    191 }
    +
    192 auto num_read = read_array(result.data() + offset, sizeof(uint8_t), length - offset);
    +
    193 offset += num_read;
    +
    194 if (!ok()) _Unlikely_
    +
    195 break;
    +
    196 length += default_block_size;
    +
    197 }
    +
    198 result.resize(offset);
    +
    199 return result;
    +
    200 }
    -
    197
    -
    -
    201 inline uint8_t read_byte()
    -
    202 {
    -
    203 uint8_t byte;
    -
    204 if (read_array(&byte, sizeof(byte), 1) == 1)
    -
    205 return byte;
    -
    206 throw std::runtime_error("failed to read");
    -
    207 }
    +
    201
    +
    +
    205 inline uint8_t read_byte()
    +
    206 {
    +
    207 uint8_t byte;
    +
    208 if (read_array(&byte, sizeof(byte), 1) == 1)
    +
    209 return byte;
    +
    210 throw std::runtime_error("failed to read");
    +
    211 }
    -
    208
    -
    -
    212 void write_byte(_In_ uint8_t byte, _In_ fsize_t amount = 1)
    -
    213 {
    -
    214 if (amount == 1)
    -
    215 write(&byte, sizeof(uint8_t));
    -
    216 else if (amount < iterate_count) {
    -
    217 for (size_t i = 0; i < static_cast<size_t>(amount); i++) {
    -
    218 write(&byte, sizeof(uint8_t));
    -
    219 if (!ok()) _Unlikely_
    -
    220 break;
    -
    221 }
    -
    222 }
    -
    223 else {
    -
    224 size_t block = static_cast<size_t>(std::min<fsize_t>(amount, default_block_size));
    -
    225 try {
    -
    226 std::unique_ptr<uint8_t[]> dummy(new uint8_t[block]);
    -
    227 memset(dummy.get(), byte, block);
    -
    228 while (amount) {
    -
    229 amount -= write_array(dummy.get(), sizeof(uint8_t), static_cast<size_t>(std::min<fsize_t>(amount, block)));
    -
    230 if (!ok()) _Unlikely_
    -
    231 break;
    -
    232 }
    -
    233 }
    -
    234 catch (const std::bad_alloc&) { m_state = state_t::fail; }
    -
    235 }
    -
    236 }
    +
    212
    +
    +
    216 void write_byte(_In_ uint8_t byte, _In_ fsize_t amount = 1)
    +
    217 {
    +
    218 if (amount == 1)
    +
    219 write(&byte, sizeof(uint8_t));
    +
    220 else if (amount < iterate_count) {
    +
    221 for (size_t i = 0; i < static_cast<size_t>(amount); i++) {
    +
    222 write(&byte, sizeof(uint8_t));
    +
    223 if (!ok()) _Unlikely_
    +
    224 break;
    +
    225 }
    +
    226 }
    +
    227 else {
    +
    228 size_t block = static_cast<size_t>(std::min<fsize_t>(amount, default_block_size));
    +
    229 try {
    +
    230 std::unique_ptr<uint8_t[]> dummy(new uint8_t[block]);
    +
    231 memset(dummy.get(), byte, block);
    +
    232 while (amount) {
    +
    233 amount -= write_array(dummy.get(), sizeof(uint8_t), static_cast<size_t>(std::min<fsize_t>(amount, block)));
    +
    234 if (!ok()) _Unlikely_
    +
    235 break;
    +
    236 }
    +
    237 }
    +
    238 catch (const std::bad_alloc&) { m_state = state_t::fail; }
    +
    239 }
    +
    240 }
    -
    237
    -
    249 template <class T>
    -
    -
    250 inline basic& read_data(_Out_ T& data)
    -
    251 {
    -
    252 if (!ok()) _Unlikely_ {
    -
    253 data = 0;
    -
    254 return *this;
    -
    255 }
    -
    256 if (read_array(&data, sizeof(T), 1) == 1)
    -
    257 LE2HE(&data);
    -
    258 else {
    -
    259 data = 0;
    -
    260 if (ok())
    -
    261 m_state = state_t::eof;
    -
    262 }
    -
    263 return *this;
    -
    264 }
    +
    241
    +
    253 template <class T>
    +
    +
    254 inline basic& read_data(_Out_ T& data)
    +
    255 {
    +
    256 if (!ok()) _Unlikely_ {
    +
    257 data = 0;
    +
    258 return *this;
    +
    259 }
    +
    260 if (read_array(&data, sizeof(T), 1) == 1)
    +
    261 (void)LE2HE(&data);
    +
    262 else {
    +
    263 data = 0;
    +
    264 if (ok())
    +
    265 m_state = state_t::eof;
    +
    266 }
    +
    267 return *this;
    +
    268 }
    -
    265
    -
    277 template <class T>
    -
    -
    278 inline basic& write_data(_In_ const T data)
    -
    279 {
    -
    280 if (!ok()) _Unlikely_
    -
    281 return *this;
    -
    282#ifdef BIG_ENDIAN
    -
    283 T data_le = HE2LE(data);
    -
    284 write(&data_le, sizeof(T));
    -
    285#else
    -
    286 write(&data, sizeof(T));
    -
    287#endif
    -
    288 return *this;
    -
    289 }
    +
    269
    +
    281 template <class T>
    +
    +
    282 inline basic& write_data(_In_ const T data)
    +
    283 {
    +
    284 if (!ok()) _Unlikely_
    +
    285 return *this;
    +
    286#if BYTE_ORDER == BIG_ENDIAN
    +
    287 T data_le = HE2LE(data);
    +
    288 write(&data_le, sizeof(T));
    +
    289#else
    +
    290 write(&data, sizeof(T));
    +
    291#endif
    +
    292 return *this;
    +
    293 }
    -
    290
    -
    296 template<class _Traits = std::char_traits<char>, class _Ax = std::allocator<char>>
    -
    -
    297 inline size_t readln(_Inout_ std::basic_string<char, _Traits, _Ax>& str)
    -
    298 {
    -
    299 str.clear();
    -
    300 return readln_and_attach(str);
    -
    301 }
    +
    294
    +
    300 template<class _Traits = std::char_traits<char>, class _Ax = std::allocator<char>>
    +
    +
    301 inline size_t readln(_Inout_ std::basic_string<char, _Traits, _Ax>& str)
    +
    302 {
    +
    303 str.clear();
    +
    304 return readln_and_attach(str);
    +
    305 }
    -
    302
    -
    308 template<class _Traits = std::char_traits<wchar_t>, class _Ax = std::allocator<wchar_t>>
    -
    -
    309 inline size_t readln(_Inout_ std::basic_string<wchar_t, _Traits, _Ax>& wstr)
    -
    310 {
    -
    311 wstr.clear();
    -
    312 return readln_and_attach(wstr);
    -
    313 }
    +
    306
    +
    312 template<class _Traits = std::char_traits<wchar_t>, class _Ax = std::allocator<wchar_t>>
    +
    +
    313 inline size_t readln(_Inout_ std::basic_string<wchar_t, _Traits, _Ax>& wstr)
    +
    314 {
    +
    315 wstr.clear();
    +
    316 return readln_and_attach(wstr);
    +
    317 }
    -
    314
    -
    320 template<class _Traits = std::char_traits<wchar_t>, class _Ax = std::allocator<wchar_t>>
    -
    -
    321 size_t readln(_Inout_ std::basic_string<wchar_t, _Traits, _Ax>& wstr, _In_ charset_id charset)
    -
    322 {
    -
    323 if (charset == charset_id::utf16)
    -
    324 return readln(wstr);
    -
    325 std::string str;
    - -
    327 wstr.clear();
    -
    328 str2wstr(wstr, str, charset);
    -
    329 return wstr.size();
    -
    330 }
    +
    318
    +
    324 template<class _Traits = std::char_traits<wchar_t>, class _Ax = std::allocator<wchar_t>>
    +
    +
    325 size_t readln(_Inout_ std::basic_string<wchar_t, _Traits, _Ax>& wstr, _In_ charset_id charset)
    +
    326 {
    +
    327 if (charset == charset_id::utf16)
    +
    328 return readln(wstr);
    +
    329 std::string str;
    + +
    331 wstr.clear();
    +
    332 str2wstr(wstr, str, charset);
    +
    333 return wstr.size();
    +
    334 }
    -
    331
    -
    337 template<class _Elem, class _Traits = std::char_traits<_Elem>, class _Ax = std::allocator<_Elem>>
    -
    -
    338 size_t readln_and_attach(_Inout_ std::basic_string<_Elem, _Traits, _Ax>& str)
    -
    339 {
    -
    340 bool initial = true;
    -
    341 _Elem chr, previous = (_Elem)0;
    -
    342 do {
    -
    343 read_array(&chr, sizeof(_Elem), 1);
    -
    344 if (!initial && !(previous == static_cast<_Elem>('\r') && chr == static_cast<_Elem>('\n')))
    -
    345 str += previous;
    -
    346 else
    -
    347 initial = false;
    -
    348 previous = chr;
    -
    349 } while (ok() && chr != static_cast<_Elem>('\n'));
    -
    350 return str.size();
    -
    351 }
    +
    335
    +
    341 template<class _Elem, class _Traits = std::char_traits<_Elem>, class _Ax = std::allocator<_Elem>>
    +
    +
    342 size_t readln_and_attach(_Inout_ std::basic_string<_Elem, _Traits, _Ax>& str)
    +
    343 {
    +
    344 bool initial = true;
    +
    345 _Elem chr, previous = (_Elem)0;
    +
    346 do {
    +
    347 read_array(&chr, sizeof(_Elem), 1);
    +
    348 if (!initial && !(previous == static_cast<_Elem>('\r') && chr == static_cast<_Elem>('\n')))
    +
    349 str += previous;
    +
    350 else
    +
    351 initial = false;
    +
    352 previous = chr;
    +
    353 } while (ok() && chr != static_cast<_Elem>('\n'));
    +
    354 return str.size();
    +
    355 }
    -
    352
    -
    358 template<class _Traits = std::char_traits<wchar_t>, class _Ax = std::allocator<wchar_t>>
    -
    -
    359 size_t readln_and_attach(_Inout_ std::basic_string<wchar_t, _Traits, _Ax>& wstr, _In_ charset_id charset)
    -
    360 {
    -
    361 if (charset == charset_id::utf16)
    -
    362 return readln_and_attach(wstr);
    -
    363 std::string str;
    - -
    365 str2wstr(wstr, str, charset);
    -
    366 return wstr.size();
    -
    367 }
    +
    356
    +
    362 template<class _Traits = std::char_traits<wchar_t>, class _Ax = std::allocator<wchar_t>>
    +
    +
    363 size_t readln_and_attach(_Inout_ std::basic_string<wchar_t, _Traits, _Ax>& wstr, _In_ charset_id charset)
    +
    364 {
    +
    365 if (charset == charset_id::utf16)
    +
    366 return readln_and_attach(wstr);
    +
    367 std::string str;
    + +
    369 str2wstr(wstr, str, charset);
    +
    370 return wstr.size();
    +
    371 }
    -
    368
    -
    -
    374 size_t read_array(_Out_writes_bytes_(size* count) void* array, _In_ size_t size, _In_ size_t count)
    -
    375 {
    -
    376 for (size_t to_read = mul(size, count);;) {
    -
    377 size_t num_read = read(array, to_read);
    -
    378 to_read -= num_read;
    -
    379 if (!to_read)
    -
    380 return count;
    -
    381 if (!ok()) _Unlikely_
    -
    382 return count - to_read / size;
    -
    383 reinterpret_cast<uint8_t*&>(array) += num_read;
    -
    384 }
    -
    385 }
    +
    372
    +
    +
    378 size_t read_array(_Out_writes_bytes_(size* count) void* array, _In_ size_t size, _In_ size_t count)
    +
    379 {
    +
    380 for (size_t to_read = mul(size, count);;) {
    +
    381 size_t num_read = read(array, to_read);
    +
    382 to_read -= num_read;
    +
    383 if (!to_read)
    +
    384 return count;
    +
    385 if (!ok()) _Unlikely_
    +
    386 return count - to_read / size;
    +
    387 reinterpret_cast<uint8_t*&>(array) += num_read;
    +
    388 }
    +
    389 }
    -
    386
    -
    -
    392 inline size_t write_array(_In_reads_bytes_opt_(size* count) const void* array, _In_ size_t size, _In_ size_t count)
    -
    393 {
    -
    394 return write(array, mul(size, count)) / size;
    -
    395 }
    +
    390
    +
    +
    396 inline size_t write_array(_In_reads_bytes_opt_(size* count) const void* array, _In_ size_t size, _In_ size_t count)
    +
    397 {
    +
    398 return write(array, mul(size, count)) / size;
    +
    399 }
    -
    396
    -
    -
    405 size_t write_array(_In_z_ const wchar_t* wstr, _In_ charset_id charset)
    -
    406 {
    -
    407 if (!ok()) _Unlikely_
    -
    408 return 0;
    -
    409 size_t num_chars = stdex::strlen(wstr);
    -
    410 if (charset != charset_id::utf16) {
    -
    411 std::string str(wstr2str(wstr, num_chars, charset));
    -
    412 return write_array(str.data(), sizeof(char), str.size());
    -
    413 }
    -
    414 return write_array(wstr, sizeof(wchar_t), num_chars);
    -
    415 }
    +
    400
    +
    +
    409 size_t write_array(_In_z_ const wchar_t* wstr, _In_ charset_id charset)
    +
    410 {
    +
    411 if (!ok()) _Unlikely_
    +
    412 return 0;
    +
    413 size_t num_chars = stdex::strlen(wstr);
    +
    414 if (charset != charset_id::utf16) {
    +
    415 std::string str(wstr2str(wstr, num_chars, charset));
    +
    416 return write_array(str.data(), sizeof(char), str.size());
    +
    417 }
    +
    418 return write_array(wstr, sizeof(wchar_t), num_chars);
    +
    419 }
    -
    416
    -
    -
    426 size_t write_array(_In_reads_or_z_opt_(num_chars) const wchar_t* wstr, _In_ size_t num_chars, _In_ charset_id charset)
    -
    427 {
    -
    428 if (!ok()) _Unlikely_
    -
    429 return 0;
    -
    430 num_chars = stdex::strnlen(wstr, num_chars);
    -
    431 if (charset != charset_id::utf16) {
    -
    432 std::string str(wstr2str(wstr, num_chars, charset));
    -
    433 return write_array(str.data(), sizeof(char), str.size());
    -
    434 }
    -
    435 return write_array(wstr, sizeof(wchar_t), num_chars);
    -
    436 }
    +
    420
    +
    +
    430 size_t write_array(_In_reads_or_z_opt_(num_chars) const wchar_t* wstr, _In_ size_t num_chars, _In_ charset_id charset)
    +
    431 {
    +
    432 if (!ok()) _Unlikely_
    +
    433 return 0;
    +
    434 num_chars = stdex::strnlen(wstr, num_chars);
    +
    435 if (charset != charset_id::utf16) {
    +
    436 std::string str(wstr2str(wstr, num_chars, charset));
    +
    437 return write_array(str.data(), sizeof(char), str.size());
    +
    438 }
    +
    439 return write_array(wstr, sizeof(wchar_t), num_chars);
    +
    440 }
    -
    437
    -
    446 template<class _Traits = std::char_traits<wchar_t>, class _Ax = std::allocator<wchar_t>>
    -
    -
    447 size_t write_array(_In_ const std::basic_string<wchar_t, _Traits, _Ax>& wstr, _In_ charset_id charset)
    -
    448 {
    -
    449 if (!ok()) _Unlikely_
    -
    450 return 0;
    -
    451 if (charset != charset_id::utf16) {
    -
    452 std::string str(wstr2str(wstr, charset));
    -
    453 return write_array(str.data(), sizeof(char), str.size());
    -
    454 }
    -
    455 return write_array(wstr.data(), sizeof(wchar_t), wstr.size());
    -
    456 }
    +
    441
    +
    450 template<class _Traits = std::char_traits<wchar_t>, class _Ax = std::allocator<wchar_t>>
    +
    +
    451 size_t write_array(_In_ const std::basic_string<wchar_t, _Traits, _Ax>& wstr, _In_ charset_id charset)
    +
    452 {
    +
    453 if (!ok()) _Unlikely_
    +
    454 return 0;
    +
    455 if (charset != charset_id::utf16) {
    +
    456 std::string str(wstr2str(wstr, charset));
    +
    457 return write_array(str.data(), sizeof(char), str.size());
    +
    458 }
    +
    459 return write_array(wstr.data(), sizeof(wchar_t), wstr.size());
    +
    460 }
    -
    457
    -
    469 template<class _Elem, class _Traits = std::char_traits<_Elem>, class _Ax = std::allocator<_Elem>>
    -
    -
    470 inline basic& read_str(_Inout_ std::basic_string<_Elem, _Traits, _Ax>& data)
    -
    471 {
    -
    472 uint32_t num_chars;
    -
    473 read_data(num_chars);
    -
    474 if (!ok()) _Unlikely_ {
    -
    475 data.clear();
    -
    476 return *this;
    -
    477 }
    -
    478 data.resize(num_chars);
    -
    479 data.resize(read_array(data.data(), sizeof(_Elem), num_chars));
    -
    480 return *this;
    -
    481 }
    +
    461
    +
    473 template<class _Elem, class _Traits = std::char_traits<_Elem>, class _Ax = std::allocator<_Elem>>
    +
    +
    474 inline basic& read_str(_Inout_ std::basic_string<_Elem, _Traits, _Ax>& data)
    +
    475 {
    +
    476 uint32_t num_chars;
    +
    477 read_data(num_chars);
    +
    478 if (!ok()) _Unlikely_ {
    +
    479 data.clear();
    +
    480 return *this;
    +
    481 }
    +
    482 data.resize(num_chars);
    +
    483 data.resize(read_array(data.data(), sizeof(_Elem), num_chars));
    +
    484 return *this;
    +
    485 }
    -
    482
    -
    494 template <class T>
    -
    -
    495 inline basic& write_str(_In_z_ const T* data)
    -
    496 {
    -
    497 // Stream state will be checked in write_data.
    -
    498 size_t num_chars = stdex::strlen(data);
    -
    499 if (num_chars > UINT32_MAX)
    -
    500 throw std::invalid_argument("string too long");
    -
    501 write_data((uint32_t)num_chars);
    -
    502 if (!ok()) _Unlikely_
    -
    503 return *this;
    -
    504 write_array(data, sizeof(T), num_chars);
    -
    505 return *this;
    -
    506 }
    +
    486
    +
    498 template <class T>
    +
    +
    499 inline basic& write_str(_In_z_ const T* data)
    +
    500 {
    +
    501 // Stream state will be checked in write_data.
    +
    502 size_t num_chars = stdex::strlen(data);
    +
    503 if (num_chars > UINT32_MAX)
    +
    504 throw std::invalid_argument("string too long");
    +
    505 write_data((uint32_t)num_chars);
    +
    506 if (!ok()) _Unlikely_
    +
    507 return *this;
    +
    508 write_array(data, sizeof(T), num_chars);
    +
    509 return *this;
    +
    510 }
    -
    507
    -
    508#ifdef _WIN32
    -
    514 size_t write_sa(_In_ LPSAFEARRAY sa)
    -
    515 {
    -
    516 safearray_accessor<void> a(sa);
    -
    517 long ubound, lbound;
    -
    518 if (FAILED(SafeArrayGetUBound(sa, 1, &ubound)) ||
    -
    519 FAILED(SafeArrayGetLBound(sa, 1, &lbound)))
    -
    520 throw std::invalid_argument("SafeArrayGet[UL]Bound failed");
    -
    521 return write(a.data(), static_cast<size_t>(ubound) - lbound + 1);
    -
    522 }
    -
    523#endif
    -
    524
    -
    -
    530 fsize_t write_stream(_Inout_ basic& stream, _In_ fsize_t amount = fsize_max)
    -
    531 {
    -
    532 std::unique_ptr<uint8_t[]> data(new uint8_t[static_cast<size_t>(std::min<fsize_t>(amount, default_block_size))]);
    -
    533 fsize_t num_copied = 0, to_write = amount;
    -
    534 m_state = state_t::ok;
    -
    535 while (to_write) {
    -
    536 size_t num_read = stream.read(data.get(), static_cast<size_t>(std::min<fsize_t>(default_block_size, to_write)));
    -
    537 size_t num_written = write(data.get(), num_read);
    -
    538 num_copied += num_written;
    -
    539 to_write -= num_written;
    -
    540 if (stream.m_state == state_t::eof) {
    -
    541 // EOF is not an error.
    -
    542 m_state = state_t::ok;
    -
    543 break;
    -
    544 }
    -
    545 m_state = stream.m_state;
    -
    546 if (!ok())
    +
    511
    +
    512#ifdef _WIN32
    +
    518 size_t write_sa(_In_ LPSAFEARRAY sa)
    +
    519 {
    +
    520 safearray_accessor<void> a(sa);
    +
    521 long ubound, lbound;
    +
    522 if (FAILED(SafeArrayGetUBound(sa, 1, &ubound)) ||
    +
    523 FAILED(SafeArrayGetLBound(sa, 1, &lbound)))
    +
    524 throw std::invalid_argument("SafeArrayGet[UL]Bound failed");
    +
    525 return write(a.data(), static_cast<size_t>(ubound) - lbound + 1);
    +
    526 }
    +
    527#endif
    +
    528
    +
    +
    534 fsize_t write_stream(_Inout_ basic& stream, _In_ fsize_t amount = fsize_max)
    +
    535 {
    +
    536 std::unique_ptr<uint8_t[]> data(new uint8_t[static_cast<size_t>(std::min<fsize_t>(amount, default_block_size))]);
    +
    537 fsize_t num_copied = 0, to_write = amount;
    +
    538 m_state = state_t::ok;
    +
    539 while (to_write) {
    +
    540 size_t num_read = stream.read(data.get(), static_cast<size_t>(std::min<fsize_t>(default_block_size, to_write)));
    +
    541 size_t num_written = write(data.get(), num_read);
    +
    542 num_copied += num_written;
    +
    543 to_write -= num_written;
    +
    544 if (stream.m_state == state_t::eof) {
    +
    545 // EOF is not an error.
    +
    546 m_state = state_t::ok;
    547 break;
    -
    548 }
    -
    549 return num_copied;
    -
    550 }
    +
    548 }
    +
    549 m_state = stream.m_state;
    +
    550 if (!ok())
    +
    551 break;
    +
    552 }
    +
    553 return num_copied;
    +
    554 }
    -
    551
    -
    -
    555 void write_charset(_In_ charset_id charset)
    -
    556 {
    -
    557 if (charset == charset_id::utf16)
    -
    558 write_data(utf16_bom);
    -
    559 else if (charset == charset_id::utf8)
    -
    560 write_array(utf8_bom, sizeof(utf8_bom), 1);
    -
    561 }
    +
    555
    +
    +
    559 void write_charset(_In_ charset_id charset)
    +
    560 {
    +
    561 if (charset == charset_id::utf16)
    +
    562 write_data(utf16_bom);
    +
    563 else if (charset == charset_id::utf8)
    +
    564 write_array(utf8_bom, sizeof(utf8_bom), 1);
    +
    565 }
    -
    562
    -
    -
    568 size_t write_sprintf(_In_z_ _Printf_format_string_params_(2) const char* format, _In_opt_ locale_t locale, ...)
    -
    569 {
    -
    570 va_list params;
    -
    571 va_start(params, locale);
    -
    572 size_t num_chars = write_vsprintf(format, locale, params);
    -
    573 va_end(params);
    -
    574 return num_chars;
    -
    575 }
    +
    566
    +
    +
    572 size_t write_sprintf(_In_z_ _Printf_format_string_params_(2) const char* format, _In_opt_ locale_t locale, ...)
    +
    573 {
    +
    574 va_list params;
    +
    575 va_start(params, locale);
    +
    576 size_t num_chars = write_vsprintf(format, locale, params);
    +
    577 va_end(params);
    +
    578 return num_chars;
    +
    579 }
    -
    576
    -
    -
    582 size_t write_sprintf(_In_z_ _Printf_format_string_params_(2) const wchar_t* format, _In_opt_ locale_t locale, ...)
    -
    583 {
    -
    584 va_list params;
    -
    585 va_start(params, locale);
    -
    586 size_t num_chars = write_vsprintf(format, locale, params);
    -
    587 va_end(params);
    -
    588 return num_chars;
    -
    589 }
    +
    580
    +
    +
    586 size_t write_sprintf(_In_z_ _Printf_format_string_params_(2) const wchar_t* format, _In_opt_ locale_t locale, ...)
    +
    587 {
    +
    588 va_list params;
    +
    589 va_start(params, locale);
    +
    590 size_t num_chars = write_vsprintf(format, locale, params);
    +
    591 va_end(params);
    +
    592 return num_chars;
    +
    593 }
    -
    590
    -
    -
    596 size_t write_vsprintf(_In_z_ _Printf_format_string_params_(2) const char* format, _In_opt_ locale_t locale, _In_ va_list params)
    -
    597 {
    -
    598 std::string str;
    -
    599 str.reserve(default_block_size);
    -
    600 vappendf(str, format, locale, params);
    -
    601 return write_array(str.data(), sizeof(char), str.size());
    -
    602 }
    +
    594
    +
    +
    600 size_t write_vsprintf(_In_z_ _Printf_format_string_params_(2) const char* format, _In_opt_ locale_t locale, _In_ va_list params)
    +
    601 {
    +
    602 std::string str;
    +
    603 str.reserve(default_block_size);
    +
    604 vappendf(str, format, locale, params);
    +
    605 return write_array(str.data(), sizeof(char), str.size());
    +
    606 }
    -
    603
    -
    -
    609 size_t write_vsprintf(_In_z_ _Printf_format_string_params_(2) const wchar_t* format, _In_opt_ locale_t locale, _In_ va_list params)
    -
    610 {
    -
    611 std::wstring str;
    -
    612 str.reserve(default_block_size);
    -
    613 vappendf(str, format, locale, params);
    -
    614 return write_array(str.data(), sizeof(wchar_t), str.size());
    -
    615 }
    +
    607
    +
    +
    613 size_t write_vsprintf(_In_z_ _Printf_format_string_params_(2) const wchar_t* format, _In_opt_ locale_t locale, _In_ va_list params)
    +
    614 {
    +
    615 std::wstring str;
    +
    616 str.reserve(default_block_size);
    +
    617 vappendf(str, format, locale, params);
    +
    618 return write_array(str.data(), sizeof(wchar_t), str.size());
    +
    619 }
    -
    616
    -
    617 inline basic& operator >>(_Out_ int8_t& data) { return read_data(data); }
    -
    618 inline basic& operator <<(_In_ const int8_t data) { return write_data(data); }
    -
    619 inline basic& operator >>(_Out_ int16_t& data) { return read_data(data); }
    -
    620 inline basic& operator <<(_In_ const int16_t data) { return write_data(data); }
    -
    621 inline basic& operator >>(_Out_ int32_t& data) { return read_data(data); }
    -
    622 inline basic& operator <<(_In_ const int32_t data) { return write_data(data); }
    -
    623 inline basic& operator >>(_Out_ int64_t& data) { return read_data(data); }
    -
    624 inline basic& operator <<(_In_ const int64_t data) { return write_data(data); }
    -
    625 inline basic& operator >>(_Out_ uint8_t& data) { return read_data(data); }
    -
    626 inline basic& operator <<(_In_ const uint8_t data) { return write_data(data); }
    -
    627 inline basic& operator >>(_Out_ uint16_t& data) { return read_data(data); }
    -
    628 inline basic& operator <<(_In_ const uint16_t data) { return write_data(data); }
    -
    629 inline basic& operator >>(_Out_ uint32_t& data) { return read_data(data); }
    -
    630 inline basic& operator <<(_In_ const uint32_t data) { return write_data(data); }
    -
    631 inline basic& operator >>(_Out_ uint64_t& data) { return read_data(data); }
    -
    632 inline basic& operator <<(_In_ const uint64_t data) { return write_data(data); }
    -
    633#if defined(_WIN64) && defined(_NATIVE_SIZE_T_DEFINED)
    -
    634 inline basic& operator >>(_Out_ size_t& data) { return read_data(data); }
    -
    635 inline basic& operator <<(_In_ const size_t data) { return write_data(data); }
    -
    636#endif
    +
    620
    +
    621 inline basic& operator >>(_Out_ int8_t& data) { return read_data(data); }
    +
    622 inline basic& operator <<(_In_ const int8_t data) { return write_data(data); }
    +
    623 inline basic& operator >>(_Out_ int16_t& data) { return read_data(data); }
    +
    624 inline basic& operator <<(_In_ const int16_t data) { return write_data(data); }
    +
    625 inline basic& operator >>(_Out_ int32_t& data) { return read_data(data); }
    +
    626 inline basic& operator <<(_In_ const int32_t data) { return write_data(data); }
    +
    627 inline basic& operator >>(_Out_ int64_t& data) { return read_data(data); }
    +
    628 inline basic& operator <<(_In_ const int64_t data) { return write_data(data); }
    +
    629 inline basic& operator >>(_Out_ uint8_t& data) { return read_data(data); }
    +
    630 inline basic& operator <<(_In_ const uint8_t data) { return write_data(data); }
    +
    631 inline basic& operator >>(_Out_ uint16_t& data) { return read_data(data); }
    +
    632 inline basic& operator <<(_In_ const uint16_t data) { return write_data(data); }
    +
    633 inline basic& operator >>(_Out_ uint32_t& data) { return read_data(data); }
    +
    634 inline basic& operator <<(_In_ const uint32_t data) { return write_data(data); }
    +
    635 inline basic& operator >>(_Out_ uint64_t& data) { return read_data(data); }
    +
    636 inline basic& operator <<(_In_ const uint64_t data) { return write_data(data); }
    637 inline basic& operator >>(_Out_ float& data) { return read_data(data); }
    638 inline basic& operator <<(_In_ const float data) { return write_data(data); }
    639 inline basic& operator >>(_Out_ double& data) { return read_data(data); }
    @@ -622,3252 +622,3250 @@ $(document).ready(function() { init_codefold(0); });
    683 };
    684
    685#if _HAS_CXX20
    -
    686 using time_point = std::chrono::time_point<std::chrono::file_clock>;
    +
    686 using clock = std::chrono::file_clock;
    687#else
    -
    688 using time_point = std::chrono::time_point<std::chrono::system_clock>;
    +
    688 using clock = std::chrono::system_clock;
    689#endif
    -
    690
    -
    -
    694 class basic_file : virtual public basic
    -
    695 {
    -
    696 public:
    -
    -
    697 virtual std::vector<uint8_t> read_remainder(_In_ size_t max_length = SIZE_MAX)
    -
    698 {
    -
    699 size_t length = std::min<size_t>(max_length, static_cast<size_t>(size() - tell()));
    -
    700 std::vector<uint8_t> result;
    -
    701 try { result.resize(length); }
    -
    702 catch (const std::bad_alloc&) {
    -
    703 m_state = state_t::fail;
    -
    704 return result;
    -
    705 }
    -
    706 result.resize(read_array(result.data(), sizeof(uint8_t), length));
    -
    707 return result;
    -
    708 }
    +
    690 using time_point = std::chrono::time_point<clock>;
    +
    691
    +
    +
    695 class basic_file : virtual public basic
    +
    696 {
    +
    697 public:
    +
    +
    698 virtual std::vector<uint8_t> read_remainder(_In_ size_t max_length = SIZE_MAX)
    +
    699 {
    +
    700 size_t length = std::min<size_t>(max_length, static_cast<size_t>(size() - tell()));
    +
    701 std::vector<uint8_t> result;
    +
    702 try { result.resize(length); }
    +
    703 catch (const std::bad_alloc&) {
    +
    704 m_state = state_t::fail;
    +
    705 return result;
    +
    706 }
    +
    707 result.resize(read_array(result.data(), sizeof(uint8_t), length));
    +
    708 return result;
    +
    709 }
    -
    709
    -
    715 virtual fpos_t seek(_In_ foff_t offset, _In_ seek_t how = seek_t::beg) = 0;
    -
    716
    -
    722 inline fpos_t seekbeg(_In_ fpos_t offset) { return seek(offset, seek_t::beg); }
    -
    723
    -
    729 inline fpos_t seekcur(_In_ foff_t offset) { return seek(offset, seek_t::cur); }
    -
    730
    -
    736 inline fpos_t seekend(_In_ foff_t offset) { return seek(offset, seek_t::end); }
    -
    737
    -
    -
    738 virtual void skip(_In_ fsize_t amount)
    -
    739 {
    -
    740 seek(amount, seek_t::cur);
    -
    741 }
    +
    710
    +
    716 virtual fpos_t seek(_In_ foff_t offset, _In_ seek_t how = seek_t::beg) = 0;
    +
    717
    +
    723 inline fpos_t seekbeg(_In_ fpos_t offset) { return seek(offset, seek_t::beg); }
    +
    724
    +
    730 inline fpos_t seekcur(_In_ foff_t offset) { return seek(offset, seek_t::cur); }
    +
    731
    +
    737 inline fpos_t seekend(_In_ foff_t offset) { return seek(offset, seek_t::end); }
    +
    738
    +
    +
    739 virtual void skip(_In_ fsize_t amount)
    +
    740 {
    +
    741 seek(amount, seek_t::cur);
    +
    742 }
    -
    742
    -
    749 virtual fpos_t tell() const = 0;
    -
    750
    -
    -
    754 virtual void lock(_In_ fpos_t offset, _In_ fsize_t length)
    -
    755 {
    -
    756 _Unreferenced_(offset);
    -
    757 _Unreferenced_(length);
    -
    758 throw std::exception("not implemented");
    -
    759 }
    +
    743
    +
    750 virtual fpos_t tell() const = 0;
    +
    751
    +
    +
    755 virtual void lock(_In_ fpos_t offset, _In_ fsize_t length)
    +
    756 {
    +
    757 _Unreferenced_(offset);
    +
    758 _Unreferenced_(length);
    +
    759 throw std::domain_error("not implemented");
    +
    760 }
    -
    760
    -
    -
    764 virtual void unlock(_In_ fpos_t offset, _In_ fsize_t length)
    -
    765 {
    -
    766 _Unreferenced_(offset);
    -
    767 _Unreferenced_(length);
    -
    768 throw std::exception("not implemented");
    -
    769 }
    +
    761
    +
    +
    765 virtual void unlock(_In_ fpos_t offset, _In_ fsize_t length)
    +
    766 {
    +
    767 _Unreferenced_(offset);
    +
    768 _Unreferenced_(length);
    +
    769 throw std::domain_error("not implemented");
    +
    770 }
    -
    770
    -
    775 virtual fsize_t size() = 0;
    -
    776
    -
    780 virtual void truncate() = 0;
    -
    781
    -
    -
    785 virtual time_point ctime() const
    -
    786 {
    -
    787 return time_point::min();
    -
    788 }
    +
    771
    +
    776 virtual fsize_t size() = 0;
    +
    777
    +
    781 virtual void truncate() = 0;
    +
    782
    +
    +
    786 virtual time_point ctime() const
    +
    787 {
    +
    788 return time_point::min();
    +
    789 }
    -
    789
    -
    -
    793 virtual time_point atime() const
    -
    794 {
    -
    795 return time_point::min();
    -
    796 }
    +
    790
    +
    +
    794 virtual time_point atime() const
    +
    795 {
    +
    796 return time_point::min();
    +
    797 }
    -
    797
    -
    -
    801 virtual time_point mtime() const
    -
    802 {
    -
    803 return time_point::min();
    -
    804 }
    +
    798
    +
    +
    802 virtual time_point mtime() const
    +
    803 {
    +
    804 return time_point::min();
    +
    805 }
    -
    805
    -
    -
    809 virtual void set_ctime(time_point date)
    -
    810 {
    -
    811 _Unreferenced_(date);
    -
    812 throw std::exception("not implemented");
    -
    813 }
    +
    806
    +
    +
    810 virtual void set_ctime(time_point date)
    +
    811 {
    +
    812 _Unreferenced_(date);
    +
    813 throw std::domain_error("not implemented");
    +
    814 }
    -
    814
    -
    -
    818 virtual void set_atime(time_point date)
    -
    819 {
    -
    820 _Unreferenced_(date);
    -
    821 throw std::exception("not implemented");
    -
    822 }
    +
    815
    +
    +
    819 virtual void set_atime(time_point date)
    +
    820 {
    +
    821 _Unreferenced_(date);
    +
    822 throw std::domain_error("not implemented");
    +
    823 }
    -
    823
    -
    -
    827 virtual void set_mtime(time_point date)
    -
    828 {
    -
    829 _Unreferenced_(date);
    -
    830 throw std::exception("not implemented");
    -
    831 }
    +
    824
    +
    +
    828 virtual void set_mtime(time_point date)
    +
    829 {
    +
    830 _Unreferenced_(date);
    +
    831 throw std::domain_error("not implemented");
    +
    832 }
    -
    832
    -
    833#ifdef _WIN32
    -
    837 LPSAFEARRAY read_sa()
    -
    838 {
    -
    839 assert(size() <= SIZE_MAX);
    -
    840 size_t length = static_cast<size_t>(size());
    -
    841 std::unique_ptr<SAFEARRAY, SafeArrayDestroy_delete> sa(SafeArrayCreateVector(VT_UI1, 0, (ULONG)length));
    -
    842 if (!sa)
    -
    843 throw std::runtime_error("SafeArrayCreateVector failed");
    -
    844 safearray_accessor<void> a(sa.get());
    -
    845 if (seek(0) != 0)
    -
    846 throw std::runtime_error("failed to seek");
    -
    847 if (read_array(a.data(), 1, length) != length)
    -
    848 throw std::runtime_error("failed to read");
    -
    849 return sa.release();
    -
    850 }
    -
    851#endif
    -
    852
    -
    -
    858 charset_id read_charset(_In_ charset_id default_charset = charset_id::default)
    -
    859 {
    -
    860 if (seek(0) != 0)
    -
    861 throw std::runtime_error("failed to seek");
    -
    862 wchar_t id_utf16;
    -
    863 read_array(&id_utf16, sizeof(wchar_t), 1);
    -
    864 if (!ok()) _Unlikely_
    -
    865 return default_charset;
    -
    866 if (id_utf16 == utf16_bom)
    -
    867 return charset_id::utf16;
    -
    868
    -
    869 if (seek(0) != 0)
    -
    870 throw std::runtime_error("failed to seek");
    -
    871 char id_utf8[3] = { 0 };
    -
    872 read_array(id_utf8, sizeof(id_utf8), 1);
    -
    873 if (!ok()) _Unlikely_
    -
    874 return default_charset;
    -
    875 if (strncmp(id_utf8, _countof(id_utf8), utf8_bom, _countof(utf8_bom)) == 0)
    -
    876 return charset_id::utf8;
    -
    877
    -
    878 if (seek(0) != 0)
    -
    879 throw std::runtime_error("failed to seek");
    -
    880 return default_charset;
    -
    881 }
    +
    833
    +
    834#ifdef _WIN32
    +
    838 LPSAFEARRAY read_sa()
    +
    839 {
    +
    840 assert(size() <= SIZE_MAX);
    +
    841 size_t length = static_cast<size_t>(size());
    +
    842 std::unique_ptr<SAFEARRAY, SafeArrayDestroy_delete> sa(SafeArrayCreateVector(VT_UI1, 0, (ULONG)length));
    +
    843 if (!sa)
    +
    844 throw std::runtime_error("SafeArrayCreateVector failed");
    +
    845 safearray_accessor<void> a(sa.get());
    +
    846 if (seek(0) != 0)
    +
    847 throw std::runtime_error("failed to seek");
    +
    848 if (read_array(a.data(), 1, length) != length)
    +
    849 throw std::runtime_error("failed to read");
    +
    850 return sa.release();
    +
    851 }
    +
    852#endif
    +
    853
    +
    +
    859 charset_id read_charset(_In_ charset_id default_charset = charset_id::system)
    +
    860 {
    +
    861 if (seek(0) != 0)
    +
    862 throw std::runtime_error("failed to seek");
    +
    863 wchar_t id_utf16;
    +
    864 read_array(&id_utf16, sizeof(wchar_t), 1);
    +
    865 if (!ok()) _Unlikely_
    +
    866 return default_charset;
    +
    867 if (id_utf16 == utf16_bom)
    +
    868 return charset_id::utf16;
    +
    869
    +
    870 if (seek(0) != 0)
    +
    871 throw std::runtime_error("failed to seek");
    +
    872 char id_utf8[3] = { 0 };
    +
    873 read_array(id_utf8, sizeof(id_utf8), 1);
    +
    874 if (!ok()) _Unlikely_
    +
    875 return default_charset;
    +
    876 if (strncmp(id_utf8, _countof(id_utf8), utf8_bom, _countof(utf8_bom)) == 0)
    +
    877 return charset_id::utf8;
    +
    878
    +
    879 if (seek(0) != 0)
    +
    880 throw std::runtime_error("failed to seek");
    +
    881 return default_charset;
    +
    882 }
    -
    882 };
    +
    883 };
    -
    883
    -
    -
    887 class converter : public basic
    -
    888 {
    -
    889 protected:
    -
    890 explicit converter() :
    -
    891 basic(state_t::fail),
    -
    892 m_source(nullptr)
    -
    893 {}
    -
    894
    -
    895 void init(_Inout_ basic& source)
    -
    896 {
    -
    897 m_state = source.state();
    -
    898 m_source = &source;
    -
    899 }
    -
    900
    -
    901 void done()
    -
    902 {
    -
    903 m_source = nullptr;
    -
    904 }
    -
    905
    -
    906 public:
    -
    907 converter(_Inout_ basic& source) :
    -
    908 basic(source.state()),
    -
    909 m_source(&source)
    -
    910 {}
    -
    911
    -
    -
    912 virtual _Success_(return != 0 || length == 0) size_t read(
    -
    913 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
    -
    914 {
    -
    915 size_t num_read = m_source->read(data, length);
    -
    916 m_state = m_source->state();
    -
    917 return num_read;
    -
    918 }
    +
    884
    +
    +
    888 class converter : public basic
    +
    889 {
    +
    890 protected:
    +
    891 explicit converter() :
    +
    892 basic(state_t::fail),
    +
    893 m_source(nullptr)
    +
    894 {}
    +
    895
    +
    896 void init(_Inout_ basic& source)
    +
    897 {
    +
    898 m_state = source.state();
    +
    899 m_source = &source;
    +
    900 }
    +
    901
    +
    902 void done()
    +
    903 {
    +
    904 m_source = nullptr;
    +
    905 }
    +
    906
    +
    907 public:
    +
    908 converter(_Inout_ basic& source) :
    +
    909 basic(source.state()),
    +
    910 m_source(&source)
    +
    911 {}
    +
    912
    +
    +
    913 virtual _Success_(return != 0 || length == 0) size_t read(
    +
    914 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
    +
    915 {
    +
    916 size_t num_read = m_source->read(data, length);
    +
    917 m_state = m_source->state();
    +
    918 return num_read;
    +
    919 }
    -
    919
    -
    -
    920 virtual _Success_(return != 0) size_t write(
    -
    921 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
    -
    922 {
    -
    923 size_t num_written = m_source->write(data, length);
    -
    924 m_state = m_source->state();
    -
    925 return num_written;
    -
    926 }
    +
    920
    +
    +
    921 virtual _Success_(return != 0) size_t write(
    +
    922 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
    +
    923 {
    +
    924 size_t num_written = m_source->write(data, length);
    +
    925 m_state = m_source->state();
    +
    926 return num_written;
    +
    927 }
    -
    927
    -
    -
    928 virtual void close()
    -
    929 {
    -
    930 m_source->close();
    -
    931 m_state = m_source->state();
    -
    932 }
    +
    928
    +
    +
    929 virtual void close()
    +
    930 {
    +
    931 m_source->close();
    +
    932 m_state = m_source->state();
    +
    933 }
    -
    933
    -
    -
    934 virtual void flush()
    -
    935 {
    -
    936 m_source->flush();
    -
    937 m_state = m_source->state();
    -
    938 }
    +
    934
    +
    +
    935 virtual void flush()
    +
    936 {
    +
    937 m_source->flush();
    +
    938 m_state = m_source->state();
    +
    939 }
    -
    939
    -
    940 protected:
    -
    941 basic* m_source;
    -
    942 };
    +
    940
    +
    941 protected:
    +
    942 basic* m_source;
    +
    943 };
    -
    943
    -
    -
    947 class replicator : public basic
    -
    948 {
    -
    949 public:
    -
    950 virtual ~replicator()
    -
    951 {
    -
    952 for (auto w = m_workers.begin(), w_end = m_workers.end(); w != w_end; ++w) {
    -
    953 auto _w = w->get();
    -
    954 {
    -
    955 const std::lock_guard<std::mutex> lk(_w->mutex);
    -
    956 _w->op = worker::op_t::quit;
    -
    957 }
    -
    958 _w->cv.notify_one();
    -
    959 }
    -
    960 for (auto w = m_workers.begin(), w_end = m_workers.end(); w != w_end; ++w)
    -
    961 w->get()->thread.join();
    -
    962 }
    -
    963
    -
    -
    967 void push_back(_In_ basic* source)
    -
    968 {
    -
    969 m_workers.push_back(std::unique_ptr<worker>(new worker(source)));
    -
    970 }
    +
    944
    +
    +
    948 class replicator : public basic
    +
    949 {
    +
    950 public:
    +
    951 virtual ~replicator()
    +
    952 {
    +
    953 for (auto w = m_workers.begin(), w_end = m_workers.end(); w != w_end; ++w) {
    +
    954 auto _w = w->get();
    +
    955 {
    +
    956 const std::lock_guard<std::mutex> lk(_w->mutex);
    +
    957 _w->op = worker::op_t::quit;
    +
    958 }
    +
    959 _w->cv.notify_one();
    +
    960 }
    +
    961 for (auto w = m_workers.begin(), w_end = m_workers.end(); w != w_end; ++w)
    +
    962 w->get()->thread.join();
    +
    963 }
    +
    964
    +
    +
    968 void push_back(_In_ basic* source)
    +
    969 {
    +
    970 m_workers.push_back(std::unique_ptr<worker>(new worker(source)));
    +
    971 }
    -
    971
    -
    -
    975 void remove(basic* source)
    -
    976 {
    -
    977 for (auto w = m_workers.begin(), w_end = m_workers.end(); w != w_end; ++w) {
    -
    978 auto _w = w->get();
    -
    979 if (_w->source == source) {
    -
    980 {
    -
    981 const std::lock_guard<std::mutex> lk(_w->mutex);
    -
    982 _w->op = worker::op_t::quit;
    -
    983 }
    -
    984 _w->cv.notify_one();
    -
    985 _w->thread.join();
    -
    986 m_workers.erase(w);
    -
    987 return;
    -
    988 }
    -
    989 }
    -
    990 }
    +
    972
    +
    +
    976 void remove(basic* source)
    +
    977 {
    +
    978 for (auto w = m_workers.begin(), w_end = m_workers.end(); w != w_end; ++w) {
    +
    979 auto _w = w->get();
    +
    980 if (_w->source == source) {
    +
    981 {
    +
    982 const std::lock_guard<std::mutex> lk(_w->mutex);
    +
    983 _w->op = worker::op_t::quit;
    +
    984 }
    +
    985 _w->cv.notify_one();
    +
    986 _w->thread.join();
    +
    987 m_workers.erase(w);
    +
    988 return;
    +
    989 }
    +
    990 }
    +
    991 }
    -
    991
    -
    -
    992 virtual _Success_(return != 0) size_t write(
    -
    993 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
    -
    994 {
    -
    995 for (auto w = m_workers.begin(), w_end = m_workers.end(); w != w_end; ++w) {
    -
    996 auto _w = w->get();
    -
    997 {
    -
    998 const std::lock_guard<std::mutex> lk(_w->mutex);
    -
    999 _w->op = worker::op_t::write;
    -
    1000 _w->data = data;
    -
    1001 _w->length = length;
    -
    1002 }
    -
    1003 _w->cv.notify_one();
    -
    1004 }
    -
    1005 size_t num_written = length;
    -
    1006 m_state = state_t::ok;
    -
    1007 for (auto w = m_workers.begin(), w_end = m_workers.end(); w != w_end; ++w) {
    -
    1008 auto _w = w->get();
    -
    1009 std::unique_lock<std::mutex> lk(_w->mutex);
    -
    1010 _w->cv.wait(lk, [&] {return _w->op == worker::op_t::noop; });
    -
    1011 if (_w->num_written < num_written)
    -
    1012 num_written = _w->num_written;
    -
    1013 if (ok() && !_w->source->ok())
    -
    1014 m_state = _w->source->state();
    -
    1015 }
    -
    1016 return num_written;
    -
    1017 }
    +
    992
    +
    +
    993 virtual _Success_(return != 0) size_t write(
    +
    994 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
    +
    995 {
    +
    996 for (auto w = m_workers.begin(), w_end = m_workers.end(); w != w_end; ++w) {
    +
    997 auto _w = w->get();
    +
    998 {
    +
    999 const std::lock_guard<std::mutex> lk(_w->mutex);
    +
    1000 _w->op = worker::op_t::write;
    +
    1001 _w->data = data;
    +
    1002 _w->length = length;
    +
    1003 }
    +
    1004 _w->cv.notify_one();
    +
    1005 }
    +
    1006 size_t num_written = length;
    +
    1007 m_state = state_t::ok;
    +
    1008 for (auto w = m_workers.begin(), w_end = m_workers.end(); w != w_end; ++w) {
    +
    1009 auto _w = w->get();
    +
    1010 std::unique_lock<std::mutex> lk(_w->mutex);
    +
    1011 _w->cv.wait(lk, [&] {return _w->op == worker::op_t::noop; });
    +
    1012 if (_w->num_written < num_written)
    +
    1013 num_written = _w->num_written;
    +
    1014 if (ok() && !_w->source->ok())
    +
    1015 m_state = _w->source->state();
    +
    1016 }
    +
    1017 return num_written;
    +
    1018 }
    -
    1018
    -
    -
    1019 virtual void close()
    -
    1020 {
    -
    1021 foreach_worker(worker::op_t::close);
    -
    1022 }
    +
    1019
    +
    +
    1020 virtual void close()
    +
    1021 {
    +
    1022 foreach_worker(worker::op_t::close);
    +
    1023 }
    -
    1023
    -
    -
    1024 virtual void flush()
    -
    1025 {
    -
    1026 foreach_worker(worker::op_t::flush);
    -
    1027 }
    +
    1024
    +
    +
    1025 virtual void flush()
    +
    1026 {
    +
    1027 foreach_worker(worker::op_t::flush);
    +
    1028 }
    -
    1028
    -
    1029 protected:
    -
    - -
    1031 {
    -
    1032 public:
    -
    1033 worker(_In_ basic* _source) :
    -
    1034 source(_source),
    -
    1035 op(op_t::noop),
    -
    1036 data(nullptr),
    -
    1037 length(0),
    -
    1038 num_written(0),
    -
    1039 thread(process_op, std::ref(*this))
    -
    1040 {}
    -
    1041
    -
    1042 protected:
    -
    1043 static void process_op(_Inout_ worker& w)
    -
    1044 {
    -
    1045 for (;;) {
    -
    1046 std::unique_lock<std::mutex> lk(w.mutex);
    -
    1047 w.cv.wait(lk, [&] {return w.op != op_t::noop; });
    -
    1048 switch (w.op) {
    -
    1049 case op_t::quit:
    -
    1050 return;
    -
    1051 case op_t::write:
    -
    1052 w.num_written = w.source->write(w.data, w.length);
    -
    1053 break;
    -
    1054 case op_t::close:
    -
    1055 w.source->close();
    -
    1056 break;
    -
    1057 case op_t::flush:
    -
    1058 w.source->flush();
    -
    1059 break;
    -
    1060 }
    -
    1061 w.op = op_t::noop;
    -
    1062 lk.unlock();
    -
    1063 w.cv.notify_one();
    -
    1064 }
    -
    1065 }
    -
    1066
    -
    1067 public:
    -
    1068 basic* source;
    -
    1069 enum class op_t {
    -
    1070 noop = 0,
    -
    1071 quit,
    -
    1072 write,
    -
    1073 close,
    -
    1074 flush,
    -
    1075 } op;
    -
    1076 const void* data;
    -
    1077 size_t length;
    - -
    1079 std::mutex mutex;
    -
    1080 std::condition_variable cv;
    -
    1081 std::thread thread;
    -
    1082 };
    +
    1029
    +
    1030 protected:
    +
    + +
    1032 {
    +
    1033 public:
    +
    1034 worker(_In_ basic* _source) :
    +
    1035 source(_source),
    +
    1036 op(op_t::noop),
    +
    1037 data(nullptr),
    +
    1038 length(0),
    +
    1039 num_written(0),
    +
    1040 thread(process_op, std::ref(*this))
    +
    1041 {}
    +
    1042
    +
    1043 protected:
    +
    1044 static void process_op(_Inout_ worker& w)
    +
    1045 {
    +
    1046 for (;;) {
    +
    1047 std::unique_lock<std::mutex> lk(w.mutex);
    +
    1048 w.cv.wait(lk, [&] {return w.op != op_t::noop; });
    +
    1049 switch (w.op) {
    +
    1050 case op_t::quit:
    +
    1051 return;
    +
    1052 case op_t::write:
    +
    1053 w.num_written = w.source->write(w.data, w.length);
    +
    1054 break;
    +
    1055 case op_t::close:
    +
    1056 w.source->close();
    +
    1057 break;
    +
    1058 case op_t::flush:
    +
    1059 w.source->flush();
    +
    1060 break;
    +
    1061 case op_t::noop:;
    +
    1062 }
    +
    1063 w.op = op_t::noop;
    +
    1064 lk.unlock();
    +
    1065 w.cv.notify_one();
    +
    1066 }
    +
    1067 }
    +
    1068
    +
    1069 public:
    +
    1070 basic* source;
    +
    1071 enum class op_t {
    +
    1072 noop = 0,
    +
    1073 quit,
    +
    1074 write,
    +
    1075 close,
    +
    1076 flush,
    +
    1077 } op;
    +
    1078 const void* data;
    +
    1079 size_t length;
    + +
    1081 std::mutex mutex;
    +
    1082 std::condition_variable cv;
    +
    1083 std::thread thread;
    +
    1084 };
    -
    1083
    -
    1084 void foreach_worker(_In_ worker::op_t op)
    -
    1085 {
    -
    1086 for (auto w = m_workers.begin(), w_end = m_workers.end(); w != w_end; ++w) {
    -
    1087 auto _w = w->get();
    -
    1088 {
    -
    1089 const std::lock_guard<std::mutex> lk(_w->mutex);
    -
    1090 _w->op = op;
    -
    1091 }
    -
    1092 _w->cv.notify_one();
    -
    1093 }
    -
    1094 m_state = state_t::ok;
    -
    1095 for (auto w = m_workers.begin(), w_end = m_workers.end(); w != w_end; ++w) {
    -
    1096 auto _w = w->get();
    -
    1097 std::unique_lock<std::mutex> lk(_w->mutex);
    -
    1098 _w->cv.wait(lk, [&] {return _w->op == worker::op_t::noop; });
    -
    1099 if (ok())
    -
    1100 m_state = _w->source->state();
    -
    1101 }
    -
    1102 }
    -
    1103
    -
    1104 std::list<std::unique_ptr<worker>> m_workers;
    -
    1105 };
    +
    1085
    +
    1086 void foreach_worker(_In_ worker::op_t op)
    +
    1087 {
    +
    1088 for (auto w = m_workers.begin(), w_end = m_workers.end(); w != w_end; ++w) {
    +
    1089 auto _w = w->get();
    +
    1090 {
    +
    1091 const std::lock_guard<std::mutex> lk(_w->mutex);
    +
    1092 _w->op = op;
    +
    1093 }
    +
    1094 _w->cv.notify_one();
    +
    1095 }
    +
    1096 m_state = state_t::ok;
    +
    1097 for (auto w = m_workers.begin(), w_end = m_workers.end(); w != w_end; ++w) {
    +
    1098 auto _w = w->get();
    +
    1099 std::unique_lock<std::mutex> lk(_w->mutex);
    +
    1100 _w->cv.wait(lk, [&] {return _w->op == worker::op_t::noop; });
    +
    1101 if (ok())
    +
    1102 m_state = _w->source->state();
    +
    1103 }
    +
    1104 }
    +
    1105
    +
    1106 std::list<std::unique_ptr<worker>> m_workers;
    +
    1107 };
    -
    1106
    -
    1107 constexpr size_t default_async_limit = 0x100000;
    1108
    -
    1114 template <size_t CAPACITY = default_async_limit>
    -
    - -
    1116 {
    -
    1117 public:
    -
    1118 async_reader(_Inout_ basic& source) :
    -
    1119 converter(source),
    -
    1120 m_worker(process, std::ref(*this))
    -
    1121 {}
    -
    1122
    -
    1123 virtual ~async_reader()
    -
    1124 {
    -
    1125 m_ring.quit();
    -
    1126 m_worker.join();
    -
    1127 }
    -
    1128
    -
    1129#pragma warning(suppress: 6101) // See [1] below
    -
    -
    1130 virtual _Success_(return != 0 || length == 0) size_t read(
    -
    1131 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
    -
    1132 {
    -
    1133 assert(data || !length);
    -
    1134 for (size_t to_read = length;;) {
    -
    1135 uint8_t* ptr; size_t num_read;
    -
    1136 std::tie(ptr, num_read) = m_ring.front();
    -
    1137 if (!ptr) _Unlikely_ {
    -
    1138 // [1] Code analysis misses length - to_read bytes were written to data in previous loop iterations.
    -
    1139 m_state = to_read < length || !length ? state_t::ok : m_source->state();
    -
    1140 return length - to_read;
    -
    1141 }
    -
    1142 if (to_read < num_read)
    -
    1143 num_read = to_read;
    -
    1144 memcpy(data, ptr, num_read);
    -
    1145 m_ring.pop(num_read);
    -
    1146 to_read -= num_read;
    -
    1147 if (!to_read) {
    -
    1148 m_state = state_t::ok;
    -
    1149 return length;
    -
    1150 }
    -
    1151 reinterpret_cast<uint8_t*&>(data) += num_read;
    -
    1152 }
    -
    1153 }
    +
    1109 constexpr size_t default_async_limit = 0x100000;
    +
    1110
    +
    1116 template <size_t CAPACITY = default_async_limit>
    +
    + +
    1118 {
    +
    1119 public:
    +
    1120 async_reader(_Inout_ basic& source) :
    +
    1121 converter(source),
    +
    1122 m_worker(process, std::ref(*this))
    +
    1123 {}
    +
    1124
    +
    1125 virtual ~async_reader()
    +
    1126 {
    +
    1127 m_ring.quit();
    +
    1128 m_worker.join();
    +
    1129 }
    +
    1130
    +
    1131#pragma warning(suppress: 6101) // See [1] below
    +
    +
    1132 virtual _Success_(return != 0 || length == 0) size_t read(
    +
    1133 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
    +
    1134 {
    +
    1135 assert(data || !length);
    +
    1136 for (size_t to_read = length;;) {
    +
    1137 uint8_t* ptr; size_t num_read;
    +
    1138 std::tie(ptr, num_read) = m_ring.front();
    +
    1139 if (!ptr) _Unlikely_ {
    +
    1140 // [1] Code analysis misses length - to_read bytes were written to data in previous loop iterations.
    +
    1141 m_state = to_read < length || !length ? state_t::ok : m_source->state();
    +
    1142 return length - to_read;
    +
    1143 }
    +
    1144 if (to_read < num_read)
    +
    1145 num_read = to_read;
    +
    1146 memcpy(data, ptr, num_read);
    +
    1147 m_ring.pop(num_read);
    +
    1148 to_read -= num_read;
    +
    1149 if (!to_read) {
    +
    1150 m_state = state_t::ok;
    +
    1151 return length;
    +
    1152 }
    +
    1153 reinterpret_cast<uint8_t*&>(data) += num_read;
    +
    1154 }
    +
    1155 }
    -
    1154
    -
    1155 protected:
    -
    1156 static void process(_Inout_ async_reader& w)
    -
    1157 {
    -
    1158 for (;;) {
    -
    1159 uint8_t* ptr; size_t num_write;
    -
    1160 std::tie(ptr, num_write) = w.m_ring.back();
    -
    1161 if (!ptr) _Unlikely_
    -
    1162 break;
    -
    1163 num_write = w.m_source->read(ptr, num_write);
    -
    1164 w.m_ring.push(num_write);
    -
    1165 if (!w.m_source->ok()) {
    -
    1166 w.m_ring.quit();
    -
    1167 break;
    -
    1168 }
    -
    1169 }
    -
    1170 }
    -
    1171
    -
    1172 protected:
    -
    1173 ring<uint8_t, CAPACITY> m_ring;
    -
    1174 std::thread m_worker;
    -
    1175 };
    +
    1156
    +
    1157 protected:
    +
    1158 static void process(_Inout_ async_reader& w)
    +
    1159 {
    +
    1160 for (;;) {
    +
    1161 uint8_t* ptr; size_t num_write;
    +
    1162 std::tie(ptr, num_write) = w.m_ring.back();
    +
    1163 if (!ptr) _Unlikely_
    +
    1164 break;
    +
    1165 num_write = w.m_source->read(ptr, num_write);
    +
    1166 w.m_ring.push(num_write);
    +
    1167 if (!w.m_source->ok()) {
    +
    1168 w.m_ring.quit();
    +
    1169 break;
    +
    1170 }
    +
    1171 }
    +
    1172 }
    +
    1173
    +
    1174 protected:
    +
    1175 ring<uint8_t, CAPACITY> m_ring;
    +
    1176 std::thread m_worker;
    +
    1177 };
    -
    1176
    -
    1182 template <size_t CAPACITY = default_async_limit>
    -
    - -
    1184 {
    -
    1185 public:
    -
    1186 async_writer(_Inout_ basic& source) :
    -
    1187 converter(source),
    -
    1188 m_worker(process, std::ref(*this))
    -
    1189 {}
    -
    1190
    -
    1191 virtual ~async_writer()
    -
    1192 {
    -
    1193 m_ring.quit();
    -
    1194 m_worker.join();
    -
    1195 }
    -
    1196
    -
    -
    1197 virtual _Success_(return != 0) size_t write(
    -
    1198 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
    -
    1199 {
    -
    1200 assert(data || !length);
    -
    1201 for (size_t to_write = length;;) {
    -
    1202 uint8_t* ptr; size_t num_write;
    -
    1203 std::tie(ptr, num_write) = m_ring.back();
    -
    1204 if (!ptr) _Unlikely_ {
    -
    1205 m_state = state_t::fail;
    -
    1206 return length - to_write;
    -
    1207 }
    -
    1208 if (to_write < num_write)
    -
    1209 num_write = to_write;
    -
    1210 memcpy(ptr, data, num_write);
    -
    1211 m_ring.push(num_write);
    -
    1212 to_write -= num_write;
    -
    1213 if (!to_write) {
    -
    1214 m_state = state_t::ok;
    -
    1215 return length;
    -
    1216 }
    -
    1217 reinterpret_cast<const uint8_t*&>(data) += num_write;
    -
    1218 }
    -
    1219 }
    +
    1178
    +
    1184 template <size_t CAPACITY = default_async_limit>
    +
    + +
    1186 {
    +
    1187 public:
    +
    1188 async_writer(_Inout_ basic& source) :
    +
    1189 converter(source),
    +
    1190 m_worker(process, std::ref(*this))
    +
    1191 {}
    +
    1192
    +
    1193 virtual ~async_writer()
    +
    1194 {
    +
    1195 m_ring.quit();
    +
    1196 m_worker.join();
    +
    1197 }
    +
    1198
    +
    +
    1199 virtual _Success_(return != 0) size_t write(
    +
    1200 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
    +
    1201 {
    +
    1202 assert(data || !length);
    +
    1203 for (size_t to_write = length;;) {
    +
    1204 uint8_t* ptr; size_t num_write;
    +
    1205 std::tie(ptr, num_write) = m_ring.back();
    +
    1206 if (!ptr) _Unlikely_ {
    +
    1207 m_state = state_t::fail;
    +
    1208 return length - to_write;
    +
    1209 }
    +
    1210 if (to_write < num_write)
    +
    1211 num_write = to_write;
    +
    1212 memcpy(ptr, data, num_write);
    +
    1213 m_ring.push(num_write);
    +
    1214 to_write -= num_write;
    +
    1215 if (!to_write) {
    +
    1216 m_state = state_t::ok;
    +
    1217 return length;
    +
    1218 }
    +
    1219 reinterpret_cast<const uint8_t*&>(data) += num_write;
    +
    1220 }
    +
    1221 }
    -
    1220
    -
    -
    1221 virtual void flush()
    -
    1222 {
    -
    1223 m_ring.sync();
    - -
    1225 }
    +
    1222
    +
    +
    1223 virtual void flush()
    +
    1224 {
    +
    1225 m_ring.sync();
    + +
    1227 }
    -
    1226
    -
    1227 protected:
    -
    1228 static void process(_Inout_ async_writer& w)
    -
    1229 {
    -
    1230 for (;;) {
    -
    1231 uint8_t* ptr; size_t num_read;
    -
    1232 std::tie(ptr, num_read) = w.m_ring.front();
    -
    1233 if (!ptr)
    -
    1234 break;
    -
    1235 num_read = w.m_source->write(ptr, num_read);
    -
    1236 w.m_ring.pop(num_read);
    -
    1237 if (!w.m_source->ok()) {
    -
    1238 w.m_ring.quit();
    -
    1239 break;
    -
    1240 }
    -
    1241 }
    -
    1242 }
    -
    1243
    -
    1244 protected:
    -
    1245 ring<uint8_t, CAPACITY> m_ring;
    -
    1246 std::thread m_worker;
    -
    1247 };
    +
    1228
    +
    1229 protected:
    +
    1230 static void process(_Inout_ async_writer& w)
    +
    1231 {
    +
    1232 for (;;) {
    +
    1233 uint8_t* ptr; size_t num_read;
    +
    1234 std::tie(ptr, num_read) = w.m_ring.front();
    +
    1235 if (!ptr)
    +
    1236 break;
    +
    1237 num_read = w.m_source->write(ptr, num_read);
    +
    1238 w.m_ring.pop(num_read);
    +
    1239 if (!w.m_source->ok()) {
    +
    1240 w.m_ring.quit();
    +
    1241 break;
    +
    1242 }
    +
    1243 }
    +
    1244 }
    +
    1245
    +
    1246 protected:
    +
    1247 ring<uint8_t, CAPACITY> m_ring;
    +
    1248 std::thread m_worker;
    +
    1249 };
    -
    1248
    -
    1249 constexpr size_t default_buffer_size = 0x400;
    1250
    -
    -
    1254 class buffer : public converter
    -
    1255 {
    -
    1256 protected:
    -
    1257 explicit buffer(_In_ size_t read_buffer_size = default_buffer_size, _In_ size_t write_buffer_size = default_buffer_size) :
    -
    1258 converter(),
    -
    1259 m_read_buffer(read_buffer_size),
    -
    1260 m_write_buffer(write_buffer_size)
    -
    1261 {}
    -
    1262
    -
    1263 void done()
    -
    1264 {
    -
    1265 if (m_source)
    -
    1266 flush_write();
    -
    1267 converter::done();
    -
    1268 }
    -
    1269
    -
    1270 public:
    -
    1271 buffer(_Inout_ basic& source, _In_ size_t read_buffer_size = default_buffer_size, _In_ size_t write_buffer_size = default_buffer_size) :
    -
    1272 converter(source),
    -
    1273 m_read_buffer(read_buffer_size),
    -
    1274 m_write_buffer(write_buffer_size)
    -
    1275 {}
    -
    1276
    -
    1277 virtual ~buffer()
    -
    1278 {
    -
    1279 if (m_source)
    -
    1280 flush_write();
    -
    1281 }
    -
    1282
    -
    -
    1283 virtual _Success_(return != 0 || length == 0) size_t read(
    -
    1284 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
    -
    1285 {
    -
    1286 assert(data || !length);
    -
    1287 for (size_t to_read = length;;) {
    -
    1288 size_t buffer_size = m_read_buffer.tail - m_read_buffer.head;
    -
    1289 if (to_read <= buffer_size) {
    -
    1290 memcpy(data, m_read_buffer.data + m_read_buffer.head, to_read);
    -
    1291 m_read_buffer.head += to_read;
    -
    1292 m_state = state_t::ok;
    -
    1293 return length;
    -
    1294 }
    -
    1295 if (buffer_size) {
    -
    1296 memcpy(data, m_read_buffer.data + m_read_buffer.head, buffer_size);
    -
    1297 reinterpret_cast<uint8_t*&>(data) += buffer_size;
    -
    1298 to_read -= buffer_size;
    -
    1299 }
    -
    1300 m_read_buffer.head = 0;
    -
    1301 if (to_read > m_read_buffer.capacity) {
    -
    1302 // When needing to read more data than buffer capacity, bypass the buffer.
    -
    1303 m_read_buffer.tail = 0;
    -
    1304 to_read -= m_source->read(data, to_read);
    -
    1305 m_state = to_read < length ? state_t::ok : m_source->state();
    -
    1306 return length - to_read;
    -
    1307 }
    -
    1308 m_read_buffer.tail = m_source->read(m_read_buffer.data, m_read_buffer.capacity);
    -
    1309 if (m_read_buffer.tail < m_read_buffer.capacity && m_read_buffer.tail < to_read) _Unlikely_ {
    -
    1310 memcpy(data, m_read_buffer.data, m_read_buffer.tail);
    -
    1311 m_read_buffer.head = m_read_buffer.tail;
    -
    1312 to_read -= m_read_buffer.tail;
    -
    1313 m_state = to_read < length ? state_t::ok : m_source->state();
    -
    1314 return length - to_read;
    -
    1315 }
    -
    1316 }
    -
    1317 }
    +
    1251 constexpr size_t default_buffer_size = 0x400;
    +
    1252
    +
    +
    1256 class buffer : public converter
    +
    1257 {
    +
    1258 protected:
    +
    1259 explicit buffer(_In_ size_t read_buffer_size = default_buffer_size, _In_ size_t write_buffer_size = default_buffer_size) :
    +
    1260 converter(),
    +
    1261 m_read_buffer(read_buffer_size),
    +
    1262 m_write_buffer(write_buffer_size)
    +
    1263 {}
    +
    1264
    +
    1265 void done()
    +
    1266 {
    +
    1267 if (m_source)
    +
    1268 flush_write();
    +
    1269 converter::done();
    +
    1270 }
    +
    1271
    +
    1272 public:
    +
    1273 buffer(_Inout_ basic& source, _In_ size_t read_buffer_size = default_buffer_size, _In_ size_t write_buffer_size = default_buffer_size) :
    +
    1274 converter(source),
    +
    1275 m_read_buffer(read_buffer_size),
    +
    1276 m_write_buffer(write_buffer_size)
    +
    1277 {}
    +
    1278
    +
    1279 virtual ~buffer()
    +
    1280 {
    +
    1281 if (m_source)
    +
    1282 flush_write();
    +
    1283 }
    +
    1284
    +
    +
    1285 virtual _Success_(return != 0 || length == 0) size_t read(
    +
    1286 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
    +
    1287 {
    +
    1288 assert(data || !length);
    +
    1289 for (size_t to_read = length;;) {
    +
    1290 size_t buffer_size = m_read_buffer.tail - m_read_buffer.head;
    +
    1291 if (to_read <= buffer_size) {
    +
    1292 memcpy(data, m_read_buffer.data + m_read_buffer.head, to_read);
    +
    1293 m_read_buffer.head += to_read;
    +
    1294 m_state = state_t::ok;
    +
    1295 return length;
    +
    1296 }
    +
    1297 if (buffer_size) {
    +
    1298 memcpy(data, m_read_buffer.data + m_read_buffer.head, buffer_size);
    +
    1299 reinterpret_cast<uint8_t*&>(data) += buffer_size;
    +
    1300 to_read -= buffer_size;
    +
    1301 }
    +
    1302 m_read_buffer.head = 0;
    +
    1303 if (to_read > m_read_buffer.capacity) {
    +
    1304 // When needing to read more data than buffer capacity, bypass the buffer.
    +
    1305 m_read_buffer.tail = 0;
    +
    1306 to_read -= m_source->read(data, to_read);
    +
    1307 m_state = to_read < length ? state_t::ok : m_source->state();
    +
    1308 return length - to_read;
    +
    1309 }
    +
    1310 m_read_buffer.tail = m_source->read(m_read_buffer.data, m_read_buffer.capacity);
    +
    1311 if (m_read_buffer.tail < m_read_buffer.capacity && m_read_buffer.tail < to_read) _Unlikely_ {
    +
    1312 memcpy(data, m_read_buffer.data, m_read_buffer.tail);
    +
    1313 m_read_buffer.head = m_read_buffer.tail;
    +
    1314 to_read -= m_read_buffer.tail;
    +
    1315 m_state = to_read < length ? state_t::ok : m_source->state();
    +
    1316 return length - to_read;
    +
    1317 }
    +
    1318 }
    +
    1319 }
    -
    1318
    -
    -
    1319 virtual _Success_(return != 0) size_t write(
    -
    1320 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
    -
    1321 {
    -
    1322 assert(data || !length);
    -
    1323 if (!length) _Unlikely_ {
    -
    1324 // Pass null writes (zero-byte length). Null write operations have special meaning with with Windows pipes.
    -
    1325 flush_write();
    -
    1326 if (!ok()) _Unlikely_
    -
    1327 return 0;
    -
    1328 m_source->write(nullptr, 0);
    -
    1329 m_state = m_source->state();
    -
    1330 return 0;
    -
    1331 }
    -
    1332
    -
    1333 for (size_t to_write = length;;) {
    -
    1334 size_t available_buffer = m_write_buffer.capacity - m_write_buffer.tail;
    -
    1335 if (to_write <= available_buffer) {
    -
    1336 memcpy(m_write_buffer.data + m_write_buffer.tail, data, to_write);
    -
    1337 m_write_buffer.tail += to_write;
    -
    1338 m_state = state_t::ok;
    -
    1339 return length;
    -
    1340 }
    -
    1341 if (available_buffer) {
    -
    1342 memcpy(m_write_buffer.data + m_write_buffer.tail, data, available_buffer);
    -
    1343 reinterpret_cast<const uint8_t*&>(data) += available_buffer;
    -
    1344 to_write -= available_buffer;
    -
    1345 m_write_buffer.tail += available_buffer;
    -
    1346 }
    -
    1347 size_t buffer_size = m_write_buffer.tail - m_write_buffer.head;
    -
    1348 if (buffer_size) {
    -
    1349 m_write_buffer.head += m_source->write(m_write_buffer.data + m_write_buffer.head, buffer_size);
    -
    1350 m_state = m_source->state();
    -
    1351 if (m_write_buffer.head == m_write_buffer.tail)
    -
    1352 m_write_buffer.head = m_write_buffer.tail = 0;
    -
    1353 else
    -
    1354 return length - to_write;
    -
    1355 }
    -
    1356 if (to_write > m_write_buffer.capacity) {
    -
    1357 // When needing to write more data than buffer capacity, bypass the buffer.
    -
    1358 to_write -= m_source->write(data, to_write);
    -
    1359 m_state = m_source->state();
    -
    1360 return length - to_write;
    -
    1361 }
    -
    1362 }
    -
    1363 }
    +
    1320
    +
    +
    1321 virtual _Success_(return != 0) size_t write(
    +
    1322 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
    +
    1323 {
    +
    1324 assert(data || !length);
    +
    1325 if (!length) _Unlikely_ {
    +
    1326 // Pass null writes (zero-byte length). Null write operations have special meaning with with Windows pipes.
    +
    1327 flush_write();
    +
    1328 if (!ok()) _Unlikely_
    +
    1329 return 0;
    +
    1330 m_source->write(nullptr, 0);
    +
    1331 m_state = m_source->state();
    +
    1332 return 0;
    +
    1333 }
    +
    1334
    +
    1335 for (size_t to_write = length;;) {
    +
    1336 size_t available_buffer = m_write_buffer.capacity - m_write_buffer.tail;
    +
    1337 if (to_write <= available_buffer) {
    +
    1338 memcpy(m_write_buffer.data + m_write_buffer.tail, data, to_write);
    +
    1339 m_write_buffer.tail += to_write;
    +
    1340 m_state = state_t::ok;
    +
    1341 return length;
    +
    1342 }
    +
    1343 if (available_buffer) {
    +
    1344 memcpy(m_write_buffer.data + m_write_buffer.tail, data, available_buffer);
    +
    1345 reinterpret_cast<const uint8_t*&>(data) += available_buffer;
    +
    1346 to_write -= available_buffer;
    +
    1347 m_write_buffer.tail += available_buffer;
    +
    1348 }
    +
    1349 size_t buffer_size = m_write_buffer.tail - m_write_buffer.head;
    +
    1350 if (buffer_size) {
    +
    1351 m_write_buffer.head += m_source->write(m_write_buffer.data + m_write_buffer.head, buffer_size);
    +
    1352 m_state = m_source->state();
    +
    1353 if (m_write_buffer.head == m_write_buffer.tail)
    +
    1354 m_write_buffer.head = m_write_buffer.tail = 0;
    +
    1355 else
    +
    1356 return length - to_write;
    +
    1357 }
    +
    1358 if (to_write > m_write_buffer.capacity) {
    +
    1359 // When needing to write more data than buffer capacity, bypass the buffer.
    +
    1360 to_write -= m_source->write(data, to_write);
    +
    1361 m_state = m_source->state();
    +
    1362 return length - to_write;
    +
    1363 }
    +
    1364 }
    +
    1365 }
    -
    1364
    -
    -
    1365 virtual void flush()
    -
    1366 {
    -
    1367 flush_write();
    -
    1368 if (ok())
    - -
    1370 }
    +
    1366
    +
    +
    1367 virtual void flush()
    +
    1368 {
    +
    1369 flush_write();
    +
    1370 if (ok())
    + +
    1372 }
    -
    1371
    -
    1372 protected:
    -
    1373 void flush_write()
    -
    1374 {
    -
    1375 size_t buffer_size = m_write_buffer.tail - m_write_buffer.head;
    -
    1376 if (buffer_size) {
    -
    1377 m_write_buffer.head += m_source->write(m_write_buffer.data + m_write_buffer.head, buffer_size);
    -
    1378 if (m_write_buffer.head == m_write_buffer.tail) {
    -
    1379 m_write_buffer.head = 0;
    -
    1380 m_write_buffer.tail = 0;
    -
    1381 }
    -
    1382 else {
    -
    1383 m_state = m_source->state();
    -
    1384 return;
    -
    1385 }
    -
    1386 }
    -
    1387 m_state = state_t::ok;
    -
    1388 }
    -
    1389
    -
    -
    1390 struct buffer_t {
    -
    1391 uint8_t* data;
    -
    1392 size_t head, tail, capacity;
    -
    1393
    -
    1394 buffer_t(_In_ size_t buffer_size) :
    -
    1395 head(0),
    -
    1396 tail(0),
    -
    1397 capacity(buffer_size),
    -
    1398 data(buffer_size ? new uint8_t[buffer_size] : nullptr)
    -
    1399 {}
    -
    1400
    -
    1401 ~buffer_t()
    -
    1402 {
    -
    1403 if (data)
    -
    1404 delete[] data;
    -
    1405 }
    -
    1406 } m_read_buffer, m_write_buffer;
    +
    1373
    +
    1374 protected:
    +
    1375 void flush_write()
    +
    1376 {
    +
    1377 size_t buffer_size = m_write_buffer.tail - m_write_buffer.head;
    +
    1378 if (buffer_size) {
    +
    1379 m_write_buffer.head += m_source->write(m_write_buffer.data + m_write_buffer.head, buffer_size);
    +
    1380 if (m_write_buffer.head == m_write_buffer.tail) {
    +
    1381 m_write_buffer.head = 0;
    +
    1382 m_write_buffer.tail = 0;
    +
    1383 }
    +
    1384 else {
    +
    1385 m_state = m_source->state();
    +
    1386 return;
    +
    1387 }
    +
    1388 }
    +
    1389 m_state = state_t::ok;
    +
    1390 }
    +
    1391
    +
    +
    1392 struct buffer_t {
    +
    1393 uint8_t* data;
    +
    1394 size_t head, tail, capacity;
    +
    1395
    +
    1396 buffer_t(_In_ size_t buffer_size) :
    +
    1397 head(0),
    +
    1398 tail(0),
    +
    1399 capacity(buffer_size),
    +
    1400 data(buffer_size ? new uint8_t[buffer_size] : nullptr)
    +
    1401 {}
    +
    1402
    +
    1403 ~buffer_t()
    +
    1404 {
    +
    1405 if (data)
    +
    1406 delete[] data;
    +
    1407 }
    +
    1408 } m_read_buffer, m_write_buffer;
    -
    1407 };
    +
    1409 };
    -
    1408
    -
    -
    1412 class limiter : public converter
    -
    1413 {
    -
    1414 public:
    -
    1415 limiter(_Inout_ basic& source, _In_ fsize_t _read_limit = 0, _In_ fsize_t _write_limit = 0) :
    -
    1416 converter(source),
    -
    1417 read_limit(_read_limit),
    -
    1418 write_limit(_write_limit)
    -
    1419 {}
    -
    1420
    -
    -
    1421 virtual _Success_(return != 0 || length == 0) size_t read(
    -
    1422 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
    -
    1423 {
    -
    1424 size_t num_read;
    -
    1425 if (read_limit == fsize_max) {
    -
    1426 num_read = m_source->read(data, length);
    -
    1427 m_state = m_source->state();
    -
    1428 }
    -
    1429 else if (length <= read_limit) {
    -
    1430 num_read = m_source->read(data, length);
    -
    1431 m_state = m_source->state();
    -
    1432 read_limit -= num_read;
    -
    1433 }
    -
    1434 else if (length && !read_limit) {
    -
    1435 num_read = 0;
    -
    1436 m_state = state_t::eof;
    -
    1437 }
    -
    1438 else {
    -
    1439 num_read = m_source->read(data, static_cast<size_t>(read_limit));
    -
    1440 m_state = m_source->state();
    -
    1441 read_limit -= num_read;
    -
    1442 }
    -
    1443 return num_read;
    -
    1444 }
    +
    1410
    +
    +
    1414 class limiter : public converter
    +
    1415 {
    +
    1416 public:
    +
    1417 limiter(_Inout_ basic& source, _In_ fsize_t _read_limit = 0, _In_ fsize_t _write_limit = 0) :
    +
    1418 converter(source),
    +
    1419 read_limit(_read_limit),
    +
    1420 write_limit(_write_limit)
    +
    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 size_t num_read;
    +
    1427 if (read_limit == fsize_max) {
    +
    1428 num_read = m_source->read(data, length);
    +
    1429 m_state = m_source->state();
    +
    1430 }
    +
    1431 else if (length <= read_limit) {
    +
    1432 num_read = m_source->read(data, length);
    +
    1433 m_state = m_source->state();
    +
    1434 read_limit -= num_read;
    +
    1435 }
    +
    1436 else if (length && !read_limit) {
    +
    1437 num_read = 0;
    +
    1438 m_state = state_t::eof;
    +
    1439 }
    +
    1440 else {
    +
    1441 num_read = m_source->read(data, static_cast<size_t>(read_limit));
    +
    1442 m_state = m_source->state();
    +
    1443 read_limit -= num_read;
    +
    1444 }
    +
    1445 return num_read;
    +
    1446 }
    -
    1445
    -
    -
    1446 virtual _Success_(return != 0) size_t write(
    -
    1447 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
    -
    1448 {
    -
    1449 size_t num_written;
    -
    1450 if (write_limit == fsize_max) {
    -
    1451 num_written = m_source->write(data, length);
    -
    1452 m_state = m_source->state();
    -
    1453 }
    -
    1454 else if (length <= write_limit) {
    -
    1455 num_written = m_source->write(data, length);
    -
    1456 m_state = m_source->state();
    -
    1457 write_limit -= num_written;
    -
    1458 }
    -
    1459 else if (length && !write_limit) {
    -
    1460 num_written = 0;
    -
    1461 m_state = state_t::fail;
    -
    1462 }
    -
    1463 else {
    -
    1464 num_written = m_source->write(data, static_cast<size_t>(write_limit));
    -
    1465 m_state = m_source->state();
    -
    1466 write_limit -= num_written;
    -
    1467 }
    -
    1468 return num_written;
    -
    1469 }
    +
    1447
    +
    +
    1448 virtual _Success_(return != 0) size_t write(
    +
    1449 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
    +
    1450 {
    +
    1451 size_t num_written;
    +
    1452 if (write_limit == fsize_max) {
    +
    1453 num_written = m_source->write(data, length);
    +
    1454 m_state = m_source->state();
    +
    1455 }
    +
    1456 else if (length <= write_limit) {
    +
    1457 num_written = m_source->write(data, length);
    +
    1458 m_state = m_source->state();
    +
    1459 write_limit -= num_written;
    +
    1460 }
    +
    1461 else if (length && !write_limit) {
    +
    1462 num_written = 0;
    +
    1463 m_state = state_t::fail;
    +
    1464 }
    +
    1465 else {
    +
    1466 num_written = m_source->write(data, static_cast<size_t>(write_limit));
    +
    1467 m_state = m_source->state();
    +
    1468 write_limit -= num_written;
    +
    1469 }
    +
    1470 return num_written;
    +
    1471 }
    -
    1470
    -
    1471 public:
    -
    1472 fsize_t
    - - -
    1475 };
    +
    1472
    +
    1473 public:
    +
    1474 fsize_t
    + + +
    1477 };
    -
    1476
    -
    -
    1480 class window : public limiter
    -
    1481 {
    -
    1482 public:
    -
    1483 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) :
    -
    1484 limiter(source, read_limit, write_limit),
    -
    1485 read_offset(_read_offset),
    -
    1486 write_offset(_write_offset)
    -
    1487 {}
    -
    1488
    -
    -
    1489 virtual _Success_(return != 0 || length == 0) size_t read(
    -
    1490 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
    -
    1491 {
    -
    1492 if (read_offset) {
    -
    1493 m_source->skip(read_offset);
    -
    1494 m_state = m_source->state();
    -
    1495 if (!ok()) _Unlikely_
    -
    1496 return 0;
    -
    1497 read_offset = 0;
    -
    1498 }
    -
    1499 size_t num_read;
    -
    1500 if (read_limit == fsize_max) {
    -
    1501 num_read = m_source->read(data, length);
    -
    1502 m_state = m_source->state();
    -
    1503 }
    -
    1504 else if (length <= read_limit) {
    -
    1505 num_read = m_source->read(data, length);
    -
    1506 m_state = m_source->state();
    -
    1507 read_limit -= num_read;
    -
    1508 }
    -
    1509 else if (length && !read_limit) {
    -
    1510 num_read = 0;
    -
    1511 m_source->skip(length);
    -
    1512 m_state = state_t::eof;
    -
    1513 }
    -
    1514 else {
    -
    1515 num_read = m_source->read(data, static_cast<size_t>(read_limit));
    -
    1516 m_state = m_source->state();
    -
    1517 read_limit -= num_read;
    -
    1518 }
    -
    1519 return num_read;
    -
    1520 }
    +
    1478
    +
    +
    1482 class window : public limiter
    +
    1483 {
    +
    1484 public:
    +
    1485 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) :
    +
    1486 limiter(source, read_limit, write_limit),
    +
    1487 read_offset(_read_offset),
    +
    1488 write_offset(_write_offset)
    +
    1489 {}
    +
    1490
    +
    +
    1491 virtual _Success_(return != 0 || length == 0) size_t read(
    +
    1492 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
    +
    1493 {
    +
    1494 if (read_offset) {
    +
    1495 m_source->skip(read_offset);
    +
    1496 m_state = m_source->state();
    +
    1497 if (!ok()) _Unlikely_
    +
    1498 return 0;
    +
    1499 read_offset = 0;
    +
    1500 }
    +
    1501 size_t num_read;
    +
    1502 if (read_limit == fsize_max) {
    +
    1503 num_read = m_source->read(data, length);
    +
    1504 m_state = m_source->state();
    +
    1505 }
    +
    1506 else if (length <= read_limit) {
    +
    1507 num_read = m_source->read(data, length);
    +
    1508 m_state = m_source->state();
    +
    1509 read_limit -= num_read;
    +
    1510 }
    +
    1511 else if (length && !read_limit) {
    +
    1512 num_read = 0;
    +
    1513 m_source->skip(length);
    +
    1514 m_state = state_t::eof;
    +
    1515 }
    +
    1516 else {
    +
    1517 num_read = m_source->read(data, static_cast<size_t>(read_limit));
    +
    1518 m_state = m_source->state();
    +
    1519 read_limit -= num_read;
    +
    1520 }
    +
    1521 return num_read;
    +
    1522 }
    -
    1521
    -
    -
    1522 virtual _Success_(return != 0) size_t write(
    -
    1523 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
    -
    1524 {
    -
    1525 size_t num_skipped, num_written;
    -
    1526 if (length <= write_offset) {
    -
    1527 write_offset -= length;
    -
    1528 m_state = state_t::ok;
    -
    1529 return length;
    -
    1530 }
    -
    1531 if (write_offset) {
    -
    1532 reinterpret_cast<const uint8_t*&>(data) += static_cast<size_t>(write_offset);
    -
    1533 length -= static_cast<size_t>(write_offset);
    -
    1534 num_skipped = static_cast<size_t>(write_offset);
    -
    1535 write_offset = 0;
    -
    1536 }
    -
    1537 else
    -
    1538 num_skipped = 0;
    -
    1539 if (write_limit == fsize_max) {
    -
    1540 num_written = m_source->write(data, length);
    -
    1541 m_state = m_source->state();
    -
    1542 }
    -
    1543 else if (length <= write_limit) {
    -
    1544 num_written = m_source->write(data, length);
    -
    1545 m_state = m_source->state();
    -
    1546 write_limit -= num_written;
    -
    1547 }
    -
    1548 else if (length && !write_limit) {
    -
    1549 num_skipped += length;
    -
    1550 num_written = 0;
    -
    1551 m_state = state_t::ok;
    -
    1552 }
    -
    1553 else {
    -
    1554 num_skipped += length - static_cast<size_t>(write_limit);
    -
    1555 num_written = m_source->write(data, static_cast<size_t>(write_limit));
    -
    1556 m_state = m_source->state();
    -
    1557 write_limit -= num_written;
    -
    1558 }
    -
    1559 return num_skipped + num_written;
    -
    1560 }
    +
    1523
    +
    +
    1524 virtual _Success_(return != 0) size_t write(
    +
    1525 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
    +
    1526 {
    +
    1527 size_t num_skipped, num_written;
    +
    1528 if (length <= write_offset) {
    +
    1529 write_offset -= length;
    +
    1530 m_state = state_t::ok;
    +
    1531 return length;
    +
    1532 }
    +
    1533 if (write_offset) {
    +
    1534 reinterpret_cast<const uint8_t*&>(data) += static_cast<size_t>(write_offset);
    +
    1535 length -= static_cast<size_t>(write_offset);
    +
    1536 num_skipped = static_cast<size_t>(write_offset);
    +
    1537 write_offset = 0;
    +
    1538 }
    +
    1539 else
    +
    1540 num_skipped = 0;
    +
    1541 if (write_limit == fsize_max) {
    +
    1542 num_written = m_source->write(data, length);
    +
    1543 m_state = m_source->state();
    +
    1544 }
    +
    1545 else if (length <= write_limit) {
    +
    1546 num_written = m_source->write(data, length);
    +
    1547 m_state = m_source->state();
    +
    1548 write_limit -= num_written;
    +
    1549 }
    +
    1550 else if (length && !write_limit) {
    +
    1551 num_skipped += length;
    +
    1552 num_written = 0;
    +
    1553 m_state = state_t::ok;
    +
    1554 }
    +
    1555 else {
    +
    1556 num_skipped += length - static_cast<size_t>(write_limit);
    +
    1557 num_written = m_source->write(data, static_cast<size_t>(write_limit));
    +
    1558 m_state = m_source->state();
    +
    1559 write_limit -= num_written;
    +
    1560 }
    +
    1561 return num_skipped + num_written;
    +
    1562 }
    -
    1561
    -
    1562 public:
    -
    1563 fpos_t
    - - -
    1566 };
    +
    1563
    +
    1564 public:
    +
    1565 fpos_t
    + + +
    1568 };
    -
    1567
    -
    - -
    1572 {
    -
    1573 public:
    -
    1574 file_window(_Inout_ basic_file& source, fpos_t offset = 0, fsize_t length = 0) :
    -
    1575 basic(source.state()),
    -
    1576 m_source(source),
    -
    1577 m_offset(source.tell()),
    -
    1578 m_region(offset, offset + length)
    -
    1579 {}
    -
    1580
    -
    -
    1581 virtual _Success_(return != 0 || length == 0) size_t read(
    -
    1582 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
    -
    1583 {
    -
    1584 assert(data || !length);
    -
    1585 if (m_region.contains(m_offset)) {
    -
    1586 size_t num_read = m_source.read(data, static_cast<size_t>(std::min<fpos_t>(length, m_region.end - m_offset)));
    -
    1587 m_state = m_source.state();
    -
    1588 m_offset += num_read;
    -
    1589 return num_read;
    -
    1590 }
    -
    1591 m_state = length ? state_t::eof : state_t::ok;
    -
    1592 return 0;
    -
    1593 }
    +
    1569
    +
    + +
    1574 {
    +
    1575 public:
    +
    1576 file_window(_Inout_ basic_file& source, fpos_t offset = 0, fsize_t length = 0) :
    +
    1577 basic(source.state()),
    +
    1578 m_source(source),
    +
    1579 m_offset(source.tell()),
    +
    1580 m_region(offset, offset + length)
    +
    1581 {}
    +
    1582
    +
    +
    1583 virtual _Success_(return != 0 || length == 0) size_t read(
    +
    1584 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
    +
    1585 {
    +
    1586 assert(data || !length);
    +
    1587 if (m_region.contains(m_offset)) {
    +
    1588 size_t num_read = m_source.read(data, static_cast<size_t>(std::min<fpos_t>(length, m_region.end - m_offset)));
    +
    1589 m_state = m_source.state();
    +
    1590 m_offset += num_read;
    +
    1591 return num_read;
    +
    1592 }
    +
    1593 m_state = length ? state_t::eof : state_t::ok;
    +
    1594 return 0;
    +
    1595 }
    -
    1594
    -
    -
    1595 virtual _Success_(return != 0) size_t write(
    -
    1596 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
    -
    1597 {
    -
    1598 assert(data || !length);
    -
    1599 if (m_region.contains(m_offset)) {
    -
    1600 size_t num_written = m_source.write(data, static_cast<size_t>(std::min<fpos_t>(length, m_region.end - m_offset)));
    -
    1601 m_state = m_source.state();
    -
    1602 m_offset += num_written;
    -
    1603 return num_written;
    -
    1604 }
    -
    1605 m_state = state_t::fail;
    -
    1606 return 0;
    -
    1607 }
    +
    1596
    +
    +
    1597 virtual _Success_(return != 0) size_t write(
    +
    1598 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
    +
    1599 {
    +
    1600 assert(data || !length);
    +
    1601 if (m_region.contains(m_offset)) {
    +
    1602 size_t num_written = m_source.write(data, static_cast<size_t>(std::min<fpos_t>(length, m_region.end - m_offset)));
    +
    1603 m_state = m_source.state();
    +
    1604 m_offset += num_written;
    +
    1605 return num_written;
    +
    1606 }
    +
    1607 m_state = state_t::fail;
    +
    1608 return 0;
    +
    1609 }
    -
    1608
    -
    -
    1609 virtual void close()
    -
    1610 {
    -
    1611 m_source.close();
    -
    1612 m_state = m_source.state();
    -
    1613 }
    +
    1610
    +
    +
    1611 virtual void close()
    +
    1612 {
    +
    1613 m_source.close();
    +
    1614 m_state = m_source.state();
    +
    1615 }
    -
    1614
    -
    -
    1615 virtual void flush()
    -
    1616 {
    -
    1617 m_source.flush();
    -
    1618 m_state = m_source.state();
    -
    1619 }
    +
    1616
    +
    +
    1617 virtual void flush()
    +
    1618 {
    +
    1619 m_source.flush();
    +
    1620 m_state = m_source.state();
    +
    1621 }
    -
    1620
    -
    -
    1621 virtual fpos_t seek(_In_ foff_t offset, _In_ seek_t how = seek_t::beg)
    -
    1622 {
    -
    1623 m_offset = m_source.seek(offset, how);
    -
    1624 m_state = m_source.state();
    -
    1625 return ok() ? m_offset - m_region.start : fpos_max;
    -
    1626 }
    +
    1622
    +
    +
    1623 virtual fpos_t seek(_In_ foff_t offset, _In_ seek_t how = seek_t::beg)
    +
    1624 {
    +
    1625 m_offset = m_source.seek(offset, how);
    +
    1626 m_state = m_source.state();
    +
    1627 return ok() ? m_offset - m_region.start : fpos_max;
    +
    1628 }
    -
    1627
    -
    -
    1628 virtual void skip(_In_ fsize_t amount)
    -
    1629 {
    -
    1630 m_source.skip(amount);
    -
    1631 m_state = m_source.state();
    -
    1632 }
    +
    1629
    +
    +
    1630 virtual void skip(_In_ fsize_t amount)
    +
    1631 {
    +
    1632 m_source.skip(amount);
    +
    1633 m_state = m_source.state();
    +
    1634 }
    -
    1633
    -
    -
    1634 virtual fpos_t tell() const
    -
    1635 {
    -
    1636 fpos_t offset = m_source.tell();
    -
    1637 return m_region.contains(offset) ? offset - m_region.start : fpos_max;
    -
    1638 }
    +
    1635
    +
    +
    1636 virtual fpos_t tell() const
    +
    1637 {
    +
    1638 fpos_t offset = m_source.tell();
    +
    1639 return m_region.contains(offset) ? offset - m_region.start : fpos_max;
    +
    1640 }
    -
    1639
    -
    -
    1640 virtual void lock(_In_ fpos_t offset, _In_ fsize_t length)
    -
    1641 {
    -
    1642 if (m_region.contains(offset)) {
    -
    1643 m_source.lock(m_region.start + offset, std::min<fsize_t>(length, m_region.end - offset));
    -
    1644 m_state = m_source.state();
    -
    1645 }
    -
    1646 else
    -
    1647 m_state = state_t::fail;
    -
    1648 }
    +
    1641
    +
    +
    1642 virtual void lock(_In_ fpos_t offset, _In_ fsize_t length)
    +
    1643 {
    +
    1644 if (m_region.contains(offset)) {
    +
    1645 m_source.lock(m_region.start + offset, std::min<fsize_t>(length, m_region.end - offset));
    +
    1646 m_state = m_source.state();
    +
    1647 }
    +
    1648 else
    +
    1649 m_state = state_t::fail;
    +
    1650 }
    -
    1649
    -
    -
    1650 virtual void unlock(_In_ fpos_t offset, _In_ fsize_t length)
    -
    1651 {
    -
    1652 if (m_region.contains(offset)) {
    -
    1653 m_source.unlock(m_region.start + offset, std::min<fsize_t>(length, m_region.end - offset));
    -
    1654 m_state = m_source.state();
    -
    1655 }
    -
    1656 else
    -
    1657 m_state = state_t::fail;
    -
    1658 }
    +
    1651
    +
    +
    1652 virtual void unlock(_In_ fpos_t offset, _In_ fsize_t length)
    +
    1653 {
    +
    1654 if (m_region.contains(offset)) {
    +
    1655 m_source.unlock(m_region.start + offset, std::min<fsize_t>(length, m_region.end - offset));
    +
    1656 m_state = m_source.state();
    +
    1657 }
    +
    1658 else
    +
    1659 m_state = state_t::fail;
    +
    1660 }
    -
    1659
    -
    -
    1660 virtual fsize_t size()
    -
    1661 {
    -
    1662 return m_region.size();
    -
    1663 }
    +
    1661
    +
    +
    1662 virtual fsize_t size()
    +
    1663 {
    +
    1664 return m_region.size();
    +
    1665 }
    -
    1664
    -
    -
    1665 virtual void truncate()
    -
    1666 {
    -
    1667 m_state = state_t::fail;
    -
    1668 }
    +
    1666
    +
    +
    1667 virtual void truncate()
    +
    1668 {
    +
    1669 m_state = state_t::fail;
    +
    1670 }
    -
    1669
    -
    1670 protected:
    -
    1671 basic_file& m_source;
    -
    1672 fpos_t m_offset;
    -
    1673 interval<fpos_t> m_region;
    -
    1674 };
    +
    1671
    +
    1672 protected:
    +
    1673 basic_file& m_source;
    +
    1674 fpos_t m_offset;
    +
    1675 interval<fpos_t> m_region;
    +
    1676 };
    -
    1675
    -
    1676 constexpr size_t default_cache_size = 0x1000;
    1677
    -
    -
    1681 class cache : public basic_file
    -
    1682 {
    -
    1683 protected:
    -
    1684 explicit cache(_In_ size_t cache_size = default_cache_size) :
    -
    1685 basic(state_t::fail),
    -
    1686 m_source(nullptr),
    -
    1687 m_cache(cache_size),
    -
    1688 m_offset(0)
    -
    1689#if SET_FILE_OP_TIMES
    -
    1690 , m_atime(time_point::min()),
    -
    1691 m_mtime(time_point::min())
    -
    1692#endif
    -
    1693 {}
    -
    1694
    -
    1695 void init(_Inout_ basic_file& source)
    -
    1696 {
    -
    1697 m_state = source.state();
    -
    1698 m_source = &source;
    -
    1699 m_offset = source.tell();
    -
    1700#if SET_FILE_OP_TIMES
    -
    1701 m_atime = source.atime();
    -
    1702 m_mtime = source.mtime();
    -
    1703#endif
    -
    1704 }
    -
    1705
    -
    1706 void done()
    -
    1707 {
    -
    1708 if (m_source) {
    -
    1709 flush_cache();
    -
    1710 if (!ok()) _Unlikely_
    -
    1711 throw std::runtime_error("cache flush failed"); // Data loss occured
    -
    1712 m_source->seek(m_offset);
    -
    1713 m_source = nullptr;
    -
    1714 }
    -
    1715 }
    -
    1716
    -
    1717 public:
    -
    1718 cache(_Inout_ basic_file& source, _In_ size_t cache_size = default_cache_size) :
    -
    1719 basic(source.state()),
    -
    1720 m_source(&source),
    -
    1721 m_cache(cache_size),
    -
    1722 m_offset(source.tell())
    -
    1723#if SET_FILE_OP_TIMES
    -
    1724 , m_atime(source.atime()),
    -
    1725 m_mtime(source.mtime())
    -
    1726#endif
    -
    1727 {}
    -
    1728
    -
    1729 virtual ~cache() noexcept(false)
    -
    1730 {
    -
    1731 if (m_source) {
    -
    1732 flush_cache();
    -
    1733 if (!ok()) _Unlikely_
    -
    1734 throw std::runtime_error("cache flush failed"); // Data loss occured
    -
    1735 m_source->seek(m_offset);
    -
    1736 }
    -
    1737 }
    -
    1738
    -
    -
    1739 virtual _Success_(return != 0 || length == 0) size_t read(
    -
    1740 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
    -
    1741 {
    -
    1742 assert(data || !length);
    -
    1743#if SET_FILE_OP_TIMES
    -
    1744 m_atime = time_point::now();
    -
    1745#endif
    -
    1746 for (size_t to_read = length;;) {
    -
    1747 if (m_cache.status != cache_t::cache_t::status_t::empty) {
    -
    1748 if (m_cache.region.contains(m_offset)) {
    -
    1749 size_t remaining_cache = static_cast<size_t>(m_cache.region.end - m_offset);
    -
    1750 if (to_read <= remaining_cache) {
    -
    1751 memcpy(data, m_cache.data + static_cast<size_t>(m_offset - m_cache.region.start), to_read);
    -
    1752 m_offset += to_read;
    -
    1753 m_state = state_t::ok;
    -
    1754 return length;
    -
    1755 }
    -
    1756 memcpy(data, m_cache.data + static_cast<size_t>(m_offset - m_cache.region.start), remaining_cache);
    -
    1757 reinterpret_cast<uint8_t*&>(data) += remaining_cache;
    -
    1758 to_read -= remaining_cache;
    -
    1759 m_offset += remaining_cache;
    -
    1760 }
    -
    1761 flush_cache();
    -
    1762 if (!ok()) _Unlikely_ {
    -
    1763 if (to_read < length)
    -
    1764 m_state = state_t::ok;
    -
    1765 return length - to_read;
    -
    1766 }
    -
    1767 }
    -
    1768 {
    -
    1769 fpos_t end_max = m_offset + to_read;
    -
    1770 if (m_offset / m_cache.capacity < end_max / m_cache.capacity) {
    -
    1771 // Read spans multiple cache blocks. Bypass cache to the last block.
    -
    1772 m_source->seek(m_offset);
    -
    1773 if (!m_source->ok()) _Unlikely_ {
    -
    1774 m_state = to_read < length ? state_t::ok : state_t::fail;
    -
    1775 return length - to_read;
    -
    1776 }
    -
    1777 size_t num_read = m_source->read(data, to_read - static_cast<size_t>(end_max % m_cache.capacity));
    -
    1778 m_offset += num_read;
    -
    1779 to_read -= num_read;
    -
    1780 if (!to_read) {
    -
    1781 m_state = state_t::ok;
    -
    1782 return length;
    -
    1783 }
    -
    1784 reinterpret_cast<uint8_t*&>(data) += num_read;
    -
    1785 m_state = m_source->state();
    -
    1786 if (!ok()) {
    -
    1787 if (to_read < length)
    -
    1788 m_state = state_t::ok;
    -
    1789 return length - to_read;
    -
    1790 }
    -
    1791 }
    -
    1792 }
    -
    1793 load_cache(m_offset);
    -
    1794 if (!ok() || m_cache.region.end <= m_offset) _Unlikely_ {
    -
    1795 m_state = to_read < length ? state_t::ok : state_t::fail;
    -
    1796 return length - to_read;
    -
    1797 }
    -
    1798 }
    -
    1799 }
    +
    1678 constexpr size_t default_cache_size = 0x1000;
    +
    1679
    +
    +
    1683 class cache : public basic_file
    +
    1684 {
    +
    1685 protected:
    +
    1686 explicit cache(_In_ size_t cache_size = default_cache_size) :
    +
    1687 basic(state_t::fail),
    +
    1688 m_source(nullptr),
    +
    1689 m_cache(cache_size),
    +
    1690 m_offset(0)
    +
    1691#if SET_FILE_OP_TIMES
    +
    1692 , m_atime(time_point::min()),
    +
    1693 m_mtime(time_point::min())
    +
    1694#endif
    +
    1695 {}
    +
    1696
    +
    1697 void init(_Inout_ basic_file& source)
    +
    1698 {
    +
    1699 m_state = source.state();
    +
    1700 m_source = &source;
    +
    1701 m_offset = source.tell();
    +
    1702#if SET_FILE_OP_TIMES
    +
    1703 m_atime = source.atime();
    +
    1704 m_mtime = source.mtime();
    +
    1705#endif
    +
    1706 }
    +
    1707
    +
    1708 void done()
    +
    1709 {
    +
    1710 if (m_source) {
    +
    1711 flush_cache();
    +
    1712 if (!ok()) _Unlikely_
    +
    1713 throw std::runtime_error("cache flush failed"); // Data loss occured
    +
    1714 m_source->seek(m_offset);
    +
    1715 m_source = nullptr;
    +
    1716 }
    +
    1717 }
    +
    1718
    +
    1719 public:
    +
    1720 cache(_Inout_ basic_file& source, _In_ size_t cache_size = default_cache_size) :
    +
    1721 basic(source.state()),
    +
    1722 m_source(&source),
    +
    1723 m_cache(cache_size),
    +
    1724 m_offset(source.tell())
    +
    1725#if SET_FILE_OP_TIMES
    +
    1726 , m_atime(source.atime()),
    +
    1727 m_mtime(source.mtime())
    +
    1728#endif
    +
    1729 {}
    +
    1730
    +
    1731 virtual ~cache() noexcept(false)
    +
    1732 {
    +
    1733 if (m_source) {
    +
    1734 flush_cache();
    +
    1735 if (!ok()) _Unlikely_
    +
    1736 throw std::runtime_error("cache flush failed"); // Data loss occured
    +
    1737 m_source->seek(m_offset);
    +
    1738 }
    +
    1739 }
    +
    1740
    +
    +
    1741 virtual _Success_(return != 0 || length == 0) size_t read(
    +
    1742 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
    +
    1743 {
    +
    1744 assert(data || !length);
    +
    1745#if SET_FILE_OP_TIMES
    +
    1746 m_atime = time_point::now();
    +
    1747#endif
    +
    1748 for (size_t to_read = length;;) {
    +
    1749 if (m_cache.status != cache_t::cache_t::status_t::empty) {
    +
    1750 if (m_cache.region.contains(m_offset)) {
    +
    1751 size_t remaining_cache = static_cast<size_t>(m_cache.region.end - m_offset);
    +
    1752 if (to_read <= remaining_cache) {
    +
    1753 memcpy(data, m_cache.data + static_cast<size_t>(m_offset - m_cache.region.start), to_read);
    +
    1754 m_offset += to_read;
    +
    1755 m_state = state_t::ok;
    +
    1756 return length;
    +
    1757 }
    +
    1758 memcpy(data, m_cache.data + static_cast<size_t>(m_offset - m_cache.region.start), remaining_cache);
    +
    1759 reinterpret_cast<uint8_t*&>(data) += remaining_cache;
    +
    1760 to_read -= remaining_cache;
    +
    1761 m_offset += remaining_cache;
    +
    1762 }
    +
    1763 flush_cache();
    +
    1764 if (!ok()) _Unlikely_ {
    +
    1765 if (to_read < length)
    +
    1766 m_state = state_t::ok;
    +
    1767 return length - to_read;
    +
    1768 }
    +
    1769 }
    +
    1770 {
    +
    1771 fpos_t end_max = m_offset + to_read;
    +
    1772 if (m_offset / m_cache.capacity < end_max / m_cache.capacity) {
    +
    1773 // Read spans multiple cache blocks. Bypass cache to the last block.
    +
    1774 m_source->seek(m_offset);
    +
    1775 if (!m_source->ok()) _Unlikely_ {
    +
    1776 m_state = to_read < length ? state_t::ok : state_t::fail;
    +
    1777 return length - to_read;
    +
    1778 }
    +
    1779 size_t num_read = m_source->read(data, to_read - static_cast<size_t>(end_max % m_cache.capacity));
    +
    1780 m_offset += num_read;
    +
    1781 to_read -= num_read;
    +
    1782 if (!to_read) {
    +
    1783 m_state = state_t::ok;
    +
    1784 return length;
    +
    1785 }
    +
    1786 reinterpret_cast<uint8_t*&>(data) += num_read;
    +
    1787 m_state = m_source->state();
    +
    1788 if (!ok()) {
    +
    1789 if (to_read < length)
    +
    1790 m_state = state_t::ok;
    +
    1791 return length - to_read;
    +
    1792 }
    +
    1793 }
    +
    1794 }
    +
    1795 load_cache(m_offset);
    +
    1796 if (!ok() || m_cache.region.end <= m_offset) _Unlikely_ {
    +
    1797 m_state = to_read < length ? state_t::ok : state_t::fail;
    +
    1798 return length - to_read;
    +
    1799 }
    +
    1800 }
    +
    1801 }
    -
    1800
    -
    -
    1801 virtual _Success_(return != 0) size_t write(
    -
    1802 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
    -
    1803 {
    -
    1804 assert(data || !length);
    -
    1805#if SET_FILE_OP_TIMES
    -
    1806 m_atime = m_mtime = time_point::now();
    -
    1807#endif
    -
    1808 for (size_t to_write = length;;) {
    -
    1809 if (m_cache.status != cache_t::cache_t::status_t::empty) {
    -
    1810 fpos_t end_max = m_cache.region.start + m_cache.capacity;
    -
    1811 if (m_cache.region.start <= m_offset && m_offset < end_max) {
    -
    1812 size_t remaining_cache = static_cast<size_t>(end_max - m_offset);
    -
    1813 if (to_write <= remaining_cache) {
    -
    1814 memcpy(m_cache.data + static_cast<size_t>(m_offset - m_cache.region.start), data, to_write);
    -
    1815 m_offset += to_write;
    -
    1816 m_cache.status = cache_t::cache_t::status_t::dirty;
    -
    1817 m_cache.region.end = std::max(m_cache.region.end, m_offset);
    -
    1818 m_state = state_t::ok;
    -
    1819 return length;
    -
    1820 }
    -
    1821 memcpy(m_cache.data + static_cast<size_t>(m_offset - m_cache.region.start), data, remaining_cache);
    -
    1822 reinterpret_cast<const uint8_t*&>(data) += remaining_cache;
    -
    1823 to_write -= remaining_cache;
    -
    1824 m_offset += remaining_cache;
    -
    1825 m_cache.status = cache_t::cache_t::status_t::dirty;
    -
    1826 m_cache.region.end = end_max;
    -
    1827 }
    -
    1828 flush_cache();
    -
    1829 if (!ok()) _Unlikely_
    -
    1830 return length - to_write;
    -
    1831 }
    -
    1832 {
    -
    1833 fpos_t end_max = m_offset + to_write;
    -
    1834 if (m_offset / m_cache.capacity < end_max / m_cache.capacity) {
    -
    1835 // Write spans multiple cache blocks. Bypass cache to the last block.
    -
    1836 m_source->seek(m_offset);
    -
    1837 if (!ok()) _Unlikely_
    -
    1838 return length - to_write;
    -
    1839 size_t num_written = m_source->write(data, to_write - static_cast<size_t>(end_max % m_cache.capacity));
    -
    1840 m_offset += num_written;
    -
    1841 m_state = m_source->state();
    -
    1842 to_write -= num_written;
    -
    1843 if (!to_write || !ok())
    -
    1844 return length - to_write;
    -
    1845 reinterpret_cast<const uint8_t*&>(data) += num_written;
    -
    1846 }
    -
    1847 }
    -
    1848 load_cache(m_offset);
    -
    1849 if (!ok()) _Unlikely_
    -
    1850 return length - to_write;
    -
    1851 }
    -
    1852 }
    +
    1802
    +
    +
    1803 virtual _Success_(return != 0) size_t write(
    +
    1804 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
    +
    1805 {
    +
    1806 assert(data || !length);
    +
    1807#if SET_FILE_OP_TIMES
    +
    1808 m_atime = m_mtime = time_point::now();
    +
    1809#endif
    +
    1810 for (size_t to_write = length;;) {
    +
    1811 if (m_cache.status != cache_t::cache_t::status_t::empty) {
    +
    1812 fpos_t end_max = m_cache.region.start + m_cache.capacity;
    +
    1813 if (m_cache.region.start <= m_offset && m_offset < end_max) {
    +
    1814 size_t remaining_cache = static_cast<size_t>(end_max - m_offset);
    +
    1815 if (to_write <= remaining_cache) {
    +
    1816 memcpy(m_cache.data + static_cast<size_t>(m_offset - m_cache.region.start), data, to_write);
    +
    1817 m_offset += to_write;
    +
    1818 m_cache.status = cache_t::cache_t::status_t::dirty;
    +
    1819 m_cache.region.end = std::max(m_cache.region.end, m_offset);
    +
    1820 m_state = state_t::ok;
    +
    1821 return length;
    +
    1822 }
    +
    1823 memcpy(m_cache.data + static_cast<size_t>(m_offset - m_cache.region.start), data, remaining_cache);
    +
    1824 reinterpret_cast<const uint8_t*&>(data) += remaining_cache;
    +
    1825 to_write -= remaining_cache;
    +
    1826 m_offset += remaining_cache;
    +
    1827 m_cache.status = cache_t::cache_t::status_t::dirty;
    +
    1828 m_cache.region.end = end_max;
    +
    1829 }
    +
    1830 flush_cache();
    +
    1831 if (!ok()) _Unlikely_
    +
    1832 return length - to_write;
    +
    1833 }
    +
    1834 {
    +
    1835 fpos_t end_max = m_offset + to_write;
    +
    1836 if (m_offset / m_cache.capacity < end_max / m_cache.capacity) {
    +
    1837 // Write spans multiple cache blocks. Bypass cache to the last block.
    +
    1838 m_source->seek(m_offset);
    +
    1839 if (!ok()) _Unlikely_
    +
    1840 return length - to_write;
    +
    1841 size_t num_written = m_source->write(data, to_write - static_cast<size_t>(end_max % m_cache.capacity));
    +
    1842 m_offset += num_written;
    +
    1843 m_state = m_source->state();
    +
    1844 to_write -= num_written;
    +
    1845 if (!to_write || !ok())
    +
    1846 return length - to_write;
    +
    1847 reinterpret_cast<const uint8_t*&>(data) += num_written;
    +
    1848 }
    +
    1849 }
    +
    1850 load_cache(m_offset);
    +
    1851 if (!ok()) _Unlikely_
    +
    1852 return length - to_write;
    +
    1853 }
    +
    1854 }
    -
    1853
    -
    -
    1854 virtual void close()
    -
    1855 {
    -
    1856 invalidate_cache();
    -
    1857 if (!ok()) _Unlikely_
    -
    1858 throw std::runtime_error("cache flush failed"); // Data loss occured
    -
    1859 m_source->close();
    -
    1860 m_state = m_source->state();
    -
    1861 }
    +
    1855
    +
    +
    1856 virtual void close()
    +
    1857 {
    +
    1858 invalidate_cache();
    +
    1859 if (!ok()) _Unlikely_
    +
    1860 throw std::runtime_error("cache flush failed"); // Data loss occured
    +
    1861 m_source->close();
    +
    1862 m_state = m_source->state();
    +
    1863 }
    -
    1862
    -
    -
    1863 virtual void flush()
    -
    1864 {
    -
    1865#if SET_FILE_OP_TIMES
    -
    1866 m_atime = m_mtime = time_point::min();
    -
    1867#endif
    -
    1868 flush_cache();
    -
    1869 if (!ok()) _Unlikely_
    -
    1870 return;
    -
    1871 m_source->flush();
    -
    1872 }
    +
    1864
    +
    +
    1865 virtual void flush()
    +
    1866 {
    +
    1867#if SET_FILE_OP_TIMES
    +
    1868 m_atime = m_mtime = time_point::min();
    +
    1869#endif
    +
    1870 flush_cache();
    +
    1871 if (!ok()) _Unlikely_
    +
    1872 return;
    +
    1873 m_source->flush();
    +
    1874 }
    -
    1873
    -
    -
    1874 virtual fpos_t seek(_In_ foff_t offset, _In_ seek_t how = seek_t::beg)
    -
    1875 {
    -
    1876 m_state = state_t::ok;
    -
    1877 switch (how) {
    -
    1878 case seek_t::beg:
    -
    1879 return m_offset = offset;
    -
    1880 case seek_t::cur:
    -
    1881 return m_offset += offset;
    -
    1882 case seek_t::end:
    -
    1883 return m_offset = size() + offset;
    -
    1884 default:
    -
    1885 throw std::invalid_argument("unknown seek origin");
    -
    1886 }
    -
    1887 }
    +
    1875
    +
    +
    1876 virtual fpos_t seek(_In_ foff_t offset, _In_ seek_t how = seek_t::beg)
    +
    1877 {
    +
    1878 m_state = state_t::ok;
    +
    1879 switch (how) {
    +
    1880 case seek_t::beg:
    +
    1881 return m_offset = offset;
    +
    1882 case seek_t::cur:
    +
    1883 return m_offset += offset;
    +
    1884 case seek_t::end:
    +
    1885 return m_offset = size() + offset;
    +
    1886 default:
    +
    1887 throw std::invalid_argument("unknown seek origin");
    +
    1888 }
    +
    1889 }
    -
    1888
    -
    -
    1889 virtual fpos_t tell() const
    -
    1890 {
    -
    1891 return m_offset;
    -
    1892 }
    +
    1890
    +
    +
    1891 virtual fpos_t tell() const
    +
    1892 {
    +
    1893 return m_offset;
    +
    1894 }
    -
    1893
    -
    -
    1894 virtual void lock(_In_ fpos_t offset, _In_ fsize_t length)
    -
    1895 {
    -
    1896 m_source->lock(offset, length);
    -
    1897 m_state = m_source->state();
    -
    1898 }
    +
    1895
    +
    +
    1896 virtual void lock(_In_ fpos_t offset, _In_ fsize_t length)
    +
    1897 {
    +
    1898 m_source->lock(offset, length);
    +
    1899 m_state = m_source->state();
    +
    1900 }
    -
    1899
    -
    -
    1900 virtual void unlock(_In_ fpos_t offset, _In_ fsize_t length)
    -
    1901 {
    -
    1902 m_source->unlock(offset, length);
    -
    1903 m_state = m_source->state();
    -
    1904 }
    +
    1901
    +
    +
    1902 virtual void unlock(_In_ fpos_t offset, _In_ fsize_t length)
    +
    1903 {
    +
    1904 m_source->unlock(offset, length);
    +
    1905 m_state = m_source->state();
    +
    1906 }
    -
    1905
    -
    -
    1906 virtual fsize_t size()
    -
    1907 {
    -
    1908 return m_cache.status != cache_t::cache_t::status_t::empty ?
    -
    1909 std::max(m_source->size(), m_cache.region.end) :
    -
    1910 m_source->size();
    -
    1911 }
    +
    1907
    +
    +
    1908 virtual fsize_t size()
    +
    1909 {
    +
    1910 return m_cache.status != cache_t::cache_t::status_t::empty ?
    +
    1911 std::max(m_source->size(), m_cache.region.end) :
    +
    1912 m_source->size();
    +
    1913 }
    -
    1912
    -
    -
    1913 virtual void truncate()
    -
    1914 {
    -
    1915#if SET_FILE_OP_TIMES
    -
    1916 m_atime = m_mtime = time_point::now();
    -
    1917#endif
    -
    1918 m_source->seek(m_offset);
    -
    1919 if (m_cache.region.end <= m_offset) {
    -
    1920 // Truncation does not affect cache.
    -
    1921 }
    -
    1922 else if (m_cache.region.start <= m_offset) {
    -
    1923 // Truncation truncates cache.
    -
    1924 m_cache.region.end = m_offset;
    -
    1925 }
    -
    1926 else {
    -
    1927 // Truncation invalidates cache.
    -
    1928 m_cache.status = cache_t::cache_t::status_t::empty;
    -
    1929 }
    -
    1930 m_source->truncate();
    -
    1931 m_state = m_source->state();
    -
    1932 }
    +
    1914
    +
    +
    1915 virtual void truncate()
    +
    1916 {
    +
    1917#if SET_FILE_OP_TIMES
    +
    1918 m_atime = m_mtime = time_point::now();
    +
    1919#endif
    +
    1920 m_source->seek(m_offset);
    +
    1921 if (m_cache.region.end <= m_offset) {
    +
    1922 // Truncation does not affect cache.
    +
    1923 }
    +
    1924 else if (m_cache.region.start <= m_offset) {
    +
    1925 // Truncation truncates cache.
    +
    1926 m_cache.region.end = m_offset;
    +
    1927 }
    +
    1928 else {
    +
    1929 // Truncation invalidates cache.
    +
    1930 m_cache.status = cache_t::cache_t::status_t::empty;
    +
    1931 }
    +
    1932 m_source->truncate();
    +
    1933 m_state = m_source->state();
    +
    1934 }
    -
    1933
    -
    -
    1934 virtual time_point ctime() const
    -
    1935 {
    -
    1936 return m_source->ctime();
    -
    1937 }
    +
    1935
    +
    +
    1936 virtual time_point ctime() const
    +
    1937 {
    +
    1938 return m_source->ctime();
    +
    1939 }
    -
    1938
    -
    -
    1939 virtual time_point atime() const
    -
    1940 {
    -
    1941#if SET_FILE_OP_TIMES
    -
    1942 return std::max(m_atime, m_source->atime());
    -
    1943#else
    -
    1944 return m_source->atime();
    -
    1945#endif
    -
    1946 }
    +
    1940
    +
    +
    1941 virtual time_point atime() const
    +
    1942 {
    +
    1943#if SET_FILE_OP_TIMES
    +
    1944 return std::max(m_atime, m_source->atime());
    +
    1945#else
    +
    1946 return m_source->atime();
    +
    1947#endif
    +
    1948 }
    -
    1947
    -
    -
    1948 virtual time_point mtime() const
    -
    1949 {
    -
    1950#if SET_FILE_OP_TIMES
    -
    1951 return std::max(m_mtime, m_source->mtime());
    -
    1952#else
    -
    1953 return m_source->mtime();
    -
    1954#endif
    -
    1955 }
    +
    1949
    +
    +
    1950 virtual time_point mtime() const
    +
    1951 {
    +
    1952#if SET_FILE_OP_TIMES
    +
    1953 return std::max(m_mtime, m_source->mtime());
    +
    1954#else
    +
    1955 return m_source->mtime();
    +
    1956#endif
    +
    1957 }
    -
    1956
    -
    -
    1957 virtual void set_ctime(time_point date)
    -
    1958 {
    -
    1959 m_source->set_ctime(date);
    -
    1960 }
    +
    1958
    +
    +
    1959 virtual void set_ctime(time_point date)
    +
    1960 {
    +
    1961 m_source->set_ctime(date);
    +
    1962 }
    -
    1961
    -
    -
    1962 virtual void set_atime(time_point date)
    -
    1963 {
    -
    1964#if SET_FILE_OP_TIMES
    -
    1965 m_atime = date;
    -
    1966#endif
    -
    1967 m_source->set_atime(date);
    -
    1968 }
    +
    1963
    +
    +
    1964 virtual void set_atime(time_point date)
    +
    1965 {
    +
    1966#if SET_FILE_OP_TIMES
    +
    1967 m_atime = date;
    +
    1968#endif
    +
    1969 m_source->set_atime(date);
    +
    1970 }
    -
    1969
    -
    -
    1970 virtual void set_mtime(time_point date)
    -
    1971 {
    -
    1972#if SET_FILE_OP_TIMES
    -
    1973 m_mtime = date;
    -
    1974#endif
    -
    1975 m_source->set_mtime(date);
    -
    1976 }
    +
    1971
    +
    +
    1972 virtual void set_mtime(time_point date)
    +
    1973 {
    +
    1974#if SET_FILE_OP_TIMES
    +
    1975 m_mtime = date;
    +
    1976#endif
    +
    1977 m_source->set_mtime(date);
    +
    1978 }
    -
    1977
    -
    1978 protected:
    -
    1979 void flush_cache()
    -
    1980 {
    -
    1981 if (m_cache.status != cache_t::cache_t::status_t::dirty)
    -
    1982 m_state = state_t::ok;
    -
    1983 else if (!m_cache.region.empty()) {
    -
    1984 write_cache();
    -
    1985 if (ok())
    -
    1986 m_cache.status = cache_t::cache_t::status_t::loaded;
    -
    1987 }
    -
    1988 else {
    -
    1989 m_state = state_t::ok;
    -
    1990 m_cache.status = cache_t::cache_t::status_t::loaded;
    -
    1991 }
    -
    1992 }
    -
    1993
    -
    1994 void invalidate_cache()
    -
    1995 {
    -
    1996 if (m_cache.status == cache_t::cache_t::status_t::dirty && !m_cache.region.empty()) {
    -
    1997 write_cache();
    -
    1998 if (!ok()) _Unlikely_
    -
    1999 return;
    -
    2000 } else
    -
    2001 m_state = state_t::ok;
    -
    2002 m_cache.status = cache_t::cache_t::status_t::empty;
    -
    2003 }
    -
    2004
    -
    2005 void load_cache(_In_ fpos_t start)
    -
    2006 {
    -
    2007 assert(m_cache.status != cache_t::cache_t::status_t::dirty);
    -
    2008 start -= start % m_cache.capacity; // Align to cache block size.
    -
    2009 m_source->seek(m_cache.region.start = start);
    -
    2010 if (m_source->ok()) {
    -
    2011 m_cache.region.end = start + m_source->read(m_cache.data, m_cache.capacity);
    -
    2012 m_cache.status = cache_t::cache_t::status_t::loaded;
    -
    2013 m_state = state_t::ok; // Regardless the read failure, we still might have cached some data.
    -
    2014 }
    -
    2015 else
    -
    2016 m_state = state_t::fail;
    -
    2017 }
    -
    2018
    -
    2019 void write_cache()
    -
    2020 {
    -
    2021 assert(m_cache.status == cache_t::cache_t::status_t::dirty);
    -
    2022 m_source->seek(m_cache.region.start);
    -
    2023 m_source->write(m_cache.data, static_cast<size_t>(m_cache.region.size()));
    -
    2024 m_state = m_source->state();
    -
    2025 }
    -
    2026
    -
    2027 basic_file* m_source;
    -
    -
    2028 struct cache_t {
    -
    2029 uint8_t* data;
    -
    2030 size_t capacity;
    -
    2031 enum class status_t {
    -
    2032 empty = 0,
    -
    2033 loaded,
    -
    2034 dirty,
    -
    2035 } status;
    - -
    2037
    -
    2038 cache_t(_In_ size_t _capacity) :
    -
    2039 data(new uint8_t[_capacity]),
    -
    2040 capacity(_capacity),
    -
    2041 status(status_t::empty),
    -
    2042 region(0)
    -
    2043 {}
    -
    2044
    -
    2045 ~cache_t()
    -
    2046 {
    -
    2047 delete[] data;
    -
    2048 }
    -
    2049 } m_cache;
    +
    1979
    +
    1980 protected:
    +
    1981 void flush_cache()
    +
    1982 {
    +
    1983 if (m_cache.status != cache_t::cache_t::status_t::dirty)
    +
    1984 m_state = state_t::ok;
    +
    1985 else if (!m_cache.region.empty()) {
    +
    1986 write_cache();
    +
    1987 if (ok())
    +
    1988 m_cache.status = cache_t::cache_t::status_t::loaded;
    +
    1989 }
    +
    1990 else {
    +
    1991 m_state = state_t::ok;
    +
    1992 m_cache.status = cache_t::cache_t::status_t::loaded;
    +
    1993 }
    +
    1994 }
    +
    1995
    +
    1996 void invalidate_cache()
    +
    1997 {
    +
    1998 if (m_cache.status == cache_t::cache_t::status_t::dirty && !m_cache.region.empty()) {
    +
    1999 write_cache();
    +
    2000 if (!ok()) _Unlikely_
    +
    2001 return;
    +
    2002 } else
    +
    2003 m_state = state_t::ok;
    +
    2004 m_cache.status = cache_t::cache_t::status_t::empty;
    +
    2005 }
    +
    2006
    +
    2007 void load_cache(_In_ fpos_t start)
    +
    2008 {
    +
    2009 assert(m_cache.status != cache_t::cache_t::status_t::dirty);
    +
    2010 start -= start % m_cache.capacity; // Align to cache block size.
    +
    2011 m_source->seek(m_cache.region.start = start);
    +
    2012 if (m_source->ok()) {
    +
    2013 m_cache.region.end = start + m_source->read(m_cache.data, m_cache.capacity);
    +
    2014 m_cache.status = cache_t::cache_t::status_t::loaded;
    +
    2015 m_state = state_t::ok; // Regardless the read failure, we still might have cached some data.
    +
    2016 }
    +
    2017 else
    +
    2018 m_state = state_t::fail;
    +
    2019 }
    +
    2020
    +
    2021 void write_cache()
    +
    2022 {
    +
    2023 assert(m_cache.status == cache_t::cache_t::status_t::dirty);
    +
    2024 m_source->seek(m_cache.region.start);
    +
    2025 m_source->write(m_cache.data, static_cast<size_t>(m_cache.region.size()));
    +
    2026 m_state = m_source->state();
    +
    2027 }
    +
    2028
    +
    2029 basic_file* m_source;
    +
    +
    2030 struct cache_t {
    +
    2031 uint8_t* data;
    +
    2032 size_t capacity;
    +
    2033 enum class status_t {
    +
    2034 empty = 0,
    +
    2035 loaded,
    +
    2036 dirty,
    +
    2037 } status;
    + +
    2039
    +
    2040 cache_t(_In_ size_t _capacity) :
    +
    2041 data(new uint8_t[_capacity]),
    +
    2042 capacity(_capacity),
    +
    2043 status(status_t::empty),
    +
    2044 region(0)
    +
    2045 {}
    +
    2046
    +
    2047 ~cache_t()
    +
    2048 {
    +
    2049 delete[] data;
    +
    2050 }
    +
    2051 } m_cache;
    -
    2050 fpos_t m_offset;
    -
    2051#if SET_FILE_OP_TIMES
    -
    2052 time_point
    -
    2053 m_atime,
    -
    2054 m_mtime;
    -
    2055#endif
    -
    2056 };
    +
    2052 fpos_t m_offset;
    +
    2053#if SET_FILE_OP_TIMES
    +
    2054 time_point
    +
    2055 m_atime,
    +
    2056 m_mtime;
    +
    2057#endif
    +
    2058 };
    -
    2057
    -
    -
    2061 class basic_sys : virtual public basic, public sys_object
    -
    2062 {
    -
    2063 public:
    -
    2064 basic_sys(_In_opt_ sys_handle h = invalid_handle, _In_ state_t state = state_t::ok) :
    -
    2065 basic(state),
    -
    2066 sys_object(h)
    -
    2067 {}
    -
    2068
    -
    -
    2069 virtual _Success_(return != 0 || length == 0) size_t read(
    -
    2070 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
    -
    2071 {
    -
    2072 assert(data || !length);
    -
    2073 // Windows Server 2003 and Windows XP: Pipe write operations across a network are limited in size per write.
    -
    2074 // The amount varies per platform. For x86 platforms it's 63.97 MB. For x64 platforms it's 31.97 MB. For Itanium
    -
    2075 // it's 63.95 MB. For more information regarding pipes, see the Remarks section.
    -
    2076 size_t
    -
    2077#if defined(_WIN64)
    -
    2078 block_size = 0x1F80000;
    -
    2079#elif defined(_WIN32)
    -
    2080 block_size = 0x3f00000;
    -
    2081#else
    -
    2082 block_size = SSIZE_MAX;
    -
    2083#endif
    -
    2084 for (size_t to_read = length;;) {
    -
    2085#ifdef _WIN32
    -
    2086 // ReadFile() might raise exception (e.g. STATUS_FILE_BAD_FORMAT/0xE0000002).
    -
    2087 BOOL succeeded;
    -
    2088 DWORD num_read;
    -
    2089 __try { succeeded = ReadFile(m_h, data, static_cast<DWORD>(std::min<size_t>(to_read, block_size)), &num_read, nullptr); }
    -
    2090 __except (EXCEPTION_EXECUTE_HANDLER) { succeeded = FALSE; SetLastError(ERROR_UNHANDLED_EXCEPTION); num_read = 0; }
    -
    2091 if (!succeeded && GetLastError() == ERROR_NO_SYSTEM_RESOURCES && block_size > default_block_size) _Unlikely_ {
    -
    2092 // Error "Insufficient system resources exist to complete the requested service." occurs
    -
    2093 // ocasionally, when attempting to read too much data at once (e.g. over \\TSClient).
    -
    2094 block_size = default_block_size;
    -
    2095 continue;
    -
    2096 }
    -
    2097 if (!succeeded) _Unlikely_
    -
    2098#else
    -
    2099 ssize_t num_read = static_cast<ssize_t>(std::min<size_t>(to_read, block_size));
    -
    2100 num_read = read(m_h, data, num_read);
    -
    2101 if (num_read < 0) _Unlikely_
    -
    2102#endif
    -
    2103 {
    -
    2104 m_state = to_read < length ? state_t::ok : state_t::fail;
    -
    2105 return length - to_read;
    -
    2106 }
    -
    2107 if (!num_read) _Unlikely_ {
    -
    2108 m_state = to_read < length || !length ? state_t::ok : state_t::eof;
    -
    2109 return length - to_read;
    -
    2110 }
    -
    2111 to_read -= num_read;
    -
    2112 if (!to_read) {
    -
    2113 m_state = state_t::ok;
    -
    2114 return length;
    -
    2115 }
    -
    2116 reinterpret_cast<uint8_t*&>(data) += num_read;
    -
    2117 }
    -
    2118 }
    +
    2059
    +
    +
    2063 class basic_sys : virtual public basic, public sys_object
    +
    2064 {
    +
    2065 public:
    +
    2066 basic_sys(_In_opt_ sys_handle h = invalid_handle, _In_ state_t state = state_t::ok) :
    +
    2067 basic(state),
    +
    2068 sys_object(h)
    +
    2069 {}
    +
    2070
    +
    +
    2071 virtual _Success_(return != 0 || length == 0) size_t read(
    +
    2072 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
    +
    2073 {
    +
    2074 assert(data || !length);
    +
    2075 // Windows Server 2003 and Windows XP: Pipe write operations across a network are limited in size per write.
    +
    2076 // The amount varies per platform. For x86 platforms it's 63.97 MB. For x64 platforms it's 31.97 MB. For Itanium
    +
    2077 // it's 63.95 MB. For more information regarding pipes, see the Remarks section.
    +
    2078 size_t
    +
    2079#if defined(_WIN64)
    +
    2080 block_size = 0x1F80000;
    +
    2081#elif defined(_WIN32)
    +
    2082 block_size = 0x3f00000;
    +
    2083#else
    +
    2084 block_size = SSIZE_MAX;
    +
    2085#endif
    +
    2086 for (size_t to_read = length;;) {
    +
    2087#ifdef _WIN32
    +
    2088 // ReadFile() might raise exception (e.g. STATUS_FILE_BAD_FORMAT/0xE0000002).
    +
    2089 BOOL succeeded;
    +
    2090 DWORD num_read;
    +
    2091 __try { succeeded = ReadFile(m_h, data, static_cast<DWORD>(std::min<size_t>(to_read, block_size)), &num_read, nullptr); }
    +
    2092 __except (EXCEPTION_EXECUTE_HANDLER) { succeeded = FALSE; SetLastError(ERROR_UNHANDLED_EXCEPTION); num_read = 0; }
    +
    2093 if (!succeeded && GetLastError() == ERROR_NO_SYSTEM_RESOURCES && block_size > default_block_size) _Unlikely_ {
    +
    2094 // Error "Insufficient system resources exist to complete the requested service." occurs
    +
    2095 // ocasionally, when attempting to read too much data at once (e.g. over \\TSClient).
    +
    2096 block_size = default_block_size;
    +
    2097 continue;
    +
    2098 }
    +
    2099 if (!succeeded) _Unlikely_
    +
    2100#else
    +
    2101 ssize_t num_read = ::read(m_h, data, static_cast<ssize_t>(std::min<size_t>(to_read, block_size)));
    +
    2102 if (num_read < 0) _Unlikely_
    +
    2103#endif
    +
    2104 {
    +
    2105 m_state = to_read < length ? state_t::ok : state_t::fail;
    +
    2106 return length - to_read;
    +
    2107 }
    +
    2108 if (!num_read) _Unlikely_ {
    +
    2109 m_state = to_read < length || !length ? state_t::ok : state_t::eof;
    +
    2110 return length - to_read;
    +
    2111 }
    +
    2112 to_read -= num_read;
    +
    2113 if (!to_read) {
    +
    2114 m_state = state_t::ok;
    +
    2115 return length;
    +
    2116 }
    +
    2117 reinterpret_cast<uint8_t*&>(data) += num_read;
    +
    2118 }
    +
    2119 }
    -
    2119
    -
    -
    2120 virtual _Success_(return != 0) size_t write(
    -
    2121 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
    -
    2122 {
    -
    2123 // Windows Server 2003 and Windows XP: Pipe write operations across a network are limited in size per write.
    -
    2124 // The amount varies per platform. For x86 platforms it's 63.97 MB. For x64 platforms it's 31.97 MB. For Itanium
    -
    2125 // it's 63.95 MB. For more information regarding pipes, see the Remarks section.
    -
    2126 constexpr size_t
    -
    2127#if defined(_WIN64)
    -
    2128 block_size = 0x1F80000;
    -
    2129#elif defined(_WIN32)
    -
    2130 block_size = 0x3f00000;
    -
    2131#else
    -
    2132 block_size = SSIZE_MAX;
    -
    2133#endif
    -
    2134 for (size_t to_write = length;;) {
    -
    2135#ifdef _WIN32
    -
    2136 // ReadFile() might raise an exception. Be cautious with WriteFile() too.
    -
    2137 BOOL succeeded;
    -
    2138 DWORD num_written;
    -
    2139 __try { succeeded = WriteFile(m_h, data, static_cast<DWORD>(std::min<size_t>(to_write, block_size)), &num_written, nullptr); }
    -
    2140 __except (EXCEPTION_EXECUTE_HANDLER) { succeeded = FALSE; SetLastError(ERROR_UNHANDLED_EXCEPTION); num_written = 0; }
    -
    2141 to_write -= num_written;
    -
    2142 if (!to_write) {
    -
    2143 m_state = state_t::ok;
    -
    2144 return length;
    -
    2145 }
    -
    2146 reinterpret_cast<const uint8_t*&>(data) += num_written;
    -
    2147 if (!succeeded) _Unlikely_ {
    -
    2148 m_state = state_t::fail;
    -
    2149 return length - to_write;
    -
    2150 }
    -
    2151#else
    -
    2152 ssize_t num_written = write(m_h, data, static_cast<ssize_t>(std::min<size_t>(to_write, block_size)));
    -
    2153 if (num_written < 0) _Unlikely_ {
    -
    2154 m_state = state_t::fail;
    -
    2155 return length - to_write;
    -
    2156 }
    -
    2157 to_write -= num_written;
    -
    2158 if (!to_write) {
    -
    2159 m_state = state_t::ok;
    -
    2160 return length;
    -
    2161 }
    -
    2162 reinterpret_cast<const uint8_t*&>(data) += num_written;
    -
    2163#endif
    -
    2164 }
    -
    2165 }
    +
    2120
    +
    +
    2121 virtual _Success_(return != 0) size_t write(
    +
    2122 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
    +
    2123 {
    +
    2124 // Windows Server 2003 and Windows XP: Pipe write operations across a network are limited in size per write.
    +
    2125 // The amount varies per platform. For x86 platforms it's 63.97 MB. For x64 platforms it's 31.97 MB. For Itanium
    +
    2126 // it's 63.95 MB. For more information regarding pipes, see the Remarks section.
    +
    2127 constexpr size_t
    +
    2128#if defined(_WIN64)
    +
    2129 block_size = 0x1F80000;
    +
    2130#elif defined(_WIN32)
    +
    2131 block_size = 0x3f00000;
    +
    2132#else
    +
    2133 block_size = SSIZE_MAX;
    +
    2134#endif
    +
    2135 for (size_t to_write = length;;) {
    +
    2136#ifdef _WIN32
    +
    2137 // ReadFile() might raise an exception. Be cautious with WriteFile() too.
    +
    2138 BOOL succeeded;
    +
    2139 DWORD num_written;
    +
    2140 __try { succeeded = WriteFile(m_h, data, static_cast<DWORD>(std::min<size_t>(to_write, block_size)), &num_written, nullptr); }
    +
    2141 __except (EXCEPTION_EXECUTE_HANDLER) { succeeded = FALSE; SetLastError(ERROR_UNHANDLED_EXCEPTION); num_written = 0; }
    +
    2142 to_write -= num_written;
    +
    2143 if (!to_write) {
    +
    2144 m_state = state_t::ok;
    +
    2145 return length;
    +
    2146 }
    +
    2147 reinterpret_cast<const uint8_t*&>(data) += num_written;
    +
    2148 if (!succeeded) _Unlikely_ {
    +
    2149 m_state = state_t::fail;
    +
    2150 return length - to_write;
    +
    2151 }
    +
    2152#else
    +
    2153 ssize_t num_written = ::write(m_h, data, static_cast<ssize_t>(std::min<size_t>(to_write, block_size)));
    +
    2154 if (num_written < 0) _Unlikely_ {
    +
    2155 m_state = state_t::fail;
    +
    2156 return length - to_write;
    +
    2157 }
    +
    2158 to_write -= num_written;
    +
    2159 if (!to_write) {
    +
    2160 m_state = state_t::ok;
    +
    2161 return length;
    +
    2162 }
    +
    2163 reinterpret_cast<const uint8_t*&>(data) += num_written;
    +
    2164#endif
    +
    2165 }
    +
    2166 }
    -
    2166
    -
    -
    2167 virtual void close()
    -
    2168 {
    -
    2169 try {
    - -
    2171 m_state = state_t::ok;
    -
    2172 }
    -
    2173 catch (...) {
    -
    2174 m_state = state_t::fail;
    -
    2175 }
    -
    2176 }
    +
    2167
    +
    +
    2168 virtual void close()
    +
    2169 {
    +
    2170 try {
    + +
    2172 m_state = state_t::ok;
    +
    2173 }
    +
    2174 catch (...) {
    +
    2175 m_state = state_t::fail;
    +
    2176 }
    +
    2177 }
    -
    2177
    -
    -
    2178 virtual void flush()
    -
    2179 {
    -
    2180#ifdef _WIN32
    -
    2181 m_state = FlushFileBuffers(m_h) ? state_t::ok : state_t::fail;
    -
    2182#else
    -
    2183 m_state = fsync(m_h) >= 0 ? state_t::ok : state_t::fail;
    -
    2184#endif
    -
    2185 }
    +
    2178
    +
    +
    2179 virtual void flush()
    +
    2180 {
    +
    2181#ifdef _WIN32
    +
    2182 m_state = FlushFileBuffers(m_h) ? state_t::ok : state_t::fail;
    +
    2183#else
    +
    2184 m_state = fsync(m_h) >= 0 ? state_t::ok : state_t::fail;
    +
    2185#endif
    +
    2186 }
    -
    2186 };
    +
    2187 };
    -
    2187
    -
    -
    2191 class buffered_sys : public buffer
    -
    2192 {
    -
    2193 public:
    -
    2194 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) :
    -
    2195 buffer(read_buffer_size, write_buffer_size),
    -
    2196 m_source(h)
    -
    2197 {
    -
    2198 init(m_source);
    -
    2199 }
    -
    2200
    -
    2201 virtual ~buffered_sys()
    -
    2202 {
    -
    2203 done();
    -
    2204 }
    -
    2205
    -
    2206 protected:
    -
    2207 basic_sys m_source;
    -
    2208 };
    +
    2188
    +
    +
    2192 class buffered_sys : public buffer
    +
    2193 {
    +
    2194 public:
    +
    2195 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) :
    +
    2196 buffer(read_buffer_size, write_buffer_size),
    +
    2197 m_source(h)
    +
    2198 {
    +
    2199 init(m_source);
    +
    2200 }
    +
    2201
    +
    2202 virtual ~buffered_sys()
    +
    2203 {
    +
    2204 done();
    +
    2205 }
    +
    2206
    +
    2207 protected:
    +
    2208 basic_sys m_source;
    +
    2209 };
    -
    2209
    -
    2210#ifdef _WIN32
    -
    2214 class sequential_stream : public basic
    -
    2215 {
    -
    2216 public:
    -
    2217 sequential_stream(_In_ ISequentialStream* source) : m_source(source)
    -
    2218 {
    -
    2219 m_source->AddRef();
    -
    2220 }
    -
    2221
    -
    2222 virtual ~sequential_stream()
    -
    2223 {
    -
    2224 m_source->Release();
    -
    2225 }
    -
    2226
    -
    2227 virtual _Success_(return != 0 || length == 0) size_t read(
    -
    2228 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
    -
    2229 {
    -
    2230 assert(data || !length);
    -
    2231 for (size_t to_read = length;;) {
    -
    2232 HRESULT hr;
    -
    2233 ULONG num_read = 0;
    -
    2234 __try { hr = m_source->Read(data, (ULONG)std::min<size_t>(to_read, ULONG_MAX), &num_read); }
    -
    2235 __except (EXCEPTION_EXECUTE_HANDLER) { hr = E_FAIL; }
    -
    2236 if (FAILED(hr)) _Unlikely_ {
    -
    2237 m_state = to_read < length ? state_t::ok : state_t::fail;
    -
    2238 return length - to_read;
    -
    2239 }
    -
    2240 to_read -= num_read;
    -
    2241 if (hr == S_FALSE) _Unlikely_ {
    -
    2242 m_state = to_read < length || !length ? state_t::ok : state_t::eof;
    -
    2243 return length - to_read;
    -
    2244 }
    -
    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 assert(data || !length);
    -
    2257 for (size_t to_write = length;;) {
    -
    2258 HRESULT hr;
    -
    2259 ULONG num_written = 0;
    -
    2260 __try { hr = m_source->Write(data, static_cast<ULONG>(std::min<size_t>(to_write, ULONG_MAX)), &num_written); }
    -
    2261 __except (EXCEPTION_EXECUTE_HANDLER) { hr = E_FAIL; }
    -
    2262 // In abscence of documentation whether num_written gets set when FAILED(hr) (i.e. partially succesful writes),
    -
    2263 // assume write failed completely.
    -
    2264 if (FAILED(hr)) _Unlikely_ {
    -
    2265 m_state = state_t::fail;
    -
    2266 return length - to_write;
    -
    2267 }
    -
    2268 to_write -= num_written;
    -
    2269 if (!to_write) {
    -
    2270 m_state = state_t::ok;
    -
    2271 return length;
    -
    2272 }
    -
    2273 reinterpret_cast<const uint8_t*&>(data) += num_written;
    -
    2274 }
    -
    2275 }
    -
    2276
    -
    2277 protected:
    -
    2278 ISequentialStream* m_source;
    -
    2279 };
    -
    2280
    -
    2284 class asp : public basic
    -
    2285 {
    -
    2286 public:
    -
    2287 asp(_In_opt_ IRequest* request, _In_opt_ IResponse* response) :
    -
    2288 m_request(request),
    -
    2289 m_response(response)
    -
    2290 {
    -
    2291 if (m_request)
    -
    2292 m_request->AddRef();
    -
    2293 if (m_response)
    -
    2294 m_response->AddRef();
    -
    2295 }
    -
    2296
    -
    2297 virtual ~asp()
    -
    2298 {
    -
    2299 if (m_request)
    -
    2300 m_request->Release();
    -
    2301 if (m_response)
    -
    2302 m_response->Release();
    -
    2303 }
    -
    2304
    -
    2305 virtual _Success_(return != 0 || length == 0) size_t read(
    -
    2306 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
    -
    2307 {
    -
    2308 assert(data || !length);
    -
    2309 if (!m_request) _Unlikely_ {
    -
    2310 m_state = state_t::fail;
    -
    2311 return 0;
    -
    2312 }
    -
    2313 for (size_t to_read = length;;) {
    -
    2314 VARIANT var_amount, var_data;
    -
    2315 V_VT(&var_amount) = VT_I4;
    -
    2316 V_I4(&var_amount) = (LONG)std::min<size_t>(to_read, LONG_MAX);
    -
    2317 V_VT(&var_data) = VT_EMPTY;
    -
    2318 HRESULT hr = [&]() {
    -
    2319 __try { return m_request->BinaryRead(&var_amount, &var_data); }
    -
    2320 __except (EXCEPTION_EXECUTE_HANDLER) { return E_FAIL; }
    -
    2321 }();
    -
    2322 if (FAILED(hr)) _Unlikely_ {
    -
    2323 m_state = to_read < length ? state_t::ok : state_t::fail;
    -
    2324 return length - to_read;
    -
    2325 }
    -
    2326 assert(V_VT(&var_amount) == VT_I4);
    -
    2327 assert(V_VT(&var_data) == (VT_ARRAY | VT_UI1));
    -
    2328 std::unique_ptr<SAFEARRAY, SafeArrayDestroy_delete> sa(V_ARRAY(&var_data));
    -
    2329 if (!V_I4(&var_amount)) _Unlikely_ {
    -
    2330 m_state = to_read < length || !length ? state_t::ok : state_t::eof;
    -
    2331 return length - to_read;
    -
    2332 }
    -
    2333 safearray_accessor<uint8_t> a(sa.get());
    -
    2334 memcpy(data, a.data(), V_I4(&var_amount));
    -
    2335 to_read -= V_I4(&var_amount);
    -
    2336 if (!to_read) {
    -
    2337 m_state = state_t::ok;
    -
    2338 return length;
    -
    2339 }
    -
    2340 reinterpret_cast<uint8_t*&>(data) += V_I4(&var_amount);
    -
    2341 }
    -
    2342 }
    -
    2343
    -
    2344 virtual _Success_(return != 0) size_t write(
    -
    2345 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
    -
    2346 {
    -
    2347 if (!m_response) {
    -
    2348 m_state = state_t::fail;
    -
    2349 return 0;
    -
    2350 }
    -
    2351 for (size_t to_write = length;;) {
    -
    2352 UINT num_written = static_cast<UINT>(std::min<size_t>(to_write, UINT_MAX));
    -
    2353 std::unique_ptr<OLECHAR, SysFreeString_delete> bstr_data(SysAllocStringByteLen(reinterpret_cast<LPCSTR>(data), num_written));
    -
    2354 VARIANT var_data;
    -
    2355 V_VT(&var_data) = VT_BSTR;
    -
    2356 V_BSTR(&var_data) = bstr_data.get();
    -
    2357 HRESULT hr = [&]() {
    -
    2358 __try { return m_response->BinaryWrite(var_data); }
    -
    2359 __except (EXCEPTION_EXECUTE_HANDLER) { return E_FAIL; }
    -
    2360 }();
    -
    2361 if (FAILED(hr)) _Unlikely_ {
    -
    2362 m_state = state_t::fail;
    -
    2363 return length - to_write;
    -
    2364 }
    -
    2365 to_write -= num_written;
    -
    2366 if (!to_write) {
    -
    2367 m_state = state_t::ok;
    -
    2368 return length;
    -
    2369 }
    -
    2370 reinterpret_cast<const uint8_t*&>(data) += num_written;
    -
    2371 }
    -
    2372 }
    -
    2373
    -
    2374 virtual void close()
    -
    2375 {
    -
    2376 if (m_response) {
    -
    2377 __try { m_response->End(); }
    -
    2378 __except (EXCEPTION_EXECUTE_HANDLER) {}
    -
    2379 }
    -
    2380 m_state = state_t::ok;
    -
    2381 }
    -
    2382
    -
    2383 virtual void flush()
    -
    2384 {
    -
    2385 if (m_response) {
    -
    2386 HRESULT hr;
    -
    2387 __try { hr = m_response->Flush(); }
    -
    2388 __except (EXCEPTION_EXECUTE_HANDLER) { hr = E_FAIL; }
    -
    2389 m_state = SUCCEEDED(hr) ? state_t::ok : state_t::fail;
    -
    2390 }
    -
    2391 }
    -
    2392
    -
    2393 protected:
    -
    2394 IRequest* m_request;
    -
    2395 IResponse* m_response;
    -
    2396 };
    -
    2397#endif
    -
    2398
    -
    2402 enum mode_t
    -
    2403 {
    -
    2404 mode_for_reading = 1 << 0,
    -
    2405 mode_for_writing = 1 << 1,
    -
    2406 mode_for_chmod = 1 << 2,
    -
    2407 mode_create = 1 << 3,
    -
    2408 mode_preserve_existing = mode_create | (1 << 4),
    -
    2409 mode_append = 1 << 5,
    -
    2410 mode_text = 0,
    -
    2411 mode_binary = 1 << 6,
    -
    2412
    -
    2413 share_none = 0,
    -
    2414 share_reading = 1 << 7,
    -
    2415 share_writing = 1 << 8,
    -
    2416 share_deleting = 1 << 9,
    -
    2417 share_all = share_reading | share_writing | share_deleting, // Allow others all operations on our file
    -
    2418
    -
    2419 inherit_handle = 1 << 10,
    -
    2420
    -
    2421 hint_write_thru = 1 << 11,
    -
    2422 hint_no_buffering = 1 << 12,
    -
    2423 hint_random_access = 1 << 13,
    -
    2424 hint_sequential_access = 1 << 14,
    -
    2425 };
    -
    2426
    -
    2427#pragma warning(push)
    -
    2428#pragma warning(disable: 4250)
    -
    -
    2432 class file : virtual public basic_file, virtual public basic_sys
    -
    2433 {
    -
    2434 public:
    -
    2435 file(_In_opt_ sys_handle h = invalid_handle, _In_ state_t state = state_t::ok) : basic_sys(h, state) {}
    -
    2436
    -
    -
    2443 file(_In_z_ const schar_t* filename, _In_ int mode)
    -
    2444 {
    -
    2445 open(filename, mode);
    -
    2446 }
    +
    2210
    +
    2211#ifdef _WIN32
    +
    2215 class sequential_stream : public basic
    +
    2216 {
    +
    2217 public:
    +
    2218 sequential_stream(_In_ ISequentialStream* source) : m_source(source)
    +
    2219 {
    +
    2220 m_source->AddRef();
    +
    2221 }
    +
    2222
    +
    2223 virtual ~sequential_stream()
    +
    2224 {
    +
    2225 m_source->Release();
    +
    2226 }
    +
    2227
    +
    2228 virtual _Success_(return != 0 || length == 0) size_t read(
    +
    2229 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
    +
    2230 {
    +
    2231 assert(data || !length);
    +
    2232 for (size_t to_read = length;;) {
    +
    2233 HRESULT hr;
    +
    2234 ULONG num_read = 0;
    +
    2235 __try { hr = m_source->Read(data, (ULONG)std::min<size_t>(to_read, ULONG_MAX), &num_read); }
    +
    2236 __except (EXCEPTION_EXECUTE_HANDLER) { hr = E_FAIL; }
    +
    2237 if (FAILED(hr)) _Unlikely_ {
    +
    2238 m_state = to_read < length ? state_t::ok : state_t::fail;
    +
    2239 return length - to_read;
    +
    2240 }
    +
    2241 to_read -= num_read;
    +
    2242 if (hr == S_FALSE) _Unlikely_ {
    +
    2243 m_state = to_read < length || !length ? state_t::ok : state_t::eof;
    +
    2244 return length - to_read;
    +
    2245 }
    +
    2246 if (!to_read) {
    +
    2247 m_state = state_t::ok;
    +
    2248 return length;
    +
    2249 }
    +
    2250 reinterpret_cast<uint8_t*&>(data) += num_read;
    +
    2251 }
    +
    2252 }
    +
    2253
    +
    2254 virtual _Success_(return != 0) size_t write(
    +
    2255 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
    +
    2256 {
    +
    2257 assert(data || !length);
    +
    2258 for (size_t to_write = length;;) {
    +
    2259 HRESULT hr;
    +
    2260 ULONG num_written = 0;
    +
    2261 __try { hr = m_source->Write(data, static_cast<ULONG>(std::min<size_t>(to_write, ULONG_MAX)), &num_written); }
    +
    2262 __except (EXCEPTION_EXECUTE_HANDLER) { hr = E_FAIL; }
    +
    2263 // In abscence of documentation whether num_written gets set when FAILED(hr) (i.e. partially succesful writes),
    +
    2264 // assume write failed completely.
    +
    2265 if (FAILED(hr)) _Unlikely_ {
    +
    2266 m_state = state_t::fail;
    +
    2267 return length - to_write;
    +
    2268 }
    +
    2269 to_write -= num_written;
    +
    2270 if (!to_write) {
    +
    2271 m_state = state_t::ok;
    +
    2272 return length;
    +
    2273 }
    +
    2274 reinterpret_cast<const uint8_t*&>(data) += num_written;
    +
    2275 }
    +
    2276 }
    +
    2277
    +
    2278 protected:
    +
    2279 ISequentialStream* m_source;
    +
    2280 };
    +
    2281
    +
    2285 class asp : public basic
    +
    2286 {
    +
    2287 public:
    +
    2288 asp(_In_opt_ IRequest* request, _In_opt_ IResponse* response) :
    +
    2289 m_request(request),
    +
    2290 m_response(response)
    +
    2291 {
    +
    2292 if (m_request)
    +
    2293 m_request->AddRef();
    +
    2294 if (m_response)
    +
    2295 m_response->AddRef();
    +
    2296 }
    +
    2297
    +
    2298 virtual ~asp()
    +
    2299 {
    +
    2300 if (m_request)
    +
    2301 m_request->Release();
    +
    2302 if (m_response)
    +
    2303 m_response->Release();
    +
    2304 }
    +
    2305
    +
    2306 virtual _Success_(return != 0 || length == 0) size_t read(
    +
    2307 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
    +
    2308 {
    +
    2309 assert(data || !length);
    +
    2310 if (!m_request) _Unlikely_ {
    +
    2311 m_state = state_t::fail;
    +
    2312 return 0;
    +
    2313 }
    +
    2314 for (size_t to_read = length;;) {
    +
    2315 VARIANT var_amount, var_data;
    +
    2316 V_VT(&var_amount) = VT_I4;
    +
    2317 V_I4(&var_amount) = (LONG)std::min<size_t>(to_read, LONG_MAX);
    +
    2318 V_VT(&var_data) = VT_EMPTY;
    +
    2319 HRESULT hr = [&]() {
    +
    2320 __try { return m_request->BinaryRead(&var_amount, &var_data); }
    +
    2321 __except (EXCEPTION_EXECUTE_HANDLER) { return E_FAIL; }
    +
    2322 }();
    +
    2323 if (FAILED(hr)) _Unlikely_ {
    +
    2324 m_state = to_read < length ? state_t::ok : state_t::fail;
    +
    2325 return length - to_read;
    +
    2326 }
    +
    2327 assert(V_VT(&var_amount) == VT_I4);
    +
    2328 assert(V_VT(&var_data) == (VT_ARRAY | VT_UI1));
    +
    2329 std::unique_ptr<SAFEARRAY, SafeArrayDestroy_delete> sa(V_ARRAY(&var_data));
    +
    2330 if (!V_I4(&var_amount)) _Unlikely_ {
    +
    2331 m_state = to_read < length || !length ? state_t::ok : state_t::eof;
    +
    2332 return length - to_read;
    +
    2333 }
    +
    2334 safearray_accessor<uint8_t> a(sa.get());
    +
    2335 memcpy(data, a.data(), V_I4(&var_amount));
    +
    2336 to_read -= V_I4(&var_amount);
    +
    2337 if (!to_read) {
    +
    2338 m_state = state_t::ok;
    +
    2339 return length;
    +
    2340 }
    +
    2341 reinterpret_cast<uint8_t*&>(data) += V_I4(&var_amount);
    +
    2342 }
    +
    2343 }
    +
    2344
    +
    2345 virtual _Success_(return != 0) size_t write(
    +
    2346 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
    +
    2347 {
    +
    2348 if (!m_response) {
    +
    2349 m_state = state_t::fail;
    +
    2350 return 0;
    +
    2351 }
    +
    2352 for (size_t to_write = length;;) {
    +
    2353 UINT num_written = static_cast<UINT>(std::min<size_t>(to_write, UINT_MAX));
    +
    2354 std::unique_ptr<OLECHAR, SysFreeString_delete> bstr_data(SysAllocStringByteLen(reinterpret_cast<LPCSTR>(data), num_written));
    +
    2355 VARIANT var_data;
    +
    2356 V_VT(&var_data) = VT_BSTR;
    +
    2357 V_BSTR(&var_data) = bstr_data.get();
    +
    2358 HRESULT hr = [&]() {
    +
    2359 __try { return m_response->BinaryWrite(var_data); }
    +
    2360 __except (EXCEPTION_EXECUTE_HANDLER) { return E_FAIL; }
    +
    2361 }();
    +
    2362 if (FAILED(hr)) _Unlikely_ {
    +
    2363 m_state = state_t::fail;
    +
    2364 return length - to_write;
    +
    2365 }
    +
    2366 to_write -= num_written;
    +
    2367 if (!to_write) {
    +
    2368 m_state = state_t::ok;
    +
    2369 return length;
    +
    2370 }
    +
    2371 reinterpret_cast<const uint8_t*&>(data) += num_written;
    +
    2372 }
    +
    2373 }
    +
    2374
    +
    2375 virtual void close()
    +
    2376 {
    +
    2377 if (m_response) {
    +
    2378 __try { m_response->End(); }
    +
    2379 __except (EXCEPTION_EXECUTE_HANDLER) {}
    +
    2380 }
    +
    2381 m_state = state_t::ok;
    +
    2382 }
    +
    2383
    +
    2384 virtual void flush()
    +
    2385 {
    +
    2386 if (m_response) {
    +
    2387 HRESULT hr;
    +
    2388 __try { hr = m_response->Flush(); }
    +
    2389 __except (EXCEPTION_EXECUTE_HANDLER) { hr = E_FAIL; }
    +
    2390 m_state = SUCCEEDED(hr) ? state_t::ok : state_t::fail;
    +
    2391 }
    +
    2392 }
    +
    2393
    +
    2394 protected:
    +
    2395 IRequest* m_request;
    +
    2396 IResponse* m_response;
    +
    2397 };
    +
    2398#endif
    +
    2399
    +
    2403 enum mode_t
    +
    2404 {
    +
    2405 mode_for_reading = 1 << 0,
    +
    2406 mode_for_writing = 1 << 1,
    +
    2407 mode_for_chmod = 1 << 2,
    +
    2408 mode_create = 1 << 3,
    +
    2409 mode_preserve_existing = mode_create | (1 << 4),
    +
    2410 mode_append = 1 << 5,
    +
    2411 mode_text = 0,
    +
    2412 mode_binary = 1 << 6,
    +
    2413
    +
    2414 share_none = 0,
    +
    2415 share_reading = 1 << 7,
    +
    2416 share_writing = 1 << 8,
    +
    2417 share_deleting = 1 << 9,
    +
    2418 share_all = share_reading | share_writing | share_deleting, // Allow others all operations on our file
    +
    2419
    +
    2420 inherit_handle = 1 << 10,
    +
    2421
    +
    2422 hint_write_thru = 1 << 11,
    +
    2423 hint_no_buffering = 1 << 12,
    +
    2424 hint_random_access = 1 << 13,
    +
    2425 hint_sequential_access = 1 << 14,
    +
    2426 };
    +
    2427
    +
    2428#pragma warning(push)
    +
    2429#pragma warning(disable: 4250)
    +
    +
    2433 class file : virtual public basic_file, virtual public basic_sys
    +
    2434 {
    +
    2435 public:
    +
    2436 file(_In_opt_ sys_handle h = invalid_handle, _In_ state_t state = state_t::ok) : basic_sys(h, state) {}
    +
    2437
    +
    +
    2444 file(_In_z_ const schar_t* filename, _In_ int mode)
    +
    2445 {
    +
    2446 open(filename, mode);
    +
    2447 }
    -
    2447
    -
    -
    2454 void open(_In_z_ const schar_t* filename, _In_ int mode)
    -
    2455 {
    -
    2456 if (m_h != invalid_handle)
    -
    2457 close();
    -
    2458
    -
    2459#ifdef _WIN32
    -
    2460 DWORD dwDesiredAccess = 0;
    -
    2461 if (mode & mode_for_reading) dwDesiredAccess |= GENERIC_READ;
    -
    2462 if (mode & mode_for_writing) dwDesiredAccess |= GENERIC_WRITE;
    -
    2463 if (mode & mode_for_chmod) dwDesiredAccess |= FILE_WRITE_ATTRIBUTES;
    -
    2464
    -
    2465 DWORD dwShareMode = 0;
    -
    2466 if (mode & share_reading) dwShareMode |= FILE_SHARE_READ;
    -
    2467 if (mode & share_writing) dwShareMode |= FILE_SHARE_WRITE;
    -
    2468 if (mode & share_deleting) dwShareMode |= FILE_SHARE_DELETE;
    -
    2469
    -
    2470 SECURITY_ATTRIBUTES sa = { sizeof(SECURITY_ATTRIBUTES) };
    -
    2471 sa.bInheritHandle = mode & inherit_handle ? true : false;
    -
    2472
    -
    2473 DWORD dwCreationDisposition;
    -
    2474 switch (mode & mode_preserve_existing) {
    -
    2475 case mode_create: dwCreationDisposition = CREATE_ALWAYS; break;
    -
    2476 case mode_preserve_existing: dwCreationDisposition = OPEN_ALWAYS; break;
    -
    2477 case 0: dwCreationDisposition = OPEN_EXISTING; break;
    -
    2478 default: throw std::invalid_argument("invalid mode");
    -
    2479 }
    -
    2480
    -
    2481 DWORD dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL;
    -
    2482 if (mode & hint_write_thru) dwFlagsAndAttributes |= FILE_FLAG_WRITE_THROUGH;
    -
    2483 if (mode & hint_no_buffering) dwFlagsAndAttributes |= FILE_FLAG_NO_BUFFERING;
    -
    2484 if (mode & hint_random_access) dwFlagsAndAttributes |= FILE_FLAG_RANDOM_ACCESS;
    -
    2485 if (mode & hint_sequential_access) dwFlagsAndAttributes |= FILE_FLAG_SEQUENTIAL_SCAN;
    -
    2486
    -
    2487 m_h = CreateFile(filename, dwDesiredAccess, dwShareMode, &sa, dwCreationDisposition, dwFlagsAndAttributes, nullptr);
    -
    2488#else
    -
    2489 int flags = 0;
    -
    2490 if (mode & mode_for_reading) flags |= O_RDONLY;
    -
    2491 if (mode & mode_for_writing) flags |= O_WRONLY;
    -
    2492 if (mode & mode_create) flags |= mode & mode_preserve_existing ? O_CREAT : (O_CREAT | O_EXCL);
    -
    2493 if (mode & hint_write_thru) flags |= O_DSYNC;
    -
    2494 if (mode & hint_no_buffering) flags |= O_RSYNC;
    -
    2495
    -
    2496 m_h = open(filename, flags, DEFFILEMODE);
    -
    2497#endif
    -
    2498 if (m_h != invalid_handle) {
    -
    2499 m_state = state_t::ok;
    -
    2500 if (mode & mode_append)
    -
    2501 seek(0, seek_t::end);
    -
    2502 }
    -
    2503 else
    -
    2504 m_state = state_t::fail;
    -
    2505 }
    +
    2448
    +
    +
    2455 void open(_In_z_ const schar_t* filename, _In_ int mode)
    +
    2456 {
    +
    2457 if (m_h != invalid_handle)
    +
    2458 close();
    +
    2459
    +
    2460#ifdef _WIN32
    +
    2461 DWORD dwDesiredAccess = 0;
    +
    2462 if (mode & mode_for_reading) dwDesiredAccess |= GENERIC_READ;
    +
    2463 if (mode & mode_for_writing) dwDesiredAccess |= GENERIC_WRITE;
    +
    2464 if (mode & mode_for_chmod) dwDesiredAccess |= FILE_WRITE_ATTRIBUTES;
    +
    2465
    +
    2466 DWORD dwShareMode = 0;
    +
    2467 if (mode & share_reading) dwShareMode |= FILE_SHARE_READ;
    +
    2468 if (mode & share_writing) dwShareMode |= FILE_SHARE_WRITE;
    +
    2469 if (mode & share_deleting) dwShareMode |= FILE_SHARE_DELETE;
    +
    2470
    +
    2471 SECURITY_ATTRIBUTES sa = { sizeof(SECURITY_ATTRIBUTES) };
    +
    2472 sa.bInheritHandle = mode & inherit_handle ? true : false;
    +
    2473
    +
    2474 DWORD dwCreationDisposition;
    +
    2475 switch (mode & mode_preserve_existing) {
    +
    2476 case mode_create: dwCreationDisposition = CREATE_ALWAYS; break;
    +
    2477 case mode_preserve_existing: dwCreationDisposition = OPEN_ALWAYS; break;
    +
    2478 case 0: dwCreationDisposition = OPEN_EXISTING; break;
    +
    2479 default: throw std::invalid_argument("invalid mode");
    +
    2480 }
    +
    2481
    +
    2482 DWORD dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL;
    +
    2483 if (mode & hint_write_thru) dwFlagsAndAttributes |= FILE_FLAG_WRITE_THROUGH;
    +
    2484 if (mode & hint_no_buffering) dwFlagsAndAttributes |= FILE_FLAG_NO_BUFFERING;
    +
    2485 if (mode & hint_random_access) dwFlagsAndAttributes |= FILE_FLAG_RANDOM_ACCESS;
    +
    2486 if (mode & hint_sequential_access) dwFlagsAndAttributes |= FILE_FLAG_SEQUENTIAL_SCAN;
    +
    2487
    +
    2488 m_h = CreateFile(filename, dwDesiredAccess, dwShareMode, &sa, dwCreationDisposition, dwFlagsAndAttributes, nullptr);
    +
    2489#else
    +
    2490 int flags = 0;
    +
    2491 switch (mode & (mode_for_reading | mode_for_writing)) {
    +
    2492 case mode_for_reading: flags |= O_RDONLY; break;
    +
    2493 case mode_for_writing: flags |= O_WRONLY; break;
    +
    2494 case mode_for_reading | mode_for_writing: flags |= O_RDWR; break;
    +
    2495 }
    +
    2496 if (mode & mode_create) flags |= mode & mode_preserve_existing ? O_CREAT : (O_CREAT | O_EXCL);
    +
    2497 if (mode & hint_write_thru) flags |= O_DSYNC;
    +
    2498#ifndef __APPLE__
    +
    2499 if (mode & hint_no_buffering) flags |= O_RSYNC;
    +
    2500#endif
    +
    2501
    +
    2502 m_h = ::open(filename, flags, DEFFILEMODE);
    +
    2503#endif
    +
    2504 if (m_h != invalid_handle) {
    +
    2505 m_state = state_t::ok;
    +
    2506 if (mode & mode_append)
    +
    2507 seek(0, seek_t::end);
    +
    2508 }
    +
    2509 else
    +
    2510 m_state = state_t::fail;
    +
    2511 }
    -
    2506
    -
    -
    2507 virtual fpos_t seek(_In_ foff_t offset, _In_ seek_t how = seek_t::beg)
    -
    2508 {
    -
    2509#ifdef _WIN32
    -
    2510 LARGE_INTEGER li;
    -
    2511 li.QuadPart = offset;
    -
    2512 li.LowPart = SetFilePointer(m_h, li.LowPart, &li.HighPart, static_cast<DWORD>(how));
    -
    2513 if (li.LowPart != 0xFFFFFFFF || GetLastError() == NO_ERROR) {
    -
    2514 m_state = state_t::ok;
    -
    2515 return li.QuadPart;
    -
    2516 }
    -
    2517#else
    -
    2518 off64_t result = lseek64(m_h, offset, how);
    -
    2519 if (result >= 0) {
    +
    2512
    +
    +
    2513 virtual fpos_t seek(_In_ foff_t offset, _In_ seek_t how = seek_t::beg)
    +
    2514 {
    +
    2515#ifdef _WIN32
    +
    2516 LARGE_INTEGER li;
    +
    2517 li.QuadPart = offset;
    +
    2518 li.LowPart = SetFilePointer(m_h, li.LowPart, &li.HighPart, static_cast<DWORD>(how));
    +
    2519 if (li.LowPart != 0xFFFFFFFF || GetLastError() == NO_ERROR) {
    2520 m_state = state_t::ok;
    -
    2521 return result;
    +
    2521 return li.QuadPart;
    2522 }
    -
    2523#endif
    -
    2524 m_state = state_t::fail;
    -
    2525 return fpos_max;
    -
    2526 }
    +
    2523#else
    +
    2524 off64_t result = lseek64(m_h, offset, static_cast<int>(how));
    +
    2525 if (result >= 0) {
    +
    2526 m_state = state_t::ok;
    +
    2527 return result;
    +
    2528 }
    +
    2529#endif
    +
    2530 m_state = state_t::fail;
    +
    2531 return fpos_max;
    +
    2532 }
    -
    2527
    -
    -
    2528 virtual fpos_t tell() const
    -
    2529 {
    -
    2530 if (m_h != invalid_handle) {
    -
    2531#ifdef _WIN32
    -
    2532 LARGE_INTEGER li;
    -
    2533 li.QuadPart = 0;
    -
    2534 li.LowPart = SetFilePointer(m_h, 0, &li.HighPart, FILE_CURRENT);
    -
    2535 if (li.LowPart != 0xFFFFFFFF || GetLastError() == NO_ERROR)
    -
    2536 return li.QuadPart;
    -
    2537#else
    -
    2538 off64_t result = lseek64(m_h, 0, SEEK_CUR);
    -
    2539 if (result >= 0)
    -
    2540 return result;
    -
    2541#endif
    -
    2542 }
    -
    2543 return fpos_max;
    -
    2544 }
    +
    2533
    +
    +
    2534 virtual fpos_t tell() const
    +
    2535 {
    +
    2536 if (m_h != invalid_handle) {
    +
    2537#ifdef _WIN32
    +
    2538 LARGE_INTEGER li;
    +
    2539 li.QuadPart = 0;
    +
    2540 li.LowPart = SetFilePointer(m_h, 0, &li.HighPart, FILE_CURRENT);
    +
    2541 if (li.LowPart != 0xFFFFFFFF || GetLastError() == NO_ERROR)
    +
    2542 return li.QuadPart;
    +
    2543#else
    +
    2544 off64_t result = lseek64(m_h, 0, SEEK_CUR);
    +
    2545 if (result >= 0)
    +
    2546 return result;
    +
    2547#endif
    +
    2548 }
    +
    2549 return fpos_max;
    +
    2550 }
    -
    2545
    -
    -
    2546 virtual void lock(_In_ fpos_t offset, _In_ fsize_t length)
    -
    2547 {
    -
    2548#ifdef _WIN32
    -
    2549 LARGE_INTEGER liOffset;
    -
    2550 LARGE_INTEGER liSize;
    -
    2551 liOffset.QuadPart = offset;
    -
    2552 liSize.QuadPart = length;
    -
    2553 if (LockFile(m_h, liOffset.LowPart, liOffset.HighPart, liSize.LowPart, liSize.HighPart)) {
    -
    2554 m_state = state_t::ok;
    -
    2555 return;
    -
    2556 }
    -
    2557#else
    -
    2558 off64_t orig = lseek64(m_h, 0, SEEK_CUR);
    -
    2559 if (orig >= 0) {
    -
    2560 m_state = lseek64(m_h, offset, SEEK_SET) >= 0 && lockf64(m_h, F_LOCK, length) >= 0 ? state_t::ok : state_t::fail;
    -
    2561 lseek64(m_h, orig, SEEK_SET);
    -
    2562 m_state = state_t::ok;
    -
    2563 return;
    -
    2564 }
    -
    2565#endif
    -
    2566 m_state = state_t::fail;
    -
    2567 }
    +
    2551
    +
    +
    2552 virtual void lock(_In_ fpos_t offset, _In_ fsize_t length)
    +
    2553 {
    +
    2554#ifdef _WIN32
    +
    2555 LARGE_INTEGER liOffset;
    +
    2556 LARGE_INTEGER liSize;
    +
    2557 liOffset.QuadPart = offset;
    +
    2558 liSize.QuadPart = length;
    +
    2559 if (LockFile(m_h, liOffset.LowPart, liOffset.HighPart, liSize.LowPart, liSize.HighPart)) {
    +
    2560 m_state = state_t::ok;
    +
    2561 return;
    +
    2562 }
    +
    2563#else
    +
    2564 off64_t orig = lseek64(m_h, 0, SEEK_CUR);
    +
    2565 if (orig >= 0) {
    +
    2566 m_state = lseek64(m_h, offset, SEEK_SET) >= 0 && lockf64(m_h, F_LOCK, length) >= 0 ? state_t::ok : state_t::fail;
    +
    2567 lseek64(m_h, orig, SEEK_SET);
    +
    2568 m_state = state_t::ok;
    +
    2569 return;
    +
    2570 }
    +
    2571#endif
    +
    2572 m_state = state_t::fail;
    +
    2573 }
    -
    2568
    -
    -
    2569 virtual void unlock(_In_ fpos_t offset, _In_ fsize_t length)
    -
    2570 {
    -
    2571#ifdef _WIN32
    -
    2572 LARGE_INTEGER liOffset;
    -
    2573 LARGE_INTEGER liSize;
    -
    2574 liOffset.QuadPart = offset;
    -
    2575 liSize.QuadPart = length;
    -
    2576 if (UnlockFile(m_h, liOffset.LowPart, liOffset.HighPart, liSize.LowPart, liSize.HighPart)) {
    -
    2577 m_state = state_t::ok;
    -
    2578 return;
    -
    2579 }
    -
    2580#else
    -
    2581 off64_t orig = lseek64(m_h, 0, SEEK_CUR);
    -
    2582 if (orig >= 0) {
    -
    2583 if (lseek64(m_h, offset, SEEK_SET) >= 0 && lockf64(m_h, F_ULOCK, length) >= 0) {
    -
    2584 lseek64(m_h, orig, SEEK_SET);
    -
    2585 m_state = state_t::ok;
    -
    2586 return;
    -
    2587 }
    -
    2588 lseek64(m_h, orig, SEEK_SET);
    -
    2589 }
    -
    2590#endif
    -
    2591 m_state = state_t::fail;
    -
    2592 }
    +
    2574
    +
    +
    2575 virtual void unlock(_In_ fpos_t offset, _In_ fsize_t length)
    +
    2576 {
    +
    2577#ifdef _WIN32
    +
    2578 LARGE_INTEGER liOffset;
    +
    2579 LARGE_INTEGER liSize;
    +
    2580 liOffset.QuadPart = offset;
    +
    2581 liSize.QuadPart = length;
    +
    2582 if (UnlockFile(m_h, liOffset.LowPart, liOffset.HighPart, liSize.LowPart, liSize.HighPart)) {
    +
    2583 m_state = state_t::ok;
    +
    2584 return;
    +
    2585 }
    +
    2586#else
    +
    2587 off64_t orig = lseek64(m_h, 0, SEEK_CUR);
    +
    2588 if (orig >= 0) {
    +
    2589 if (lseek64(m_h, offset, SEEK_SET) >= 0 && lockf64(m_h, F_ULOCK, length) >= 0) {
    +
    2590 lseek64(m_h, orig, SEEK_SET);
    +
    2591 m_state = state_t::ok;
    +
    2592 return;
    +
    2593 }
    +
    2594 lseek64(m_h, orig, SEEK_SET);
    +
    2595 }
    +
    2596#endif
    +
    2597 m_state = state_t::fail;
    +
    2598 }
    -
    2593
    -
    -
    2594 virtual fsize_t size()
    -
    2595 {
    -
    2596#ifdef _WIN32
    -
    2597 LARGE_INTEGER li;
    -
    2598 li.LowPart = GetFileSize(m_h, (LPDWORD)&li.HighPart);
    -
    2599 if (li.LowPart == 0xFFFFFFFF && GetLastError() != NO_ERROR)
    -
    2600 li.QuadPart = -1;
    -
    2601 return li.QuadPart;
    -
    2602#else
    -
    2603 off64_t length = -1, orig = lseek64(m_h, 0, SEEK_CUR);
    -
    2604 if (orig >= 0) {
    -
    2605 length = lseek64(m_h, 0, SEEK_END);
    -
    2606 lseek64(m_h, orig, SEEK_SET);
    -
    2607 }
    -
    2608 return length;
    -
    2609#endif
    -
    2610 }
    +
    2599
    +
    +
    2600 virtual fsize_t size()
    +
    2601 {
    +
    2602#ifdef _WIN32
    +
    2603 LARGE_INTEGER li;
    +
    2604 li.LowPart = GetFileSize(m_h, (LPDWORD)&li.HighPart);
    +
    2605 if (li.LowPart == 0xFFFFFFFF && GetLastError() != NO_ERROR)
    +
    2606 li.QuadPart = -1;
    +
    2607 return li.QuadPart;
    +
    2608#else
    +
    2609 off64_t length = -1, orig = lseek64(m_h, 0, SEEK_CUR);
    +
    2610 if (orig >= 0) {
    +
    2611 length = lseek64(m_h, 0, SEEK_END);
    +
    2612 lseek64(m_h, orig, SEEK_SET);
    +
    2613 }
    +
    2614 return length;
    +
    2615#endif
    +
    2616 }
    -
    2611
    -
    -
    2612 virtual void truncate()
    -
    2613 {
    -
    2614#ifdef _WIN32
    -
    2615 if (SetEndOfFile(m_h)) {
    -
    2616 m_state = state_t::ok;
    -
    2617 return;
    -
    2618 }
    -
    2619#else
    -
    2620 off64_t length = lseek64(m_h, 0, SEEK_CUR);
    -
    2621 if (length >= 0 && ftruncate64(m_h, length) >= 0) {
    +
    2617
    +
    +
    2618 virtual void truncate()
    +
    2619 {
    +
    2620#ifdef _WIN32
    +
    2621 if (SetEndOfFile(m_h)) {
    2622 m_state = state_t::ok;
    2623 return;
    2624 }
    -
    2625#endif
    -
    2626 m_state = state_t::fail;
    -
    2627 }
    +
    2625#else
    +
    2626 off64_t length = lseek64(m_h, 0, SEEK_CUR);
    +
    2627 if (length >= 0 && ftruncate64(m_h, length) >= 0) {
    +
    2628 m_state = state_t::ok;
    +
    2629 return;
    +
    2630 }
    +
    2631#endif
    +
    2632 m_state = state_t::fail;
    +
    2633 }
    -
    2628
    -
    2629#ifdef _WIN32
    -
    2630 static inline time_point ft2tp(_In_ const FILETIME& ft)
    -
    2631 {
    -
    2632#if _HAS_CXX20
    -
    2633 uint64_t t = (static_cast<int64_t>(ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
    -
    2634#else
    -
    2635 uint64_t t = ((static_cast<int64_t>(ft.dwHighDateTime) << 32) | ft.dwLowDateTime) - 116444736000000000ll;
    -
    2636#endif
    -
    2637 return time_point(time_point::duration(t));
    -
    2638 }
    -
    2639
    -
    2640 static inline void tp2ft(_In_ time_point tp, _Out_ FILETIME& ft)
    -
    2641 {
    -
    2642#if _HAS_CXX20
    -
    2643 uint64_t t = tp.time_since_epoch().count();
    -
    2644#else
    -
    2645 uint64_t t = tp.time_since_epoch().count() + 116444736000000000ll;
    -
    2646#endif
    -
    2647 ft.dwHighDateTime = static_cast<DWORD>((t >> 32) & 0xffffffff);
    -
    2648 ft.dwLowDateTime = static_cast<DWORD>(t & 0xffffffff);
    -
    2649 }
    -
    2650#endif
    -
    2651
    -
    -
    2652 virtual time_point ctime() const
    -
    2653 {
    -
    2654#ifdef _WIN32
    -
    2655 FILETIME ft;
    -
    2656 if (GetFileTime(m_h, &ft, nullptr, nullptr))
    -
    2657 return ft2tp(ft);
    -
    2658#endif
    -
    2659 return time_point::min();
    -
    2660 }
    +
    2634
    +
    2635#ifdef _WIN32
    +
    2636 static inline time_point ft2tp(_In_ const FILETIME& ft)
    +
    2637 {
    +
    2638#if _HAS_CXX20
    +
    2639 uint64_t t = (static_cast<int64_t>(ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
    +
    2640#else
    +
    2641 uint64_t t = ((static_cast<int64_t>(ft.dwHighDateTime) << 32) | ft.dwLowDateTime) - 116444736000000000ll;
    +
    2642#endif
    +
    2643 return time_point(time_point::duration(t));
    +
    2644 }
    +
    2645
    +
    2646 static inline void tp2ft(_In_ time_point tp, _Out_ FILETIME& ft)
    +
    2647 {
    +
    2648#if _HAS_CXX20
    +
    2649 uint64_t t = tp.time_since_epoch().count();
    +
    2650#else
    +
    2651 uint64_t t = tp.time_since_epoch().count() + 116444736000000000ll;
    +
    2652#endif
    +
    2653 ft.dwHighDateTime = static_cast<DWORD>((t >> 32) & 0xffffffff);
    +
    2654 ft.dwLowDateTime = static_cast<DWORD>(t & 0xffffffff);
    +
    2655 }
    +
    2656#endif
    +
    2657
    +
    +
    2658 virtual time_point ctime() const
    +
    2659 {
    +
    2660#ifdef _WIN32
    +
    2661 FILETIME ft;
    +
    2662 if (GetFileTime(m_h, &ft, nullptr, nullptr))
    +
    2663 return ft2tp(ft);
    +
    2664#endif
    +
    2665 return time_point::min();
    +
    2666 }
    -
    2661
    -
    -
    2662 virtual time_point atime() const
    -
    2663 {
    -
    2664#ifdef _WIN32
    -
    2665 FILETIME ft;
    -
    2666 if (GetFileTime(m_h, nullptr, &ft, nullptr))
    -
    2667 return ft2tp(ft);
    -
    2668#else
    -
    2669 struct stat buf;
    -
    2670 if (fstat(m_h, &buf) >= 0);
    -
    2671 return time_point::from_time_t(buf.st_atim);
    -
    2672#endif
    -
    2673 return time_point::min();
    -
    2674 }
    +
    2667
    +
    +
    2668 virtual time_point atime() const
    +
    2669 {
    +
    2670#ifdef _WIN32
    +
    2671 FILETIME ft;
    +
    2672 if (GetFileTime(m_h, nullptr, &ft, nullptr))
    +
    2673 return ft2tp(ft);
    +
    2674#else
    +
    2675 struct stat buf;
    +
    2676 if (fstat(m_h, &buf) >= 0)
    +
    2677 return clock::from_time_t(buf.st_atime);
    +
    2678#endif
    +
    2679 return time_point::min();
    +
    2680 }
    -
    2675
    -
    -
    2676 virtual time_point mtime() const
    -
    2677 {
    -
    2678#ifdef _WIN32
    -
    2679 FILETIME ft;
    -
    2680 if (GetFileTime(m_h, nullptr, nullptr, &ft))
    -
    2681 return ft2tp(ft);
    -
    2682#else
    -
    2683 struct stat buf;
    -
    2684 if (fstat(m_h, &buf) >= 0)
    -
    2685 return time_point::from_time_t(buf.st_mtim);
    -
    2686#endif
    -
    2687 return time_point::min();
    -
    2688 }
    +
    2681
    +
    +
    2682 virtual time_point mtime() const
    +
    2683 {
    +
    2684#ifdef _WIN32
    +
    2685 FILETIME ft;
    +
    2686 if (GetFileTime(m_h, nullptr, nullptr, &ft))
    +
    2687 return ft2tp(ft);
    +
    2688#else
    +
    2689 struct stat buf;
    +
    2690 if (fstat(m_h, &buf) >= 0)
    +
    2691 return clock::from_time_t(buf.st_mtime);
    +
    2692#endif
    +
    2693 return time_point::min();
    +
    2694 }
    -
    2689
    -
    -
    2690 virtual void set_ctime(time_point date)
    -
    2691 {
    -
    2692 assert(m_h != invalid_handle);
    -
    2693#ifdef _WIN32
    -
    2694 FILETIME ft;
    -
    2695 tp2ft(date, ft);
    -
    2696 if (SetFileTime(m_h, &ft, nullptr, nullptr))
    -
    2697 return;
    -
    2698#endif
    -
    2699 throw std::runtime_error("failed to set file ctime");
    -
    2700 }
    +
    2695
    +
    +
    2696 virtual void set_ctime(time_point date)
    +
    2697 {
    +
    2698 assert(m_h != invalid_handle);
    +
    2699#ifdef _WIN32
    +
    2700 FILETIME ft;
    +
    2701 tp2ft(date, ft);
    +
    2702 if (SetFileTime(m_h, &ft, nullptr, nullptr))
    +
    2703 return;
    +
    2704#endif
    +
    2705 throw std::runtime_error("failed to set file ctime");
    +
    2706 }
    -
    2701
    -
    -
    2702 virtual void set_atime(time_point date)
    -
    2703 {
    -
    2704 assert(m_h != invalid_handle);
    -
    2705#ifdef _WIN32
    -
    2706 FILETIME ft;
    -
    2707 tp2ft(date, ft);
    -
    2708 if (SetFileTime(m_h, nullptr, &ft, nullptr))
    -
    2709 return;
    -
    2710#else
    -
    2711 struct timespec ts[2];
    -
    2712 ts[0].tv_sec = date;
    -
    2713 ts[1].tv_nsec = UTIME_OMIT;
    -
    2714 if (futimens(m_h, ts) >= 0)
    +
    2707
    +
    +
    2708 virtual void set_atime(time_point date)
    +
    2709 {
    +
    2710 assert(m_h != invalid_handle);
    +
    2711#ifdef _WIN32
    +
    2712 FILETIME ft;
    +
    2713 tp2ft(date, ft);
    +
    2714 if (SetFileTime(m_h, nullptr, &ft, nullptr))
    2715 return;
    -
    2716#endif
    -
    2717 throw std::runtime_error("failed to set file atime");
    -
    2718 }
    +
    2716#else
    +
    2717 struct timespec ts[2] = {
    +
    2718 { date.time_since_epoch().count(), 0 },
    +
    2719 { 0, UTIME_OMIT },
    +
    2720 };
    +
    2721 if (futimens(m_h, ts) >= 0)
    +
    2722 return;
    +
    2723#endif
    +
    2724 throw std::runtime_error("failed to set file atime");
    +
    2725 }
    -
    2719
    -
    -
    2720 virtual void set_mtime(time_point date)
    -
    2721 {
    -
    2722#ifdef _WIN32
    -
    2723 FILETIME ft;
    -
    2724 tp2ft(date, ft);
    -
    2725 if (SetFileTime(m_h, nullptr, nullptr, &ft))
    -
    2726 return;
    -
    2727#else
    -
    2728 struct timespec ts[2];
    -
    2729 ts[0].tv_nsec = UTIME_OMIT;
    -
    2730 ts[1].tv_sec = date;
    -
    2731 if (futimens(m_h, ts) >= 0)
    -
    2732 return;
    -
    2733#endif
    -
    2734 throw std::runtime_error("failed to set file mtime");
    -
    2735 }
    +
    2726
    +
    +
    2727 virtual void set_mtime(time_point date)
    +
    2728 {
    +
    2729#ifdef _WIN32
    +
    2730 FILETIME ft;
    +
    2731 tp2ft(date, ft);
    +
    2732 if (SetFileTime(m_h, nullptr, nullptr, &ft))
    +
    2733 return;
    +
    2734#else
    +
    2735 struct timespec ts[2] = {
    +
    2736 { 0, UTIME_OMIT },
    +
    2737 { date.time_since_epoch().count(), 0 },
    +
    2738 };
    +
    2739 if (futimens(m_h, ts) >= 0)
    +
    2740 return;
    +
    2741#endif
    +
    2742 throw std::runtime_error("failed to set file mtime");
    +
    2743 }
    -
    2736 };
    +
    2744 };
    -
    2737#pragma warning(pop)
    -
    2738
    -
    -
    2742 class cached_file : public cache
    -
    2743 {
    -
    2744 public:
    -
    2745 cached_file(_In_opt_ sys_handle h = invalid_handle, _In_ state_t state = state_t::ok, _In_ size_t cache_size = default_cache_size) :
    -
    2746 cache(cache_size),
    -
    2747 m_source(h, state)
    -
    2748 {
    -
    2749 init(m_source);
    -
    2750 }
    -
    2751
    -
    -
    2759 cached_file(_In_z_ const schar_t* filename, _In_ int mode, _In_ size_t cache_size = default_cache_size) :
    -
    2760 cache(cache_size),
    -
    2761 m_source(filename, mode & mode_for_writing ? mode | mode_for_reading : mode)
    -
    2762 {
    -
    2763 init(m_source);
    -
    2764 }
    +
    2745#pragma warning(pop)
    +
    2746
    +
    +
    2750 class cached_file : public cache
    +
    2751 {
    +
    2752 public:
    +
    2753 cached_file(_In_opt_ sys_handle h = invalid_handle, _In_ state_t state = state_t::ok, _In_ size_t cache_size = default_cache_size) :
    +
    2754 cache(cache_size),
    +
    2755 m_source(h, state)
    +
    2756 {
    +
    2757 init(m_source);
    +
    2758 }
    +
    2759
    +
    +
    2767 cached_file(_In_z_ const schar_t* filename, _In_ int mode, _In_ size_t cache_size = default_cache_size) :
    +
    2768 cache(cache_size),
    +
    2769 m_source(filename, mode & mode_for_writing ? mode | mode_for_reading : mode)
    +
    2770 {
    +
    2771 init(m_source);
    +
    2772 }
    -
    2765
    -
    2766 virtual ~cached_file()
    -
    2767 {
    -
    2768 done();
    -
    2769 }
    -
    2770
    -
    -
    2778 void open(_In_z_ const schar_t* filename, _In_ int mode)
    -
    2779 {
    -
    2780 invalidate_cache();
    -
    2781 if (!ok()) _Unlikely_{
    -
    2782 m_state = state_t::fail;
    -
    2783 return;
    -
    2784 }
    -
    2785 m_source.open(filename, mode & mode_for_writing ? mode | mode_for_reading : mode);
    -
    2786 if (m_source.ok()) {
    -
    2787#if SET_FILE_OP_TIMES
    -
    2788 m_atime = m_source.atime();
    -
    2789 m_mtime = m_source.mtime();
    -
    2790#endif
    -
    2791 m_offset = m_source.tell();
    -
    2792 m_state = state_t::ok;
    -
    2793 return;
    -
    2794 }
    -
    2795 m_state = state_t::fail;
    -
    2796 }
    +
    2773
    +
    2774 virtual ~cached_file()
    +
    2775 {
    +
    2776 done();
    +
    2777 }
    +
    2778
    +
    +
    2785 void open(_In_z_ const schar_t* filename, _In_ int mode)
    +
    2786 {
    +
    2787 invalidate_cache();
    +
    2788 if (!ok()) _Unlikely_{
    +
    2789 m_state = state_t::fail;
    +
    2790 return;
    +
    2791 }
    +
    2792 m_source.open(filename, mode & mode_for_writing ? mode | mode_for_reading : mode);
    +
    2793 if (m_source.ok()) {
    +
    2794#if SET_FILE_OP_TIMES
    +
    2795 m_atime = m_source.atime();
    +
    2796 m_mtime = m_source.mtime();
    +
    2797#endif
    +
    2798 m_offset = m_source.tell();
    +
    2799 m_state = state_t::ok;
    +
    2800 return;
    +
    2801 }
    +
    2802 m_state = state_t::fail;
    +
    2803 }
    -
    2797
    -
    2798 protected:
    -
    2799 file m_source;
    -
    2800 };
    +
    2804
    +
    2805 protected:
    +
    2806 file m_source;
    +
    2807 };
    -
    2801
    -
    - -
    2806 {
    -
    2807 public:
    -
    2808 memory_file(_In_ state_t state = state_t::ok) :
    -
    2809 basic(state),
    -
    2810 m_data(nullptr),
    -
    2811 m_offset(0),
    -
    2812 m_size(0),
    -
    2813 m_reserved(0),
    -
    2814 m_manage(true)
    -
    2815 {
    -
    2816#if SET_FILE_OP_TIMES
    -
    2817 m_ctime = m_atime = m_mtime = time_point::now();
    -
    2818#endif
    -
    2819 }
    -
    2820
    -
    -
    2827 memory_file(_In_ size_t size, _In_ state_t state = state_t::ok) :
    -
    2828 basic(state),
    -
    2829 m_data(reinterpret_cast<uint8_t*>(malloc(size))),
    -
    2830 m_offset(0),
    -
    2831 m_size(0),
    - -
    2833 m_manage(true)
    -
    2834 {
    -
    2835 if (!m_data)
    -
    2836 throw std::bad_alloc();
    -
    2837#if SET_FILE_OP_TIMES
    -
    2838 m_ctime = m_atime = m_mtime = time_point::now();
    -
    2839#endif
    -
    2840 }
    +
    2808
    +
    + +
    2813 {
    +
    2814 public:
    +
    2815 memory_file(_In_ state_t state = state_t::ok) :
    +
    2816 basic(state),
    +
    2817 m_data(nullptr),
    +
    2818 m_offset(0),
    +
    2819 m_size(0),
    +
    2820 m_reserved(0),
    +
    2821 m_manage(true)
    +
    2822 {
    +
    2823#if SET_FILE_OP_TIMES
    +
    2824 m_ctime = m_atime = m_mtime = time_point::now();
    +
    2825#endif
    +
    2826 }
    +
    2827
    +
    +
    2834 memory_file(_In_ size_t size, _In_ state_t state = state_t::ok) :
    +
    2835 basic(state),
    +
    2836 m_data(reinterpret_cast<uint8_t*>(malloc(size))),
    +
    2837 m_offset(0),
    +
    2838 m_size(0),
    + +
    2840 m_manage(true)
    +
    2841 {
    +
    2842 if (!m_data)
    +
    2843 throw std::bad_alloc();
    +
    2844#if SET_FILE_OP_TIMES
    +
    2845 m_ctime = m_atime = m_mtime = time_point::now();
    +
    2846#endif
    +
    2847 }
    -
    2841
    -
    -
    2851 memory_file(_Inout_ void* data, _In_ size_t size, _In_ size_t reserved, _In_ bool manage = false, _In_ state_t state = state_t::ok) :
    -
    2852 basic(state),
    -
    2853 m_data(reinterpret_cast<uint8_t*>(data)),
    -
    2854 m_offset(0),
    -
    2855 m_size(size),
    -
    2856 m_reserved(reserved),
    -
    2857 m_manage(manage)
    -
    2858 {
    -
    2859 assert(data || !size);
    -
    2860 assert(reserved >= size);
    -
    2861#if SET_FILE_OP_TIMES
    -
    2862 m_ctime = m_atime = m_mtime = time_point::now();
    -
    2863#endif
    -
    2864 }
    +
    2848
    +
    +
    2858 memory_file(_Inout_ void* data, _In_ size_t size, _In_ size_t reserved, _In_ bool manage = false, _In_ state_t state = state_t::ok) :
    +
    2859 basic(state),
    +
    2860 m_data(reinterpret_cast<uint8_t*>(data)),
    +
    2861 m_offset(0),
    +
    2862 m_size(size),
    +
    2863 m_reserved(reserved),
    +
    2864 m_manage(manage)
    +
    2865 {
    +
    2866 assert(data || !size);
    +
    2867 assert(reserved >= size);
    +
    2868#if SET_FILE_OP_TIMES
    +
    2869 m_ctime = m_atime = m_mtime = time_point::now();
    +
    2870#endif
    +
    2871 }
    -
    2865
    -
    -
    2874 memory_file(_Inout_ void* data, _In_ size_t size, _In_ bool manage = false, _In_ state_t state = state_t::ok) :
    -
    2875 memory_file(data, size, size, manage, state)
    -
    2876 {}
    +
    2872
    +
    +
    2881 memory_file(_Inout_ void* data, _In_ size_t size, _In_ bool manage = false, _In_ state_t state = state_t::ok) :
    +
    2882 memory_file(data, size, size, manage, state)
    +
    2883 {}
    -
    2877
    -
    -
    2884 memory_file(_In_z_ const schar_t* filename, _In_ int mode) : memory_file()
    -
    2885 {
    -
    2886 load(filename, mode);
    -
    2887 }
    +
    2884
    +
    +
    2891 memory_file(_In_z_ const schar_t* filename, _In_ int mode) : memory_file()
    +
    2892 {
    +
    2893 load(filename, mode);
    +
    2894 }
    -
    2888
    -
    2889 virtual ~memory_file()
    -
    2890 {
    -
    2891 if (m_manage && m_data)
    -
    2892 free(m_data);
    -
    2893 }
    -
    2894
    -
    -
    2901 void reserve(_In_ size_t required, _In_ bool tight = false) noexcept
    -
    2902 {
    -
    2903 if (required <= m_reserved && (!tight || required >= m_reserved)) {
    -
    2904 m_state = state_t::ok;
    -
    2905 return;
    -
    2906 }
    -
    2907 if (!m_manage) {
    -
    2908 m_state = state_t::fail;
    -
    2909 return;
    -
    2910 }
    -
    2911 size_t reserved = tight ? required : ((required + required / 4 + (default_block_size - 1)) / default_block_size) * default_block_size;
    -
    2912 auto data = reinterpret_cast<uint8_t*>(realloc(m_data, reserved));
    -
    2913 if (!data && reserved) _Unlikely_ {
    -
    2914 m_state = state_t::fail;
    -
    2915 return;
    -
    2916 }
    -
    2917 m_data = data;
    -
    2918 if (reserved < m_size)
    -
    2919 m_size = reserved;
    -
    2920 m_reserved = reserved;
    -
    2921 m_state = state_t::ok;
    -
    2922 }
    +
    2895
    +
    2896 virtual ~memory_file()
    +
    2897 {
    +
    2898 if (m_manage && m_data)
    +
    2899 free(m_data);
    +
    2900 }
    +
    2901
    +
    +
    2908 void reserve(_In_ size_t required, _In_ bool tight = false) noexcept
    +
    2909 {
    +
    2910 if (required <= m_reserved && (!tight || required >= m_reserved)) {
    +
    2911 m_state = state_t::ok;
    +
    2912 return;
    +
    2913 }
    +
    2914 if (!m_manage) {
    +
    2915 m_state = state_t::fail;
    +
    2916 return;
    +
    2917 }
    +
    2918 size_t reserved = tight ? required : ((required + required / 4 + (default_block_size - 1)) / default_block_size) * default_block_size;
    +
    2919 auto data = reinterpret_cast<uint8_t*>(realloc(m_data, reserved));
    +
    2920 if (!data && reserved) _Unlikely_ {
    +
    2921 m_state = state_t::fail;
    +
    2922 return;
    +
    2923 }
    +
    2924 m_data = data;
    +
    2925 if (reserved < m_size)
    +
    2926 m_size = reserved;
    +
    2927 m_reserved = reserved;
    +
    2928 m_state = state_t::ok;
    +
    2929 }
    -
    2923
    -
    -
    2930 void load(_In_z_ const schar_t* filename, _In_ int mode)
    -
    2931 {
    -
    2932 file f(filename, (mode & ~hint_random_access) | mode_for_reading | hint_sequential_access);
    -
    2933 if (!f.ok()) {
    -
    2934 m_state = state_t::fail;
    -
    2935 return;
    -
    2936 }
    -
    2937 fsize_t size = f.size();
    -
    2938 if (size > SIZE_MAX) {
    -
    2939 m_state = state_t::fail;
    -
    2940 return;
    -
    2941 }
    -
    2942 reserve(static_cast<size_t>(size), true);
    -
    2943 if (!ok()) _Unlikely_ {
    -
    2944 return;
    -
    2945 }
    -
    2946 m_offset = m_size = 0;
    -
    2947 write_stream(f);
    -
    2948 if (ok())
    -
    2949 m_offset = 0;
    -
    2950#if SET_FILE_OP_TIMES
    -
    2951 m_ctime = f.ctime();
    -
    2952 m_atime = f.atime();
    -
    2953 m_mtime = f.mtime();
    -
    2954#endif
    -
    2955 }
    +
    2930
    +
    +
    2937 void load(_In_z_ const schar_t* filename, _In_ int mode)
    +
    2938 {
    +
    2939 file f(filename, (mode & ~hint_random_access) | mode_for_reading | hint_sequential_access);
    +
    2940 if (!f.ok()) {
    +
    2941 m_state = state_t::fail;
    +
    2942 return;
    +
    2943 }
    +
    2944 fsize_t size = f.size();
    +
    2945 if (size > SIZE_MAX) {
    +
    2946 m_state = state_t::fail;
    +
    2947 return;
    +
    2948 }
    +
    2949 reserve(static_cast<size_t>(size), true);
    +
    2950 if (!ok()) _Unlikely_ {
    +
    2951 return;
    +
    2952 }
    +
    2953 m_offset = m_size = 0;
    +
    2954 write_stream(f);
    +
    2955 if (ok())
    +
    2956 m_offset = 0;
    +
    2957#if SET_FILE_OP_TIMES
    +
    2958 m_ctime = f.ctime();
    +
    2959 m_atime = f.atime();
    +
    2960 m_mtime = f.mtime();
    +
    2961#endif
    +
    2962 }
    -
    2956
    -
    -
    2963 void save(_In_z_ const schar_t* filename, _In_ int mode)
    -
    2964 {
    -
    2965 file f(filename, (mode & ~hint_random_access) | mode_for_writing | hint_sequential_access);
    -
    2966 if (!f.ok()) {
    -
    2967 m_state = state_t::fail;
    -
    2968 return;
    -
    2969 }
    -
    2970 f.write(m_data, m_size);
    -
    2971 if (!f.ok()) {
    -
    2972 m_state = state_t::fail;
    -
    2973 return;
    -
    2974 }
    -
    2975 f.truncate();
    -
    2976#if SET_FILE_OP_TIMES
    -
    2977 f.set_ctime(m_ctime);
    -
    2978 f.set_atime(m_atime);
    -
    2979 f.set_mtime(m_mtime);
    -
    2980#endif
    +
    2963
    +
    +
    2970 void save(_In_z_ const schar_t* filename, _In_ int mode)
    +
    2971 {
    +
    2972 file f(filename, (mode & ~hint_random_access) | mode_for_writing | hint_sequential_access);
    +
    2973 if (!f.ok()) {
    +
    2974 m_state = state_t::fail;
    +
    2975 return;
    +
    2976 }
    +
    2977 f.write(m_data, m_size);
    +
    2978 if (!f.ok()) {
    +
    2979 m_state = state_t::fail;
    +
    2980 return;
    2981 }
    +
    2982 f.truncate();
    +
    2983#if SET_FILE_OP_TIMES
    +
    2984 f.set_ctime(m_ctime);
    +
    2985 f.set_atime(m_atime);
    +
    2986 f.set_mtime(m_mtime);
    +
    2987#endif
    +
    2988 }
    -
    2982
    -
    2986 inline const void* data() const { return m_data; }
    -
    2987
    -
    -
    2988 virtual _Success_(return != 0 || length == 0) size_t read(
    -
    2989 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
    -
    2990 {
    -
    2991 assert(data || !length);
    -
    2992#if SET_FILE_OP_TIMES
    -
    2993 m_atime = time_point::now();
    -
    2994#endif
    -
    2995 size_t available = m_size - m_offset;
    -
    2996 if (length <= available) {
    -
    2997 memcpy(data, m_data + m_offset, length);
    -
    2998 m_offset += length;
    -
    2999 m_state = state_t::ok;
    -
    3000 return length;
    -
    3001 }
    -
    3002 if (length && !available) {
    -
    3003 m_state = state_t::eof;
    -
    3004 return 0;
    -
    3005 }
    -
    3006 memcpy(data, m_data + m_offset, available);
    -
    3007 m_offset += available;
    -
    3008 m_state = state_t::ok;
    -
    3009 return available;
    -
    3010 }
    +
    2989
    +
    2993 inline const void* data() const { return m_data; }
    +
    2994
    +
    +
    2995 virtual _Success_(return != 0 || length == 0) size_t read(
    +
    2996 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
    +
    2997 {
    +
    2998 assert(data || !length);
    +
    2999#if SET_FILE_OP_TIMES
    +
    3000 m_atime = time_point::now();
    +
    3001#endif
    +
    3002 size_t available = m_size - m_offset;
    +
    3003 if (length <= available) {
    +
    3004 memcpy(data, m_data + m_offset, length);
    +
    3005 m_offset += length;
    +
    3006 m_state = state_t::ok;
    +
    3007 return length;
    +
    3008 }
    +
    3009 if (length && !available) {
    +
    3010 m_state = state_t::eof;
    +
    3011 return 0;
    +
    3012 }
    +
    3013 memcpy(data, m_data + m_offset, available);
    +
    3014 m_offset += available;
    +
    3015 m_state = state_t::ok;
    +
    3016 return available;
    +
    3017 }
    -
    3011
    -
    3026 template <class T>
    -
    - -
    3028 {
    -
    3029#if SET_FILE_OP_TIMES
    -
    3030 m_atime = time_point::now();
    -
    3031#endif
    -
    3032 if (CHECK_STREAM_STATE && !ok()) _Unlikely_ {
    -
    3033 data = 0;
    -
    3034 return *this;
    -
    3035 }
    -
    3036 size_t end_offset = m_offset + sizeof(T);
    -
    3037 if (end_offset <= m_size) {
    -
    3038 data = LE2HE(*reinterpret_cast<T*>(m_data + m_offset));
    -
    3039 m_offset = end_offset;
    -
    3040#if !CHECK_STREAM_STATE
    -
    3041 m_state = state_t::ok;
    -
    3042#endif
    -
    3043 }
    -
    3044 else {
    -
    3045 data = 0;
    -
    3046 m_offset = m_size;
    -
    3047 m_state = state_t::eof;
    -
    3048 }
    -
    3049 return *this;
    -
    3050 }
    +
    3018
    +
    3033 template <class T>
    +
    + +
    3035 {
    +
    3036#if SET_FILE_OP_TIMES
    +
    3037 m_atime = time_point::now();
    +
    3038#endif
    +
    3039 if (CHECK_STREAM_STATE && !ok()) _Unlikely_ {
    +
    3040 data = 0;
    +
    3041 return *this;
    +
    3042 }
    +
    3043 size_t end_offset = m_offset + sizeof(T);
    +
    3044 if (end_offset <= m_size) {
    +
    3045 data = LE2HE(*reinterpret_cast<T*>(m_data + m_offset));
    +
    3046 m_offset = end_offset;
    +
    3047#if !CHECK_STREAM_STATE
    +
    3048 m_state = state_t::ok;
    +
    3049#endif
    +
    3050 }
    +
    3051 else {
    +
    3052 data = 0;
    +
    3053 m_offset = m_size;
    +
    3054 m_state = state_t::eof;
    +
    3055 }
    +
    3056 return *this;
    +
    3057 }
    -
    3051
    -
    3066 template<class _Elem, class _Traits = std::char_traits<_Elem>, class _Ax = std::allocator<_Elem>>
    -
    -
    3067 memory_file& read_str(_Inout_ std::basic_string<_Elem, _Traits, _Ax>&data)
    -
    3068 {
    -
    3069#if SET_FILE_OP_TIMES
    -
    3070 m_atime = time_point::now();
    -
    3071#endif
    -
    3072 if (CHECK_STREAM_STATE && !ok()) _Unlikely_ {
    -
    3073 data.clear();
    -
    3074 return *this;
    -
    3075 }
    -
    3076 size_t end_offset = m_offset + sizeof(uint32_t);
    -
    3077 if (end_offset <= m_size) {
    -
    3078 uint32_t num_chars = LE2HE(*reinterpret_cast<uint32_t*>(m_data + m_offset));
    -
    3079 m_offset = end_offset;
    -
    3080 end_offset = stdex::add(m_offset + stdex::mul(num_chars, sizeof(_Elem)));
    -
    3081 _Elem* start = reinterpret_cast<_Elem*>(m_data + m_offset);
    -
    3082 if (end_offset <= m_size) {
    -
    3083 data.assign(start, start + num_chars);
    -
    3084 m_offset = end_offset;
    -
    3085#if !CHECK_STREAM_STATE
    -
    3086 m_state = state_t::ok;
    -
    3087#endif
    -
    3088 return *this;
    -
    3089 }
    -
    3090 if (end_offset <= m_size)
    -
    3091 data.assign(start, reinterpret_cast<_Elem*>(m_data + m_size));
    -
    3092 }
    -
    3093 m_offset = m_size;
    -
    3094 m_state = state_t::eof;
    -
    3095 return *this;
    -
    3096 }
    +
    3058
    +
    3073 template<class _Elem, class _Traits = std::char_traits<_Elem>, class _Ax = std::allocator<_Elem>>
    +
    +
    3074 memory_file& read_str(_Inout_ std::basic_string<_Elem, _Traits, _Ax>&data)
    +
    3075 {
    +
    3076#if SET_FILE_OP_TIMES
    +
    3077 m_atime = time_point::now();
    +
    3078#endif
    +
    3079 if (CHECK_STREAM_STATE && !ok()) _Unlikely_ {
    +
    3080 data.clear();
    +
    3081 return *this;
    +
    3082 }
    +
    3083 size_t end_offset = m_offset + sizeof(uint32_t);
    +
    3084 if (end_offset <= m_size) {
    +
    3085 uint32_t num_chars = LE2HE(*reinterpret_cast<uint32_t*>(m_data + m_offset));
    +
    3086 m_offset = end_offset;
    +
    3087 end_offset = stdex::add(m_offset, stdex::mul(num_chars, sizeof(_Elem)));
    +
    3088 _Elem* start = reinterpret_cast<_Elem*>(m_data + m_offset);
    +
    3089 if (end_offset <= m_size) {
    +
    3090 data.assign(start, start + num_chars);
    +
    3091 m_offset = end_offset;
    +
    3092#if !CHECK_STREAM_STATE
    +
    3093 m_state = state_t::ok;
    +
    3094#endif
    +
    3095 return *this;
    +
    3096 }
    +
    3097 if (end_offset <= m_size)
    +
    3098 data.assign(start, reinterpret_cast<_Elem*>(m_data + m_size));
    +
    3099 }
    +
    3100 m_offset = m_size;
    +
    3101 m_state = state_t::eof;
    +
    3102 return *this;
    +
    3103 }
    -
    3097
    -
    -
    3098 virtual _Success_(return != 0) size_t write(
    -
    3099 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
    -
    3100 {
    -
    3101 assert(data || !length);
    -
    3102#if SET_FILE_OP_TIMES
    -
    3103 m_atime = m_mtime = time_point::now();
    -
    3104#endif
    -
    3105 size_t end_offset = m_offset + length;
    -
    3106 if (end_offset > m_reserved) {
    -
    3107 reserve(end_offset);
    -
    3108 if (!ok()) _Unlikely_
    -
    3109 return 0;
    -
    3110 }
    -
    3111 memcpy(m_data + m_offset, data, length);
    -
    3112 m_offset = end_offset;
    -
    3113 if (m_offset > m_size)
    -
    3114 m_size = m_offset;
    -
    3115 m_state = state_t::ok;
    -
    3116 return length;
    -
    3117 }
    +
    3104
    +
    +
    3105 virtual _Success_(return != 0) size_t write(
    +
    3106 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
    +
    3107 {
    +
    3108 assert(data || !length);
    +
    3109#if SET_FILE_OP_TIMES
    +
    3110 m_atime = m_mtime = time_point::now();
    +
    3111#endif
    +
    3112 size_t end_offset = m_offset + length;
    +
    3113 if (end_offset > m_reserved) {
    +
    3114 reserve(end_offset);
    +
    3115 if (!ok()) _Unlikely_
    +
    3116 return 0;
    +
    3117 }
    +
    3118 memcpy(m_data + m_offset, data, length);
    +
    3119 m_offset = end_offset;
    +
    3120 if (m_offset > m_size)
    +
    3121 m_size = m_offset;
    +
    3122 m_state = state_t::ok;
    +
    3123 return length;
    +
    3124 }
    -
    3118
    -
    -
    3122 void write_byte(_In_ uint8_t byte, _In_ size_t amount = 1)
    -
    3123 {
    -
    3124#if SET_FILE_OP_TIMES
    -
    3125 m_atime = m_mtime = time_point::now();
    -
    3126#endif
    -
    3127 size_t end_offset = m_offset + amount;
    -
    3128 if (end_offset > m_reserved) {
    -
    3129 reserve(end_offset);
    -
    3130 if (!ok()) _Unlikely_
    -
    3131 return;
    -
    3132 }
    -
    3133 memset(m_data + m_offset, byte, amount);
    -
    3134 m_offset = end_offset;
    -
    3135 if (m_offset > m_size)
    -
    3136 m_size = m_offset;
    -
    3137 m_state = state_t::ok;
    -
    3138 }
    +
    3125
    +
    +
    3129 void write_byte(_In_ uint8_t byte, _In_ size_t amount = 1)
    +
    3130 {
    +
    3131#if SET_FILE_OP_TIMES
    +
    3132 m_atime = m_mtime = time_point::now();
    +
    3133#endif
    +
    3134 size_t end_offset = m_offset + amount;
    +
    3135 if (end_offset > m_reserved) {
    +
    3136 reserve(end_offset);
    +
    3137 if (!ok()) _Unlikely_
    +
    3138 return;
    +
    3139 }
    +
    3140 memset(m_data + m_offset, byte, amount);
    +
    3141 m_offset = end_offset;
    +
    3142 if (m_offset > m_size)
    +
    3143 m_size = m_offset;
    +
    3144 m_state = state_t::ok;
    +
    3145 }
    -
    3139
    -
    3154 template <class T>
    -
    -
    3155 inline memory_file& write_data(const T data)
    -
    3156 {
    -
    3157#if SET_FILE_OP_TIMES
    -
    3158 m_atime = m_mtime = time_point::now();
    -
    3159#endif
    -
    3160 if (CHECK_STREAM_STATE && !ok()) _Unlikely_
    -
    3161 return *this;
    -
    3162 size_t end_offset = m_offset + sizeof(T);
    -
    3163 if (end_offset > m_reserved) {
    -
    3164 reserve(end_offset);
    -
    3165 if (!ok()) _Unlikely_
    -
    3166 return *this;
    -
    3167 }
    -
    3168 (*reinterpret_cast<T*>(m_data + m_offset)) = HE2LE(data);
    -
    3169 m_offset = end_offset;
    -
    3170 if (m_offset > m_size)
    -
    3171 m_size = m_offset;
    -
    3172#if !CHECK_STREAM_STATE
    -
    3173 m_state = state_t::ok;
    -
    3174#endif
    -
    3175 return *this;
    -
    3176 }
    +
    3146
    +
    3161 template <class T>
    +
    +
    3162 inline memory_file& write_data(const T data)
    +
    3163 {
    +
    3164#if SET_FILE_OP_TIMES
    +
    3165 m_atime = m_mtime = time_point::now();
    +
    3166#endif
    +
    3167 if (CHECK_STREAM_STATE && !ok()) _Unlikely_
    +
    3168 return *this;
    +
    3169 size_t end_offset = m_offset + sizeof(T);
    +
    3170 if (end_offset > m_reserved) {
    +
    3171 reserve(end_offset);
    +
    3172 if (!ok()) _Unlikely_
    +
    3173 return *this;
    +
    3174 }
    +
    3175 (*reinterpret_cast<T*>(m_data + m_offset)) = HE2LE(data);
    +
    3176 m_offset = end_offset;
    +
    3177 if (m_offset > m_size)
    +
    3178 m_size = m_offset;
    +
    3179#if !CHECK_STREAM_STATE
    +
    3180 m_state = state_t::ok;
    +
    3181#endif
    +
    3182 return *this;
    +
    3183 }
    -
    3177
    -
    3192 template <class T>
    -
    -
    3193 inline memory_file& write_str(_In_z_ const T * data)
    -
    3194 {
    -
    3195#if SET_FILE_OP_TIMES
    -
    3196 m_atime = m_mtime = time_point::now();
    -
    3197#endif
    -
    3198 if (CHECK_STREAM_STATE && !ok()) _Unlikely_
    -
    3199 return *this;
    -
    3200 size_t num_chars = stdex::strlen(data);
    -
    3201 if (num_chars > UINT32_MAX)
    -
    3202 throw std::invalid_argument("string too long");
    -
    3203 size_t size_chars = num_chars * sizeof(T);
    -
    3204 size_t size = sizeof(uint32_t) + size_chars;
    -
    3205 size_t end_offset = m_offset + size;
    -
    3206 if (end_offset > m_reserved) {
    -
    3207 reserve(end_offset);
    -
    3208 if (!ok()) _Unlikely_
    -
    3209 return *this;
    -
    3210 }
    -
    3211 auto p = tok.m_podatki + m_offset;
    -
    3212 *reinterpret_cast<uint32_t*>(p) = HE2LE((uint32_t)num_chars);
    -
    3213 memcpy(p + sizeof(uint32_t), data, size_chars);
    -
    3214 m_offset = end_offset;
    -
    3215 if (m_offset > m_size)
    -
    3216 m_size = m_offset;
    -
    3217#if !CHECK_STREAM_STATE
    -
    3218 m_state = state_t::ok;
    -
    3219#endif
    -
    3220 return *this;
    -
    3221 }
    +
    3184
    +
    3199 template <class T>
    +
    +
    3200 inline memory_file& write_str(_In_z_ const T * data)
    +
    3201 {
    +
    3202#if SET_FILE_OP_TIMES
    +
    3203 m_atime = m_mtime = time_point::now();
    +
    3204#endif
    +
    3205 if (CHECK_STREAM_STATE && !ok()) _Unlikely_
    +
    3206 return *this;
    +
    3207 size_t num_chars = stdex::strlen(data);
    +
    3208 if (num_chars > UINT32_MAX)
    +
    3209 throw std::invalid_argument("string too long");
    +
    3210 size_t size_chars = num_chars * sizeof(T);
    +
    3211 size_t size = sizeof(uint32_t) + size_chars;
    +
    3212 size_t end_offset = m_offset + size;
    +
    3213 if (end_offset > m_reserved) {
    +
    3214 reserve(end_offset);
    +
    3215 if (!ok()) _Unlikely_
    +
    3216 return *this;
    +
    3217 }
    +
    3218 auto p = m_data + m_offset;
    +
    3219 *reinterpret_cast<uint32_t*>(p) = HE2LE((uint32_t)num_chars);
    +
    3220 memcpy(p + sizeof(uint32_t), data, size_chars);
    +
    3221 m_offset = end_offset;
    +
    3222 if (m_offset > m_size)
    +
    3223 m_size = m_offset;
    +
    3224#if !CHECK_STREAM_STATE
    +
    3225 m_state = state_t::ok;
    +
    3226#endif
    +
    3227 return *this;
    +
    3228 }
    -
    3222
    -
    -
    3228 size_t write_stream(_Inout_ basic & stream, _In_ size_t amount = SIZE_MAX)
    -
    3229 {
    -
    3230#if SET_FILE_OP_TIMES
    -
    3231 m_atime = m_mtime = time_point::now();
    -
    3232#endif
    -
    3233 size_t num_read, dst_offset = m_offset, dst_size = m_offset;
    -
    3234 size_t num_copied = 0, to_write = amount;
    -
    3235 m_state = state_t::ok;
    -
    3236 if (amount != SIZE_MAX) {
    -
    3237 dst_size = stdex::add(dst_size, amount);
    -
    3238 reserve(dst_size);
    -
    3239 if (!ok()) _Unlikely_
    -
    3240 return 0;
    -
    3241 while (to_write) {
    -
    3242 num_read = stream.read(m_data + dst_offset, to_write);
    -
    3243 dst_size = dst_offset += num_read;
    -
    3244 num_copied += num_read;
    -
    3245 to_write -= num_read;
    -
    3246 if (!stream.ok()) {
    -
    3247 if (stream.state() != state_t::eof)
    -
    3248 m_state = state_t::fail;
    -
    3249 break;
    -
    3250 }
    -
    3251 };
    -
    3252 }
    -
    3253 else {
    -
    3254 size_t block_size;
    -
    3255 while (to_write) {
    -
    3256 block_size = std::min(to_write, default_block_size);
    -
    3257 dst_size = stdex::add(dst_size, block_size);
    -
    3258 reserve(dst_size);
    -
    3259 if (!ok()) _Unlikely_
    -
    3260 break;
    -
    3261 num_read = stream.read(m_data + dst_offset, block_size);
    -
    3262 dst_size = dst_offset += num_read;
    -
    3263 num_copied += num_read;
    -
    3264 to_write -= num_read;
    -
    3265 if (!stream.ok()) {
    -
    3266 if (stream.state() != state_t::eof)
    -
    3267 m_state = state_t::fail;
    -
    3268 break;
    -
    3269 }
    -
    3270 };
    -
    3271 }
    -
    3272 m_offset = dst_offset;
    -
    3273 if (m_offset > m_size)
    -
    3274 m_size = m_offset;
    -
    3275 return num_copied;
    -
    3276 }
    +
    3229
    +
    +
    3235 size_t write_stream(_Inout_ basic & stream, _In_ size_t amount = SIZE_MAX)
    +
    3236 {
    +
    3237#if SET_FILE_OP_TIMES
    +
    3238 m_atime = m_mtime = time_point::now();
    +
    3239#endif
    +
    3240 size_t num_read, dst_offset = m_offset, dst_size = m_offset;
    +
    3241 size_t num_copied = 0, to_write = amount;
    +
    3242 m_state = state_t::ok;
    +
    3243 if (amount != SIZE_MAX) {
    +
    3244 dst_size = stdex::add(dst_size, amount);
    +
    3245 reserve(dst_size);
    +
    3246 if (!ok()) _Unlikely_
    +
    3247 return 0;
    +
    3248 while (to_write) {
    +
    3249 num_read = stream.read(m_data + dst_offset, to_write);
    +
    3250 dst_size = dst_offset += num_read;
    +
    3251 num_copied += num_read;
    +
    3252 to_write -= num_read;
    +
    3253 if (!stream.ok()) {
    +
    3254 if (stream.state() != state_t::eof)
    +
    3255 m_state = state_t::fail;
    +
    3256 break;
    +
    3257 }
    +
    3258 };
    +
    3259 }
    +
    3260 else {
    +
    3261 size_t block_size;
    +
    3262 while (to_write) {
    +
    3263 block_size = std::min(to_write, default_block_size);
    +
    3264 dst_size = stdex::add(dst_size, block_size);
    +
    3265 reserve(dst_size);
    +
    3266 if (!ok()) _Unlikely_
    +
    3267 break;
    +
    3268 num_read = stream.read(m_data + dst_offset, block_size);
    +
    3269 dst_size = dst_offset += num_read;
    +
    3270 num_copied += num_read;
    +
    3271 to_write -= num_read;
    +
    3272 if (!stream.ok()) {
    +
    3273 if (stream.state() != state_t::eof)
    +
    3274 m_state = state_t::fail;
    +
    3275 break;
    +
    3276 }
    +
    3277 };
    +
    3278 }
    +
    3279 m_offset = dst_offset;
    +
    3280 if (m_offset > m_size)
    +
    3281 m_size = m_offset;
    +
    3282 return num_copied;
    +
    3283 }
    -
    3277
    -
    -
    3278 virtual void close()
    -
    3279 {
    -
    3280 if (m_manage && m_data)
    -
    3281 free(m_data);
    -
    3282 m_data = nullptr;
    -
    3283 m_manage = true;
    -
    3284 m_offset = 0;
    -
    3285 m_size = m_reserved = 0;
    -
    3286#if SET_FILE_OP_TIMES
    -
    3287 m_ctime = m_atime = m_mtime = time_point::min();
    -
    3288#endif
    -
    3289 m_state = state_t::ok;
    -
    3290 }
    +
    3284
    +
    +
    3285 virtual void close()
    +
    3286 {
    +
    3287 if (m_manage && m_data)
    +
    3288 free(m_data);
    +
    3289 m_data = nullptr;
    +
    3290 m_manage = true;
    +
    3291 m_offset = 0;
    +
    3292 m_size = m_reserved = 0;
    +
    3293#if SET_FILE_OP_TIMES
    +
    3294 m_ctime = m_atime = m_mtime = time_point::min();
    +
    3295#endif
    +
    3296 m_state = state_t::ok;
    +
    3297 }
    -
    3291
    -
    -
    3292 virtual fpos_t seek(_In_ foff_t offset, _In_ seek_t how = seek_t::beg)
    -
    3293 {
    -
    3294 fpos_t target;
    -
    3295 switch (how) {
    -
    3296 case seek_t::beg: target = offset; break;
    -
    3297 case seek_t::cur: target = static_cast<fpos_t>(m_offset) + offset; break;
    -
    3298 case seek_t::end: target = static_cast<fpos_t>(m_size) + offset; break;
    -
    3299 default: throw std::invalid_argument("unknown seek origin");
    -
    3300 }
    -
    3301 if (target <= SIZE_MAX) {
    -
    3302 m_state = state_t::ok;
    -
    3303 return m_offset = static_cast<size_t>(target);
    -
    3304 }
    -
    3305 m_state = state_t::fail;
    -
    3306 return fpos_max;
    -
    3307 }
    +
    3298
    +
    +
    3299 virtual fpos_t seek(_In_ foff_t offset, _In_ seek_t how = seek_t::beg)
    +
    3300 {
    +
    3301 fpos_t target;
    +
    3302 switch (how) {
    +
    3303 case seek_t::beg: target = offset; break;
    +
    3304 case seek_t::cur: target = static_cast<fpos_t>(m_offset) + offset; break;
    +
    3305 case seek_t::end: target = static_cast<fpos_t>(m_size) + offset; break;
    +
    3306 default: throw std::invalid_argument("unknown seek origin");
    +
    3307 }
    +
    3308 if (target <= SIZE_MAX) {
    +
    3309 m_state = state_t::ok;
    +
    3310 return m_offset = static_cast<size_t>(target);
    +
    3311 }
    +
    3312 m_state = state_t::fail;
    +
    3313 return fpos_max;
    +
    3314 }
    -
    3308
    -
    -
    3309 virtual fpos_t tell() const
    -
    3310 {
    -
    3311 return m_offset;
    -
    3312 }
    +
    3315
    +
    +
    3316 virtual fpos_t tell() const
    +
    3317 {
    +
    3318 return m_offset;
    +
    3319 }
    -
    3313
    -
    -
    3314 virtual fsize_t size()
    -
    3315 {
    -
    3316 return m_size;
    -
    3317 }
    +
    3320
    +
    +
    3321 virtual fsize_t size()
    +
    3322 {
    +
    3323 return m_size;
    +
    3324 }
    -
    3318
    -
    -
    3319 virtual void truncate()
    -
    3320 {
    -
    3321#if SET_FILE_OP_TIMES
    -
    3322 m_atime = m_mtime = time_point::now();
    -
    3323#endif
    -
    3324 m_size = m_offset;
    - -
    3326 }
    -
    -
    3327
    +
    3325
    +
    +
    3326 virtual void truncate()
    +
    3327 {
    3328#if SET_FILE_OP_TIMES
    -
    3329 virtual time_point ctime() const
    -
    3330 {
    -
    3331 return m_ctime;
    -
    3332 }
    -
    3333
    -
    3334 virtual time_point atime() const
    -
    3335 {
    -
    3336 return m_atime;
    -
    3337 }
    -
    3338
    -
    3339 virtual time_point mtime() const
    -
    3340 {
    -
    3341 return m_mtime;
    -
    3342 }
    -
    3343
    -
    3344 virtual void set_ctime(time_point date)
    -
    3345 {
    -
    3346 m_ctime = date;
    -
    3347 }
    -
    3348
    -
    3349 virtual void set_atime(time_point date)
    -
    3350 {
    -
    3351 m_atime = date;
    -
    3352 }
    -
    3353
    -
    3354 virtual void set_mtime(time_point date)
    -
    3355 {
    -
    3356 m_mtime = date;
    -
    3357 }
    -
    3358#endif
    -
    3359
    -
    3360 protected:
    -
    3368 template <class T>
    -
    -
    3369 inline void set(_In_ fpos_t offset, _In_ const T data)
    -
    3370 {
    -
    3371#if SET_FILE_OP_TIMES
    -
    3372 m_atime = m_mtime = time_point::now();
    -
    3373#endif
    -
    3374 assert(offset + sizeof(T) < m_size);
    -
    3375 (*reinterpret_cast<T*>(m_data + offset)) = HE2LE(data);
    -
    3376 }
    +
    3329 m_atime = m_mtime = time_point::now();
    +
    3330#endif
    +
    3331 m_size = m_offset;
    + +
    3333 }
    -
    3377
    -
    3378 public:
    -
    3379 inline void set(_In_ fpos_t offset, _In_ const int8_t data) { set<int8_t>(offset, data); }
    -
    3380 inline void set(_In_ fpos_t offset, _In_ const int16_t data) { set<int16_t>(offset, data); }
    -
    3381 inline void set(_In_ fpos_t offset, _In_ const int32_t data) { set<int32_t>(offset, data); }
    -
    3382 inline void set(_In_ fpos_t offset, _In_ const int64_t data) { set<int64_t>(offset, data); }
    -
    3383 inline void set(_In_ fpos_t offset, _In_ const uint8_t data) { set<uint8_t>(offset, data); }
    -
    3384 inline void set(_In_ fpos_t offset, _In_ const uint16_t data) { set<uint16_t>(offset, data); }
    -
    3385 inline void set(_In_ fpos_t offset, _In_ const uint32_t data) { set<uint32_t>(offset, data); }
    -
    3386 inline void set(_In_ fpos_t offset, _In_ const uint64_t data) { set<uint64_t>(offset, data); }
    -
    3387#if defined(_WIN64) && defined(_NATIVE_SIZE_T_DEFINED)
    -
    3388 inline void set(_In_ fpos_t offset, _In_ const size_t data) { set<size_t>(offset, data); }
    -
    3389#endif
    -
    3390 inline void set(_In_ fpos_t offset, _In_ const float data) { set<float>(offset, data); }
    -
    3391 inline void set(_In_ fpos_t offset, _In_ const double data) { set<double>(offset, data); }
    -
    3392 inline void set(_In_ fpos_t offset, _In_ const char data) { set<char>(offset, data); }
    -
    3393#ifdef _NATIVE_WCHAR_T_DEFINED
    -
    3394 inline void set(_In_ fpos_t offset, _In_ const wchar_t data) { set<wchar_t>(offset, data); }
    -
    3395#endif
    -
    3396
    -
    3404 protected:
    -
    3405 template <class T>
    -
    -
    3406 inline void get(_In_ fpos_t offset, _Out_ T & data)
    -
    3407 {
    -
    3408 assert(offset + sizeof(T) < m_size);
    -
    3409 data = LE2HE(*(T*)(m_data + offset));
    -
    3410#if SET_FILE_OP_TIMES
    -
    3411 m_atime = time_point::now();
    -
    3412#endif
    -
    3413 }
    +
    3334
    +
    3335#if SET_FILE_OP_TIMES
    +
    3336 virtual time_point ctime() const
    +
    3337 {
    +
    3338 return m_ctime;
    +
    3339 }
    +
    3340
    +
    3341 virtual time_point atime() const
    +
    3342 {
    +
    3343 return m_atime;
    +
    3344 }
    +
    3345
    +
    3346 virtual time_point mtime() const
    +
    3347 {
    +
    3348 return m_mtime;
    +
    3349 }
    +
    3350
    +
    3351 virtual void set_ctime(time_point date)
    +
    3352 {
    +
    3353 m_ctime = date;
    +
    3354 }
    +
    3355
    +
    3356 virtual void set_atime(time_point date)
    +
    3357 {
    +
    3358 m_atime = date;
    +
    3359 }
    +
    3360
    +
    3361 virtual void set_mtime(time_point date)
    +
    3362 {
    +
    3363 m_mtime = date;
    +
    3364 }
    +
    3365#endif
    +
    3366
    +
    3367 protected:
    +
    3375 template <class T>
    +
    +
    3376 inline void set(_In_ fpos_t offset, _In_ const T data)
    +
    3377 {
    +
    3378#if SET_FILE_OP_TIMES
    +
    3379 m_atime = m_mtime = time_point::now();
    +
    3380#endif
    +
    3381 assert(offset + sizeof(T) < m_size);
    +
    3382 (*reinterpret_cast<T*>(m_data + offset)) = HE2LE(data);
    +
    3383 }
    -
    3414
    -
    3415 public:
    -
    3416 inline void get(_In_ fpos_t offset, _Out_ int8_t & data) { get<int8_t>(offset, data); }
    -
    3417 inline void get(_In_ fpos_t offset, _Out_ int16_t & data) { get<int16_t>(offset, data); }
    -
    3418 inline void get(_In_ fpos_t offset, _Out_ int32_t & data) { get<int32_t>(offset, data); }
    -
    3419 inline void get(_In_ fpos_t offset, _Out_ int64_t & data) { get<int64_t>(offset, data); }
    -
    3420 inline void get(_In_ fpos_t offset, _Out_ uint8_t & data) { get<uint8_t>(offset, data); }
    -
    3421 inline void get(_In_ fpos_t offset, _Out_ uint16_t & data) { get<uint16_t>(offset, data); }
    -
    3422 inline void get(_In_ fpos_t offset, _Out_ uint32_t & data) { get<uint32_t>(offset, data); }
    -
    3423 inline void get(_In_ fpos_t offset, _Out_ uint64_t & data) { get<uint64_t>(offset, data); }
    -
    3424#if defined(_WIN64) && defined(_NATIVE_SIZE_T_DEFINED)
    -
    3425 inline void get(_In_ fpos_t offset, _Out_ size_t & data) { get<size_t>(offset, data); }
    -
    3426#endif
    -
    3427 inline void get(_In_ fpos_t offset, _Out_ float& data) { get<float>(offset, data); }
    -
    3428 inline void get(_In_ fpos_t offset, _Out_ double& data) { get<double>(offset, data); }
    -
    3429 inline void get(_In_ fpos_t offset, _Out_ char& data) { get<char>(offset, data); }
    -
    3430#ifdef _NATIVE_WCHAR_T_DEFINED
    -
    3431 inline void get(_In_ fpos_t offset, _Out_ wchar_t& data) { get<wchar_t>(offset, data); }
    -
    3432#endif
    -
    3433
    -
    3434 inline memory_file& operator <<(_In_ const int8_t data) { return write_data(data); }
    -
    3435 inline memory_file& operator >>(_Out_ int8_t & data) { return read_data(data); }
    -
    3436 inline memory_file& operator <<(_In_ const int16_t data) { return write_data(data); }
    -
    3437 inline memory_file& operator >>(_Out_ int16_t & data) { return read_data(data); }
    -
    3438 inline memory_file& operator <<(_In_ const int32_t data) { return write_data(data); }
    -
    3439 inline memory_file& operator >>(_Out_ int32_t & data) { return read_data(data); }
    -
    3440 inline memory_file& operator <<(_In_ const int64_t data) { return write_data(data); }
    -
    3441 inline memory_file& operator >>(_Out_ int64_t & data) { return read_data(data); }
    -
    3442 inline memory_file& operator <<(_In_ const uint8_t data) { return write_data(data); }
    -
    3443 inline memory_file& operator >>(_Out_ uint8_t & data) { return read_data(data); }
    -
    3444 inline memory_file& operator <<(_In_ const uint16_t data) { return write_data(data); }
    -
    3445 inline memory_file& operator >>(_Out_ uint16_t & data) { return read_data(data); }
    -
    3446 inline memory_file& operator <<(_In_ const uint32_t data) { return write_data(data); }
    -
    3447 inline memory_file& operator >>(_Out_ uint32_t & data) { return read_data(data); }
    -
    3448 inline memory_file& operator <<(_In_ const uint64_t data) { return write_data(data); }
    -
    3449 inline memory_file& operator >>(_Out_ uint64_t & data) { return read_data(data); }
    -
    3450#if defined(_WIN64) && defined(_NATIVE_SIZE_T_DEFINED)
    -
    3451 inline memory_file& operator <<(_In_ const size_t data) { return write_data(data); }
    -
    3452 inline memory_file& operator >>(_Out_ size_t & data) { return read_data(data); }
    -
    3453#endif
    -
    3454 inline memory_file& operator <<(_In_ const float data) { return write_data(data); }
    -
    3455 inline memory_file& operator >>(_Out_ float& data) { return read_data(data); }
    -
    3456 inline memory_file& operator <<(_In_ const double data) { return write_data(data); }
    -
    3457 inline memory_file& operator >>(_Out_ double& data) { return read_data(data); }
    -
    3458 inline memory_file& operator <<(_In_ const char data) { return write_data(data); }
    -
    3459 inline memory_file& operator >>(_Out_ char& data) { return read_data(data); }
    -
    3460#ifdef _NATIVE_WCHAR_T_DEFINED
    -
    3461 inline memory_file& operator <<(_In_ const wchar_t data) { return write_data(data); }
    -
    3462 inline memory_file& operator >>(_Out_ wchar_t& data) { return read_data(data); }
    -
    3463#endif
    -
    3464 template <class T>
    -
    3465 inline memory_file& operator <<(_In_ const T * data) { return write_str(data); }
    -
    3466 template<class _Elem, class _Traits = std::char_traits<_Elem>, class _Ax = std::allocator<_Elem>>
    -
    3467 inline memory_file& operator >>(_Inout_ std::basic_string<_Elem, _Traits, _Ax>&data) { return read_str(data); }
    -
    3468
    -
    3469 protected:
    -
    3470 uint8_t* m_data;
    - -
    3472 size_t m_offset;
    -
    3473 size_t m_size;
    -
    3474 size_t m_reserved;
    -
    3475#if SET_FILE_OP_TIMES
    -
    3476 time_point
    -
    3477 m_ctime,
    -
    3478 m_atime,
    -
    3479 m_mtime;
    -
    3480#endif
    -
    3481 };
    +
    3384
    +
    3385 public:
    +
    3386 inline void set(_In_ fpos_t offset, _In_ const int8_t data) { set<int8_t>(offset, data); }
    +
    3387 inline void set(_In_ fpos_t offset, _In_ const int16_t data) { set<int16_t>(offset, data); }
    +
    3388 inline void set(_In_ fpos_t offset, _In_ const int32_t data) { set<int32_t>(offset, data); }
    +
    3389 inline void set(_In_ fpos_t offset, _In_ const int64_t data) { set<int64_t>(offset, data); }
    +
    3390 inline void set(_In_ fpos_t offset, _In_ const uint8_t data) { set<uint8_t>(offset, data); }
    +
    3391 inline void set(_In_ fpos_t offset, _In_ const uint16_t data) { set<uint16_t>(offset, data); }
    +
    3392 inline void set(_In_ fpos_t offset, _In_ const uint32_t data) { set<uint32_t>(offset, data); }
    +
    3393 inline void set(_In_ fpos_t offset, _In_ const uint64_t data) { set<uint64_t>(offset, data); }
    +
    3394 inline void set(_In_ fpos_t offset, _In_ const float data) { set<float>(offset, data); }
    +
    3395 inline void set(_In_ fpos_t offset, _In_ const double data) { set<double>(offset, data); }
    +
    3396 inline void set(_In_ fpos_t offset, _In_ const char data) { set<char>(offset, data); }
    +
    3397#ifdef _NATIVE_WCHAR_T_DEFINED
    +
    3398 inline void set(_In_ fpos_t offset, _In_ const wchar_t data) { set<wchar_t>(offset, data); }
    +
    3399#endif
    +
    3400
    +
    3408 protected:
    +
    3409 template <class T>
    +
    +
    3410 inline void get(_In_ fpos_t offset, _Out_ T & data)
    +
    3411 {
    +
    3412 assert(offset + sizeof(T) < m_size);
    +
    3413 data = LE2HE(*(T*)(m_data + offset));
    +
    3414#if SET_FILE_OP_TIMES
    +
    3415 m_atime = time_point::now();
    +
    3416#endif
    +
    3417 }
    -
    3482
    -
    -
    3486 class fifo : public basic {
    -
    3487 public:
    -
    3488 fifo() :
    -
    3489 m_offset(0),
    -
    3490 m_size(0),
    -
    3491 m_head(nullptr),
    -
    3492 m_tail(nullptr)
    -
    3493 {}
    -
    3494
    -
    3495 virtual ~fifo()
    -
    3496 {
    -
    3497 while (m_head) {
    -
    3498 auto p = m_head;
    -
    3499 m_head = p->next;
    -
    3500 delete p;
    -
    3501 }
    -
    3502 }
    -
    3503
    -
    3504#pragma warning(suppress: 6101) // See [2] below
    -
    -
    3505 virtual _Success_(return != 0 || length == 0) size_t read(
    -
    3506 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
    -
    3507 {
    -
    3508 assert(data || !length);
    -
    3509 for (size_t to_read = length;;) {
    -
    3510 if (!m_head) _Unlikely_ {
    -
    3511 // [1] Code analysis misses length - to_read bytes were written to data in previous loop iterations.
    -
    3512 m_state = to_read < length || !length ? state_t::ok : state_t::eof;
    -
    3513 return length - to_read;
    -
    3514 }
    -
    3515 size_t remaining = m_head->size - m_offset;
    -
    3516 if (remaining > to_read) {
    -
    3517 memcpy(data, m_head->data + m_offset, to_read);
    -
    3518 m_offset += to_read;
    -
    3519 m_size -= to_read;
    -
    3520 m_state = state_t::ok;
    -
    3521 return length;
    -
    3522 }
    -
    3523 memcpy(data, m_head->data + m_offset, remaining);
    -
    3524 m_offset = 0;
    -
    3525 m_size -= remaining;
    -
    3526 reinterpret_cast<uint8_t*&>(data) += remaining;
    -
    3527 to_read -= remaining;
    -
    3528 auto p = m_head;
    -
    3529 m_head = p->next;
    -
    3530 delete p;
    -
    3531 }
    -
    3532 }
    +
    3418
    +
    3419 public:
    +
    3420 inline void get(_In_ fpos_t offset, _Out_ int8_t & data) { get<int8_t>(offset, data); }
    +
    3421 inline void get(_In_ fpos_t offset, _Out_ int16_t & data) { get<int16_t>(offset, data); }
    +
    3422 inline void get(_In_ fpos_t offset, _Out_ int32_t & data) { get<int32_t>(offset, data); }
    +
    3423 inline void get(_In_ fpos_t offset, _Out_ int64_t & data) { get<int64_t>(offset, data); }
    +
    3424 inline void get(_In_ fpos_t offset, _Out_ uint8_t & data) { get<uint8_t>(offset, data); }
    +
    3425 inline void get(_In_ fpos_t offset, _Out_ uint16_t & data) { get<uint16_t>(offset, data); }
    +
    3426 inline void get(_In_ fpos_t offset, _Out_ uint32_t & data) { get<uint32_t>(offset, data); }
    +
    3427 inline void get(_In_ fpos_t offset, _Out_ uint64_t & data) { get<uint64_t>(offset, data); }
    +
    3428 inline void get(_In_ fpos_t offset, _Out_ float& data) { get<float>(offset, data); }
    +
    3429 inline void get(_In_ fpos_t offset, _Out_ double& data) { get<double>(offset, data); }
    +
    3430 inline void get(_In_ fpos_t offset, _Out_ char& data) { get<char>(offset, data); }
    +
    3431#ifdef _NATIVE_WCHAR_T_DEFINED
    +
    3432 inline void get(_In_ fpos_t offset, _Out_ wchar_t& data) { get<wchar_t>(offset, data); }
    +
    3433#endif
    +
    3434
    +
    3435 inline memory_file& operator <<(_In_ const int8_t data) { return write_data(data); }
    +
    3436 inline memory_file& operator >>(_Out_ int8_t & data) { return read_data(data); }
    +
    3437 inline memory_file& operator <<(_In_ const int16_t data) { return write_data(data); }
    +
    3438 inline memory_file& operator >>(_Out_ int16_t & data) { return read_data(data); }
    +
    3439 inline memory_file& operator <<(_In_ const int32_t data) { return write_data(data); }
    +
    3440 inline memory_file& operator >>(_Out_ int32_t & data) { return read_data(data); }
    +
    3441 inline memory_file& operator <<(_In_ const int64_t data) { return write_data(data); }
    +
    3442 inline memory_file& operator >>(_Out_ int64_t & data) { return read_data(data); }
    +
    3443 inline memory_file& operator <<(_In_ const uint8_t data) { return write_data(data); }
    +
    3444 inline memory_file& operator >>(_Out_ uint8_t & data) { return read_data(data); }
    +
    3445 inline memory_file& operator <<(_In_ const uint16_t data) { return write_data(data); }
    +
    3446 inline memory_file& operator >>(_Out_ uint16_t & data) { return read_data(data); }
    +
    3447 inline memory_file& operator <<(_In_ const uint32_t data) { return write_data(data); }
    +
    3448 inline memory_file& operator >>(_Out_ uint32_t & data) { return read_data(data); }
    +
    3449 inline memory_file& operator <<(_In_ const uint64_t data) { return write_data(data); }
    +
    3450 inline memory_file& operator >>(_Out_ uint64_t & data) { return read_data(data); }
    +
    3451 inline memory_file& operator <<(_In_ const float data) { return write_data(data); }
    +
    3452 inline memory_file& operator >>(_Out_ float& data) { return read_data(data); }
    +
    3453 inline memory_file& operator <<(_In_ const double data) { return write_data(data); }
    +
    3454 inline memory_file& operator >>(_Out_ double& data) { return read_data(data); }
    +
    3455 inline memory_file& operator <<(_In_ const char data) { return write_data(data); }
    +
    3456 inline memory_file& operator >>(_Out_ char& data) { return read_data(data); }
    +
    3457#ifdef _NATIVE_WCHAR_T_DEFINED
    +
    3458 inline memory_file& operator <<(_In_ const wchar_t data) { return write_data(data); }
    +
    3459 inline memory_file& operator >>(_Out_ wchar_t& data) { return read_data(data); }
    +
    3460#endif
    +
    3461 template <class T>
    +
    3462 inline memory_file& operator <<(_In_ const T * data) { return write_str(data); }
    +
    3463 template<class _Elem, class _Traits = std::char_traits<_Elem>, class _Ax = std::allocator<_Elem>>
    +
    3464 inline memory_file& operator >>(_Inout_ std::basic_string<_Elem, _Traits, _Ax>&data) { return read_str(data); }
    +
    3465
    +
    3466 protected:
    +
    3467 uint8_t* m_data;
    + +
    3469 size_t m_offset;
    +
    3470 size_t m_size;
    +
    3471 size_t m_reserved;
    +
    3472#if SET_FILE_OP_TIMES
    +
    3473 time_point
    +
    3474 m_ctime,
    +
    3475 m_atime,
    +
    3476 m_mtime;
    +
    3477#endif
    +
    3478 };
    -
    3533
    -
    -
    3534 virtual _Success_(return != 0) size_t write(
    -
    3535 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
    -
    3536 {
    -
    3537 assert(data || !length);
    -
    3538 try {
    -
    3539 std::unique_ptr<node_t> n(reinterpret_cast<node_t*>(new uint8_t[sizeof(node_t) + length]));
    -
    3540 n->next = nullptr;
    -
    3541 n->size = length;
    -
    3542 memcpy(n->data, data, length);
    -
    3543 m_size += length;
    -
    3544 if (m_head)
    -
    3545 m_tail = m_tail->next = n.release();
    -
    3546 else
    -
    3547 m_head = m_tail = n.release();
    -
    3548 m_state = state_t::ok;
    -
    3549 return length;
    -
    3550 }
    -
    3551 catch (const std::bad_alloc&) {
    -
    3552 m_state = state_t::fail;
    -
    3553 return 0;
    -
    3554 }
    -
    3555 }
    +
    3479
    +
    +
    3483 class fifo : public basic {
    +
    3484 public:
    +
    3485 fifo() :
    +
    3486 m_offset(0),
    +
    3487 m_size(0),
    +
    3488 m_head(nullptr),
    +
    3489 m_tail(nullptr)
    +
    3490 {}
    +
    3491
    +
    3492 virtual ~fifo()
    +
    3493 {
    +
    3494 while (m_head) {
    +
    3495 auto p = m_head;
    +
    3496 m_head = p->next;
    +
    3497 delete p;
    +
    3498 }
    +
    3499 }
    +
    3500
    +
    3501#pragma warning(suppress: 6101) // See [2] below
    +
    +
    3502 virtual _Success_(return != 0 || length == 0) size_t read(
    +
    3503 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
    +
    3504 {
    +
    3505 assert(data || !length);
    +
    3506 for (size_t to_read = length;;) {
    +
    3507 if (!m_head) _Unlikely_ {
    +
    3508 // [1] Code analysis misses length - to_read bytes were written to data in previous loop iterations.
    +
    3509 m_state = to_read < length || !length ? state_t::ok : state_t::eof;
    +
    3510 return length - to_read;
    +
    3511 }
    +
    3512 size_t remaining = m_head->size - m_offset;
    +
    3513 if (remaining > to_read) {
    +
    3514 memcpy(data, m_head->data + m_offset, to_read);
    +
    3515 m_offset += to_read;
    +
    3516 m_size -= to_read;
    +
    3517 m_state = state_t::ok;
    +
    3518 return length;
    +
    3519 }
    +
    3520 memcpy(data, m_head->data + m_offset, remaining);
    +
    3521 m_offset = 0;
    +
    3522 m_size -= remaining;
    +
    3523 reinterpret_cast<uint8_t*&>(data) += remaining;
    +
    3524 to_read -= remaining;
    +
    3525 auto p = m_head;
    +
    3526 m_head = p->next;
    +
    3527 delete p;
    +
    3528 }
    +
    3529 }
    -
    3556
    -
    -
    3557 virtual void close()
    -
    3558 {
    -
    3559 m_size = m_offset = 0;
    -
    3560 while (m_head) {
    -
    3561 auto p = m_head;
    -
    3562 m_head = p->next;
    -
    3563 delete p;
    -
    3564 }
    -
    3565 m_state = state_t::ok;
    -
    3566 }
    +
    3530
    +
    +
    3531 virtual _Success_(return != 0) size_t write(
    +
    3532 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
    +
    3533 {
    +
    3534 assert(data || !length);
    +
    3535 try {
    +
    3536 std::unique_ptr<node_t> n(reinterpret_cast<node_t*>(new uint8_t[sizeof(node_t) + length]));
    +
    3537 n->next = nullptr;
    +
    3538 n->size = length;
    +
    3539 memcpy(n->data, data, length);
    +
    3540 m_size += length;
    +
    3541 if (m_head)
    +
    3542 m_tail = m_tail->next = n.release();
    +
    3543 else
    +
    3544 m_head = m_tail = n.release();
    +
    3545 m_state = state_t::ok;
    +
    3546 return length;
    +
    3547 }
    +
    3548 catch (const std::bad_alloc&) {
    +
    3549 m_state = state_t::fail;
    +
    3550 return 0;
    +
    3551 }
    +
    3552 }
    -
    3567
    -
    3571 inline size_t size() const { return m_size; };
    -
    3572
    -
    3573 protected:
    -
    3574 size_t m_offset, m_size;
    -
    -
    3575 struct node_t {
    -
    3576 node_t* next;
    -
    3577 size_t size;
    -
    3578#pragma warning(suppress:4200)
    -
    3579 uint8_t data[0];
    -
    3580 } *m_head, * m_tail;
    +
    3553
    +
    +
    3554 virtual void close()
    +
    3555 {
    +
    3556 m_size = m_offset = 0;
    +
    3557 while (m_head) {
    +
    3558 auto p = m_head;
    +
    3559 m_head = p->next;
    +
    3560 delete p;
    +
    3561 }
    +
    3562 m_state = state_t::ok;
    +
    3563 }
    -
    3581 };
    +
    3564
    +
    3568 inline size_t size() const { return m_size; };
    +
    3569
    +
    3570 protected:
    +
    3571 size_t m_offset, m_size;
    +
    +
    3572 struct node_t {
    +
    3573 node_t* next;
    +
    3574 size_t size;
    +
    3575#pragma warning(suppress:4200)
    +
    3576 uint8_t data[0];
    +
    3577 } *m_head, * m_tail;
    -
    3582
    -
    -
    3586 class diag_file : public basic_file {
    -
    3587 public:
    -
    3588 diag_file(_In_count_(num_files) basic_file* const* files, _In_ size_t num_files) :
    -
    3589 basic(num_files ? files[0]->state() : state_t::fail),
    -
    3590 m_files(files, files + num_files)
    -
    3591 {
    -
    3592 }
    -
    3593
    -
    -
    3594 virtual _Success_(return != 0 || length == 0) size_t read(
    -
    3595 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
    -
    3596 {
    -
    3597 assert(data || !length);
    -
    3598 if (m_files.empty()) {
    -
    3599 m_state = state_t::fail;
    -
    3600 return 0;
    -
    3601 }
    -
    3602 size_t result = m_files[0]->read(data, length);
    -
    3603 _Analysis_assume_(result <= length);
    -
    3604 m_state = m_files[0]->state();
    -
    3605 if (length > m_tmp.size())
    -
    3606 m_tmp.resize(length);
    -
    3607 for (size_t i = 1, n = m_files.size(); i < n; ++i) {
    -
    3608 if (m_files[i]->read(m_tmp.data(), length) != result ||
    -
    3609 memcmp(m_tmp.data(), data, result))
    -
    3610 throw std::runtime_error("read mismatch");
    -
    3611 if (m_files[i]->state() != m_state)
    -
    3612 throw std::runtime_error("state mismatch");
    -
    3613 }
    -
    3614 return result;
    -
    3615 }
    +
    3578 };
    -
    3616
    -
    -
    3617 virtual _Success_(return != 0) size_t write(
    -
    3618 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
    -
    3619 {
    -
    3620 if (m_files.empty()) {
    -
    3621 m_state = state_t::fail;
    -
    3622 return 0;
    -
    3623 }
    -
    3624 size_t result = m_files[0]->write(data, length);
    -
    3625 m_state = m_files[0]->state();
    -
    3626 for (size_t i = 1, n = m_files.size(); i < n; ++i) {
    -
    3627 if (m_files[i]->write(data, length) != result)
    -
    3628 throw std::runtime_error("write mismatch");
    -
    3629 if (m_files[i]->state() != m_state)
    -
    3630 throw std::runtime_error("state mismatch");
    -
    3631 }
    -
    3632 return result;
    -
    3633 }
    +
    3579
    +
    +
    3583 class diag_file : public basic_file {
    +
    3584 public:
    +
    3585 diag_file(_In_count_(num_files) basic_file* const* files, _In_ size_t num_files) :
    +
    3586 basic(num_files ? files[0]->state() : state_t::fail),
    +
    3587 m_files(files, files + num_files)
    +
    3588 {
    +
    3589 }
    +
    3590
    +
    +
    3591 virtual _Success_(return != 0 || length == 0) size_t read(
    +
    3592 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
    +
    3593 {
    +
    3594 assert(data || !length);
    +
    3595 if (m_files.empty()) {
    +
    3596 m_state = state_t::fail;
    +
    3597 return 0;
    +
    3598 }
    +
    3599 size_t result = m_files[0]->read(data, length);
    +
    3600 _Analysis_assume_(result <= length);
    +
    3601 m_state = m_files[0]->state();
    +
    3602 if (length > m_tmp.size())
    +
    3603 m_tmp.resize(length);
    +
    3604 for (size_t i = 1, n = m_files.size(); i < n; ++i) {
    +
    3605 if (m_files[i]->read(m_tmp.data(), length) != result ||
    +
    3606 memcmp(m_tmp.data(), data, result))
    +
    3607 throw std::runtime_error("read mismatch");
    +
    3608 if (m_files[i]->state() != m_state)
    +
    3609 throw std::runtime_error("state mismatch");
    +
    3610 }
    +
    3611 return result;
    +
    3612 }
    -
    3634
    -
    -
    3635 virtual void flush()
    -
    3636 {
    -
    3637 if (m_files.empty()) {
    -
    3638 m_state = state_t::ok;
    -
    3639 return;
    -
    3640 }
    -
    3641 m_files[0]->flush();
    -
    3642 m_state = m_files[0]->state();
    -
    3643 for (size_t i = 1, n = m_files.size(); i < n; ++i) {
    -
    3644 m_files[i]->flush();
    -
    3645 if (m_files[i]->state() != m_state)
    -
    3646 throw std::runtime_error("state mismatch");
    -
    3647 }
    -
    3648 }
    +
    3613
    +
    +
    3614 virtual _Success_(return != 0) size_t write(
    +
    3615 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
    +
    3616 {
    +
    3617 if (m_files.empty()) {
    +
    3618 m_state = state_t::fail;
    +
    3619 return 0;
    +
    3620 }
    +
    3621 size_t result = m_files[0]->write(data, length);
    +
    3622 m_state = m_files[0]->state();
    +
    3623 for (size_t i = 1, n = m_files.size(); i < n; ++i) {
    +
    3624 if (m_files[i]->write(data, length) != result)
    +
    3625 throw std::runtime_error("write mismatch");
    +
    3626 if (m_files[i]->state() != m_state)
    +
    3627 throw std::runtime_error("state mismatch");
    +
    3628 }
    +
    3629 return result;
    +
    3630 }
    -
    3649
    -
    -
    3650 virtual void close()
    -
    3651 {
    -
    3652 if (m_files.empty()) {
    -
    3653 m_state = state_t::ok;
    -
    3654 return;
    -
    3655 }
    -
    3656 m_files[0]->close();
    -
    3657 m_state = m_files[0]->state();
    -
    3658 for (size_t i = 1, n = m_files.size(); i < n; ++i) {
    -
    3659 m_files[i]->close();
    -
    3660 if (m_files[i]->state() != m_state)
    -
    3661 throw std::runtime_error("state mismatch");
    -
    3662 }
    -
    3663 m_tmp.clear();
    -
    3664 m_tmp.shrink_to_fit();
    -
    3665 }
    +
    3631
    +
    +
    3632 virtual void flush()
    +
    3633 {
    +
    3634 if (m_files.empty()) {
    +
    3635 m_state = state_t::ok;
    +
    3636 return;
    +
    3637 }
    +
    3638 m_files[0]->flush();
    +
    3639 m_state = m_files[0]->state();
    +
    3640 for (size_t i = 1, n = m_files.size(); i < n; ++i) {
    +
    3641 m_files[i]->flush();
    +
    3642 if (m_files[i]->state() != m_state)
    +
    3643 throw std::runtime_error("state mismatch");
    +
    3644 }
    +
    3645 }
    -
    3666
    -
    -
    3667 virtual fpos_t seek(_In_ foff_t offset, _In_ seek_t how = seek_t::beg)
    -
    3668 {
    -
    3669 if (m_files.empty()) {
    -
    3670 m_state = state_t::fail;
    -
    3671 return fpos_max;
    -
    3672 }
    -
    3673 fpos_t result = m_files[0]->seek(offset, how);
    -
    3674 m_state = m_files[0]->state();
    -
    3675 for (size_t i = 1, n = m_files.size(); i < n; ++i) {
    -
    3676 if (m_files[i]->seek(offset, how) != result)
    -
    3677 throw std::runtime_error("seek mismatch");
    -
    3678 if (m_files[i]->state() != m_state)
    -
    3679 throw std::runtime_error("state mismatch");
    -
    3680 }
    -
    3681 return result;
    -
    3682 }
    +
    3646
    +
    +
    3647 virtual void close()
    +
    3648 {
    +
    3649 if (m_files.empty()) {
    +
    3650 m_state = state_t::ok;
    +
    3651 return;
    +
    3652 }
    +
    3653 m_files[0]->close();
    +
    3654 m_state = m_files[0]->state();
    +
    3655 for (size_t i = 1, n = m_files.size(); i < n; ++i) {
    +
    3656 m_files[i]->close();
    +
    3657 if (m_files[i]->state() != m_state)
    +
    3658 throw std::runtime_error("state mismatch");
    +
    3659 }
    +
    3660 m_tmp.clear();
    +
    3661 m_tmp.shrink_to_fit();
    +
    3662 }
    -
    3683
    -
    -
    3684 virtual fpos_t tell() const
    -
    3685 {
    -
    3686 if (m_files.empty())
    -
    3687 return fpos_max;
    -
    3688 fpos_t result = m_files[0]->tell();
    -
    3689 for (size_t i = 1, n = m_files.size(); i < n; ++i) {
    -
    3690 if (m_files[i]->tell() != result)
    -
    3691 throw std::runtime_error("tell mismatch");
    -
    3692 }
    -
    3693 return result;
    -
    3694 }
    +
    3663
    +
    +
    3664 virtual fpos_t seek(_In_ foff_t offset, _In_ seek_t how = seek_t::beg)
    +
    3665 {
    +
    3666 if (m_files.empty()) {
    +
    3667 m_state = state_t::fail;
    +
    3668 return fpos_max;
    +
    3669 }
    +
    3670 fpos_t result = m_files[0]->seek(offset, how);
    +
    3671 m_state = m_files[0]->state();
    +
    3672 for (size_t i = 1, n = m_files.size(); i < n; ++i) {
    +
    3673 if (m_files[i]->seek(offset, how) != result)
    +
    3674 throw std::runtime_error("seek mismatch");
    +
    3675 if (m_files[i]->state() != m_state)
    +
    3676 throw std::runtime_error("state mismatch");
    +
    3677 }
    +
    3678 return result;
    +
    3679 }
    -
    3695
    -
    -
    3696 virtual void lock(_In_ fpos_t offset, _In_ fsize_t length)
    -
    3697 {
    -
    3698 if (m_files.empty())
    -
    3699 m_state = state_t::fail;
    -
    3700 m_files[0]->lock(offset, length);
    -
    3701 m_state = m_files[0]->state();
    -
    3702 for (size_t i = 1, n = m_files.size(); i < n; ++i) {
    -
    3703 m_files[i]->lock(offset, length);
    -
    3704 if (m_files[i]->state() != m_state)
    -
    3705 throw std::runtime_error("state mismatch");
    -
    3706 }
    -
    3707 }
    +
    3680
    +
    +
    3681 virtual fpos_t tell() const
    +
    3682 {
    +
    3683 if (m_files.empty())
    +
    3684 return fpos_max;
    +
    3685 fpos_t result = m_files[0]->tell();
    +
    3686 for (size_t i = 1, n = m_files.size(); i < n; ++i) {
    +
    3687 if (m_files[i]->tell() != result)
    +
    3688 throw std::runtime_error("tell mismatch");
    +
    3689 }
    +
    3690 return result;
    +
    3691 }
    -
    3708
    -
    -
    3709 virtual void unlock(_In_ fpos_t offset, _In_ fsize_t length)
    -
    3710 {
    -
    3711 if (m_files.empty())
    -
    3712 m_state = state_t::fail;
    -
    3713 m_files[0]->unlock(offset, length);
    -
    3714 m_state = m_files[0]->state();
    -
    3715 for (size_t i = 1, n = m_files.size(); i < n; ++i) {
    -
    3716 m_files[i]->unlock(offset, length);
    -
    3717 if (m_files[i]->state() != m_state)
    -
    3718 throw std::runtime_error("state mismatch");
    -
    3719 }
    -
    3720 }
    +
    3692
    +
    +
    3693 virtual void lock(_In_ fpos_t offset, _In_ fsize_t length)
    +
    3694 {
    +
    3695 if (m_files.empty())
    +
    3696 m_state = state_t::fail;
    +
    3697 m_files[0]->lock(offset, length);
    +
    3698 m_state = m_files[0]->state();
    +
    3699 for (size_t i = 1, n = m_files.size(); i < n; ++i) {
    +
    3700 m_files[i]->lock(offset, length);
    +
    3701 if (m_files[i]->state() != m_state)
    +
    3702 throw std::runtime_error("state mismatch");
    +
    3703 }
    +
    3704 }
    -
    3721
    -
    -
    3722 virtual fsize_t size()
    -
    3723 {
    -
    3724 if (m_files.empty()) {
    -
    3725 m_state = state_t::fail;
    -
    3726 return 0;
    -
    3727 }
    -
    3728 fsize_t result = m_files[0]->size();
    -
    3729 m_state = m_files[0]->state();
    -
    3730 for (size_t i = 1, n = m_files.size(); i < n; ++i) {
    -
    3731 if (m_files[i]->size() != result)
    -
    3732 throw std::runtime_error("size mismatch");
    -
    3733 if (m_files[i]->state() != m_state)
    -
    3734 throw std::runtime_error("state mismatch");
    -
    3735 }
    -
    3736 return result;
    -
    3737 }
    +
    3705
    +
    +
    3706 virtual void unlock(_In_ fpos_t offset, _In_ fsize_t length)
    +
    3707 {
    +
    3708 if (m_files.empty())
    +
    3709 m_state = state_t::fail;
    +
    3710 m_files[0]->unlock(offset, length);
    +
    3711 m_state = m_files[0]->state();
    +
    3712 for (size_t i = 1, n = m_files.size(); i < n; ++i) {
    +
    3713 m_files[i]->unlock(offset, length);
    +
    3714 if (m_files[i]->state() != m_state)
    +
    3715 throw std::runtime_error("state mismatch");
    +
    3716 }
    +
    3717 }
    -
    3738
    -
    -
    3739 virtual void truncate()
    -
    3740 {
    -
    3741 if (m_files.empty())
    -
    3742 m_state = state_t::fail;
    -
    3743 m_files[0]->truncate();
    -
    3744 m_state = m_files[0]->state();
    -
    3745 for (size_t i = 1, n = m_files.size(); i < n; ++i) {
    -
    3746 m_files[i]->truncate();
    -
    3747 if (m_files[i]->state() != m_state)
    -
    3748 throw std::runtime_error("state mismatch");
    -
    3749 }
    -
    3750 }
    +
    3718
    +
    +
    3719 virtual fsize_t size()
    +
    3720 {
    +
    3721 if (m_files.empty()) {
    +
    3722 m_state = state_t::fail;
    +
    3723 return 0;
    +
    3724 }
    +
    3725 fsize_t result = m_files[0]->size();
    +
    3726 m_state = m_files[0]->state();
    +
    3727 for (size_t i = 1, n = m_files.size(); i < n; ++i) {
    +
    3728 if (m_files[i]->size() != result)
    +
    3729 throw std::runtime_error("size mismatch");
    +
    3730 if (m_files[i]->state() != m_state)
    +
    3731 throw std::runtime_error("state mismatch");
    +
    3732 }
    +
    3733 return result;
    +
    3734 }
    -
    3751
    -
    3752 protected:
    -
    3753 std::vector<basic_file*> m_files;
    -
    3754 std::vector<uint8_t> m_tmp;
    -
    3755 };
    +
    3735
    +
    +
    3736 virtual void truncate()
    +
    3737 {
    +
    3738 if (m_files.empty())
    +
    3739 m_state = state_t::fail;
    +
    3740 m_files[0]->truncate();
    +
    3741 m_state = m_files[0]->state();
    +
    3742 for (size_t i = 1, n = m_files.size(); i < n; ++i) {
    +
    3743 m_files[i]->truncate();
    +
    3744 if (m_files[i]->state() != m_state)
    +
    3745 throw std::runtime_error("state mismatch");
    +
    3746 }
    +
    3747 }
    -
    3756 }
    -
    3757}
    -
    Provides read-ahead stream capability.
    Definition stream.hpp:1116
    -
    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:1130
    -
    Provides write-back stream capability.
    Definition stream.hpp:1184
    -
    virtual void flush()
    Persists volatile element data.
    Definition stream.hpp:1221
    -
    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:1197
    -
    Basic seekable stream operations.
    Definition stream.hpp:695
    -
    virtual void skip(fsize_t amount)
    Skips given amount of bytes of data on the stream.
    Definition stream.hpp:738
    -
    virtual time_point ctime() const
    Returns file creation time.
    Definition stream.hpp:785
    -
    virtual void lock(fpos_t offset, fsize_t length)
    Locks file section for exclusive access.
    Definition stream.hpp:754
    +
    3748
    +
    3749 protected:
    +
    3750 std::vector<basic_file*> m_files;
    +
    3751 std::vector<uint8_t> m_tmp;
    +
    3752 };
    +
    +
    3753 }
    +
    3754}
    +
    Provides read-ahead stream capability.
    Definition stream.hpp:1118
    +
    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:1132
    +
    Provides write-back stream capability.
    Definition stream.hpp:1186
    +
    virtual void flush()
    Persists volatile element data.
    Definition stream.hpp:1223
    +
    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:1199
    +
    Basic seekable stream operations.
    Definition stream.hpp:696
    +
    virtual void skip(fsize_t amount)
    Skips given amount of bytes of data on the stream.
    Definition stream.hpp:739
    +
    virtual time_point ctime() const
    Returns file creation time.
    Definition stream.hpp:786
    +
    virtual void lock(fpos_t offset, fsize_t length)
    Locks file section for exclusive access.
    Definition stream.hpp:755
    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::default)
    Attempts to detect textfile charset based on UTF16 or UTF8 BOM.
    Definition stream.hpp:858
    -
    fpos_t seekbeg(fpos_t offset)
    Seeks to absolute file position.
    Definition stream.hpp:722
    -
    virtual std::vector< uint8_t > read_remainder(size_t max_length=SIZE_MAX)
    Reads and returns remainder of the stream.
    Definition stream.hpp:697
    -
    virtual void set_mtime(time_point date)
    Sets file modification time.
    Definition stream.hpp:827
    -
    fpos_t seekcur(foff_t offset)
    Seeks to relative from current file position.
    Definition stream.hpp:729
    -
    virtual time_point atime() const
    Returns file access time.
    Definition stream.hpp:793
    -
    virtual void set_ctime(time_point date)
    Sets file create time.
    Definition stream.hpp:809
    +
    charset_id read_charset(charset_id default_charset=charset_id::system)
    Attempts to detect textfile charset based on UTF16 or UTF8 BOM.
    Definition stream.hpp:859
    +
    fpos_t seekbeg(fpos_t offset)
    Seeks to absolute file position.
    Definition stream.hpp:723
    +
    virtual std::vector< uint8_t > read_remainder(size_t max_length=SIZE_MAX)
    Reads and returns remainder of the stream.
    Definition stream.hpp:698
    +
    virtual void set_mtime(time_point date)
    Sets file modification time.
    Definition stream.hpp:828
    +
    fpos_t seekcur(foff_t offset)
    Seeks to relative from current file position.
    Definition stream.hpp:730
    +
    virtual time_point atime() const
    Returns file access time.
    Definition stream.hpp:794
    +
    virtual void set_ctime(time_point date)
    Sets file create time.
    Definition stream.hpp:810
    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:764
    +
    virtual void unlock(fpos_t offset, fsize_t length)
    Unlocks file section for exclusive access.
    Definition stream.hpp:765
    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:801
    -
    fpos_t seekend(foff_t offset)
    Seeks to relative from end file position.
    Definition stream.hpp:736
    -
    virtual void set_atime(time_point date)
    Sets file access time.
    Definition stream.hpp:818
    +
    virtual time_point mtime() const
    Returns file modification time.
    Definition stream.hpp:802
    +
    fpos_t seekend(foff_t offset)
    Seeks to relative from end file position.
    Definition stream.hpp:737
    +
    virtual void set_atime(time_point date)
    Sets file access time.
    Definition stream.hpp:819
    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:2062
    -
    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:2120
    -
    virtual void flush()
    Persists volatile element data.
    Definition stream.hpp:2178
    -
    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:2069
    -
    virtual void close()
    Closes the stream.
    Definition stream.hpp:2167
    -
    ‍UTF-8 byte-order-mark
    Definition stream.hpp:72
    -
    bool ok() const
    Returns true if the stream state is clean i.e. previous operation was succesful.
    Definition stream.hpp:166
    -
    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:596
    -
    size_t write_array(_In_reads_or_z_opt_(num_chars) const wchar_t *wstr, size_t num_chars, charset_id charset)
    Writes array of characters to the stream.
    Definition stream.hpp:426
    -
    state_t state() const
    Returns stream state after last operation.
    Definition stream.hpp:161
    -
    basic & read_str(std::basic_string< _Elem, _Traits, _Ax > &data)
    Reads length-prefixed string from the stream.
    Definition stream.hpp:470
    -
    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:582
    -
    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:609
    -
    virtual void flush()
    Persists volatile element data.
    Definition stream.hpp:117
    -
    virtual void skip(fsize_t amount)
    Skips given amount of bytes of data on the stream.
    Definition stream.hpp:133
    -
    virtual void close()
    Closes the stream.
    Definition stream.hpp:125
    -
    uint8_t read_byte()
    Reads one byte of data.
    Definition stream.hpp:201
    -
    virtual std::vector< uint8_t > read_remainder(size_t max_length=SIZE_MAX)
    Reads and returns remainder of the stream.
    Definition stream.hpp:175
    -
    size_t write_sprintf(_Printf_format_string_params_(2) const char *format, locale_t locale,...)
    Writes formatted string to the stream.
    Definition stream.hpp:568
    -
    size_t readln_and_attach(std::basic_string< wchar_t, _Traits, _Ax > &wstr, charset_id charset)
    Reads stream to the end-of-line or end-of-file and append to str.
    Definition stream.hpp:359
    -
    size_t readln(std::basic_string< char, _Traits, _Ax > &str)
    Reads stream to the end-of-line or end-of-file.
    Definition stream.hpp:297
    -
    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:338
    -
    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:374
    -
    basic & write_str(const T *data)
    Writes string to the stream length-prefixed.
    Definition stream.hpp:495
    -
    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:87
    -
    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:309
    -
    void write_charset(charset_id charset)
    Writes UTF8 or UTF-16 byte-order-mark.
    Definition stream.hpp:555
    -
    size_t readln(std::basic_string< wchar_t, _Traits, _Ax > &wstr, charset_id charset)
    Reads stream to the end-of-line or end-of-file.
    Definition stream.hpp:321
    -
    size_t write_array(const wchar_t *wstr, charset_id charset)
    Writes array of characters to the stream.
    Definition stream.hpp:405
    -
    basic & write_data(const T data)
    Writes one primitive data type.
    Definition stream.hpp:278
    -
    fsize_t write_stream(basic &stream, fsize_t amount=fsize_max)
    Writes content of another stream.
    Definition stream.hpp:530
    -
    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:105
    -
    size_t write_array(const std::basic_string< wchar_t, _Traits, _Ax > &wstr, charset_id charset)
    Writes array of characters to the stream.
    Definition stream.hpp:447
    -
    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:392
    -
    void write_byte(uint8_t byte, fsize_t amount=1)
    Writes a byte of data.
    Definition stream.hpp:212
    -
    basic & read_data(T &data)
    Reads one primitive data type.
    Definition stream.hpp:250
    -
    Buffered read/write stream.
    Definition stream.hpp:1255
    -
    virtual void flush()
    Persists volatile element data.
    Definition stream.hpp:1365
    -
    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:1283
    -
    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:1319
    -
    Buffered OS data stream (file, pipe, socket...)
    Definition stream.hpp:2192
    -
    Cached file.
    Definition stream.hpp:1682
    -
    virtual time_point ctime() const
    Returns file creation time.
    Definition stream.hpp:1934
    -
    fpos_t m_offset
    Logical absolute file position.
    Definition stream.hpp:2050
    -
    virtual void truncate()
    Sets file size - truncates the remainder of file content from the current file position to the end of...
    Definition stream.hpp:1913
    -
    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:1739
    -
    virtual time_point atime() const
    Returns file access time.
    Definition stream.hpp:1939
    -
    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:1906
    -
    virtual void unlock(fpos_t offset, fsize_t length)
    Unlocks file section for exclusive access.
    Definition stream.hpp:1900
    -
    virtual time_point mtime() const
    Returns file modification time.
    Definition stream.hpp:1948
    -
    virtual void close()
    Closes the stream.
    Definition stream.hpp:1854
    -
    virtual void set_mtime(time_point date)
    Sets file modification time.
    Definition stream.hpp:1970
    -
    virtual void lock(fpos_t offset, fsize_t length)
    Locks file section for exclusive access.
    Definition stream.hpp:1894
    -
    virtual void flush()
    Persists volatile element data.
    Definition stream.hpp:1863
    -
    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:1801
    -
    virtual void set_ctime(time_point date)
    Sets file create time.
    Definition stream.hpp:1957
    -
    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:1889
    -
    virtual void set_atime(time_point date)
    Sets file access time.
    Definition stream.hpp:1962
    -
    virtual fpos_t seek(foff_t offset, seek_t how=seek_t::beg)
    Seeks to specified relative file position.
    Definition stream.hpp:1874
    -
    Cached file-system file.
    Definition stream.hpp:2743
    -
    void open(const schar_t *filename, int mode)
    Opens file.
    Definition stream.hpp:2778
    -
    cached_file(const schar_t *filename, int mode, size_t cache_size=default_cache_size)
    Opens file.
    Definition stream.hpp:2759
    -
    Modifies data on the fly when reading from/writing to a source stream.
    Definition stream.hpp:888
    -
    virtual void flush()
    Persists volatile element data.
    Definition stream.hpp:934
    -
    virtual void close()
    Closes the stream.
    Definition stream.hpp:928
    -
    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:912
    -
    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:920
    -
    Compares multiple files to perform the same.
    Definition stream.hpp:3586
    -
    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:3722
    -
    virtual void truncate()
    Sets file size - truncates the remainder of file content from the current file position to the end of...
    Definition stream.hpp:3739
    -
    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:3617
    -
    virtual void close()
    Closes the stream.
    Definition stream.hpp:3650
    -
    virtual void lock(fpos_t offset, fsize_t length)
    Locks file section for exclusive access.
    Definition stream.hpp:3696
    -
    virtual void unlock(fpos_t offset, fsize_t length)
    Unlocks file section for exclusive access.
    Definition stream.hpp:3709
    -
    virtual fpos_t seek(foff_t offset, seek_t how=seek_t::beg)
    Seeks to specified relative file position.
    Definition stream.hpp:3667
    -
    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:3684
    -
    virtual void flush()
    Persists volatile element data.
    Definition stream.hpp:3635
    -
    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:3594
    -
    In-memory FIFO queue.
    Definition stream.hpp:3486
    -
    virtual void close()
    Closes the stream.
    Definition stream.hpp:3557
    -
    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:3534
    -
    size_t size() const
    Returns total size of pending data in the queue.
    Definition stream.hpp:3571
    -
    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:3505
    -
    Limits file reading/writing to a predefined window.
    Definition stream.hpp:1572
    -
    virtual void truncate()
    Sets file size - truncates the remainder of file content from the current file position to the end of...
    Definition stream.hpp:1665
    -
    virtual void flush()
    Persists volatile element data.
    Definition stream.hpp:1615
    -
    virtual void skip(fsize_t amount)
    Skips given amount of bytes of data on the stream.
    Definition stream.hpp:1628
    -
    virtual fpos_t seek(foff_t offset, seek_t how=seek_t::beg)
    Seeks to specified relative file position.
    Definition stream.hpp:1621
    -
    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:1660
    -
    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:1595
    -
    virtual void lock(fpos_t offset, fsize_t length)
    Locks file section for exclusive access.
    Definition stream.hpp:1640
    -
    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:1581
    -
    virtual void unlock(fpos_t offset, fsize_t length)
    Unlocks file section for exclusive access.
    Definition stream.hpp:1650
    -
    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:1634
    -
    virtual void close()
    Closes the stream.
    Definition stream.hpp:1609
    -
    File-system file.
    Definition stream.hpp:2433
    -
    virtual time_point mtime() const
    Returns file modification time.
    Definition stream.hpp:2676
    -
    virtual void unlock(fpos_t offset, fsize_t length)
    Unlocks file section for exclusive access.
    Definition stream.hpp:2569
    -
    file(const schar_t *filename, int mode)
    Opens file.
    Definition stream.hpp:2443
    -
    virtual void set_ctime(time_point date)
    Sets file create time.
    Definition stream.hpp:2690
    -
    virtual time_point atime() const
    Returns file access time.
    Definition stream.hpp:2662
    -
    void open(const schar_t *filename, int mode)
    Opens file.
    Definition stream.hpp:2454
    -
    virtual void set_mtime(time_point date)
    Sets file modification time.
    Definition stream.hpp:2720
    -
    virtual void set_atime(time_point date)
    Sets file access time.
    Definition stream.hpp:2702
    -
    virtual void lock(fpos_t offset, fsize_t length)
    Locks file section for exclusive access.
    Definition stream.hpp:2546
    -
    virtual void truncate()
    Sets file size - truncates the remainder of file content from the current file position to the end of...
    Definition stream.hpp:2612
    -
    virtual time_point ctime() const
    Returns file creation time.
    Definition stream.hpp:2652
    -
    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:2594
    -
    virtual fpos_t seek(foff_t offset, seek_t how=seek_t::beg)
    Seeks to specified relative file position.
    Definition stream.hpp:2507
    -
    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:2528
    -
    Limits reading from/writing to stream to a predefined number of bytes.
    Definition stream.hpp:1413
    -
    fsize_t read_limit
    Number of bytes left that may be read from the stream.
    Definition stream.hpp:1473
    -
    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:1421
    -
    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:1446
    -
    fsize_t write_limit
    Number of bytes left, that can be written to the stream.
    Definition stream.hpp:1474
    -
    In-memory file.
    Definition stream.hpp:2806
    -
    memory_file(const schar_t *filename, int mode)
    Loads content from file-system file.
    Definition stream.hpp:2884
    -
    size_t m_size
    file size
    Definition stream.hpp:3473
    -
    void get(fpos_t offset, T &data)
    Reads data from specified file location This does not move file pointer. It checks for data size asse...
    Definition stream.hpp:3406
    -
    size_t write_stream(basic &stream, size_t amount=SIZE_MAX)
    Writes content of another stream.
    Definition stream.hpp:3228
    -
    uint8_t * m_data
    file data
    Definition stream.hpp:3470
    -
    memory_file & read_data(T &data)
    Reads one primitive data type.
    Definition stream.hpp:3027
    -
    virtual void close()
    Closes the stream.
    Definition stream.hpp:3278
    -
    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:2988
    -
    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:3309
    -
    size_t m_reserved
    reserved file size
    Definition stream.hpp:3474
    -
    memory_file(size_t size, state_t state=state_t::ok)
    Creates an empty file of reserved size.
    Definition stream.hpp:2827
    -
    void reserve(size_t required, bool tight=false) noexcept
    Reallocates memory.
    Definition stream.hpp:2901
    -
    memory_file & read_str(std::basic_string< _Elem, _Traits, _Ax > &data)
    Reads length-prefixed string from the stream.
    Definition stream.hpp:3067
    -
    void write_byte(uint8_t byte, size_t amount=1)
    Writes a byte of data.
    Definition stream.hpp:3122
    -
    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:3369
    -
    size_t m_offset
    file pointer
    Definition stream.hpp:3472
    -
    void save(const schar_t *filename, int mode)
    Saves content to a file-system file.
    Definition stream.hpp:2963
    -
    void load(const schar_t *filename, int mode)
    Loads content from a file-system file.
    Definition stream.hpp:2930
    -
    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:3314
    -
    virtual fpos_t seek(foff_t offset, seek_t how=seek_t::beg)
    Seeks to specified relative file position.
    Definition stream.hpp:3292
    -
    virtual void truncate()
    Sets file size - truncates the remainder of file content from the current file position to the end of...
    Definition stream.hpp:3319
    -
    memory_file & write_data(const T data)
    Writes one primitive data type.
    Definition stream.hpp:3155
    -
    memory_file & write_str(const T *data)
    Writes string to the stream length-prefixed.
    Definition stream.hpp:3193
    -
    bool m_manage
    may reallocate m_data?
    Definition stream.hpp:3471
    -
    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:2874
    -
    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:3098
    -
    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:2851
    -
    const void * data() const
    Returns pointer to data.
    Definition stream.hpp:2986
    -
    Definition stream.hpp:1031
    +
    OS data stream (file, pipe, socket...)
    Definition stream.hpp:2064
    +
    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:2121
    +
    virtual void flush()
    Persists volatile element data.
    Definition stream.hpp:2179
    +
    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:2071
    +
    virtual void close()
    Closes the stream.
    Definition stream.hpp:2168
    +
    ‍UTF-8 byte-order-mark
    Definition stream.hpp:76
    +
    bool ok() const
    Returns true if the stream state is clean i.e. previous operation was succesful.
    Definition stream.hpp:170
    +
    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:600
    +
    size_t write_array(_In_reads_or_z_opt_(num_chars) const wchar_t *wstr, size_t num_chars, charset_id charset)
    Writes array of characters to the stream.
    Definition stream.hpp:430
    +
    state_t state() const
    Returns stream state after last operation.
    Definition stream.hpp:165
    +
    basic & read_str(std::basic_string< _Elem, _Traits, _Ax > &data)
    Reads length-prefixed string from the stream.
    Definition stream.hpp:474
    +
    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:586
    +
    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:613
    +
    virtual void flush()
    Persists volatile element data.
    Definition stream.hpp:121
    +
    virtual void skip(fsize_t amount)
    Skips given amount of bytes of data on the stream.
    Definition stream.hpp:137
    +
    virtual void close()
    Closes the stream.
    Definition stream.hpp:129
    +
    uint8_t read_byte()
    Reads one byte of data.
    Definition stream.hpp:205
    +
    virtual std::vector< uint8_t > read_remainder(size_t max_length=SIZE_MAX)
    Reads and returns remainder of the stream.
    Definition stream.hpp:179
    +
    size_t write_sprintf(_Printf_format_string_params_(2) const char *format, locale_t locale,...)
    Writes formatted string to the stream.
    Definition stream.hpp:572
    +
    size_t readln_and_attach(std::basic_string< wchar_t, _Traits, _Ax > &wstr, charset_id charset)
    Reads stream to the end-of-line or end-of-file and append to str.
    Definition stream.hpp:363
    +
    size_t readln(std::basic_string< char, _Traits, _Ax > &str)
    Reads stream to the end-of-line or end-of-file.
    Definition stream.hpp:301
    +
    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:342
    +
    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:378
    +
    basic & write_str(const T *data)
    Writes string to the stream length-prefixed.
    Definition stream.hpp:499
    +
    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:91
    +
    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:313
    +
    void write_charset(charset_id charset)
    Writes UTF8 or UTF-16 byte-order-mark.
    Definition stream.hpp:559
    +
    size_t readln(std::basic_string< wchar_t, _Traits, _Ax > &wstr, charset_id charset)
    Reads stream to the end-of-line or end-of-file.
    Definition stream.hpp:325
    +
    size_t write_array(const wchar_t *wstr, charset_id charset)
    Writes array of characters to the stream.
    Definition stream.hpp:409
    +
    basic & write_data(const T data)
    Writes one primitive data type.
    Definition stream.hpp:282
    +
    fsize_t write_stream(basic &stream, fsize_t amount=fsize_max)
    Writes content of another stream.
    Definition stream.hpp:534
    +
    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:109
    +
    size_t write_array(const std::basic_string< wchar_t, _Traits, _Ax > &wstr, charset_id charset)
    Writes array of characters to the stream.
    Definition stream.hpp:451
    +
    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:396
    +
    void write_byte(uint8_t byte, fsize_t amount=1)
    Writes a byte of data.
    Definition stream.hpp:216
    +
    basic & read_data(T &data)
    Reads one primitive data type.
    Definition stream.hpp:254
    +
    Buffered read/write stream.
    Definition stream.hpp:1257
    +
    virtual void flush()
    Persists volatile element data.
    Definition stream.hpp:1367
    +
    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:1285
    +
    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:1321
    +
    Buffered OS data stream (file, pipe, socket...)
    Definition stream.hpp:2193
    +
    Cached file.
    Definition stream.hpp:1684
    +
    virtual time_point ctime() const
    Returns file creation time.
    Definition stream.hpp:1936
    +
    fpos_t m_offset
    Logical absolute file position.
    Definition stream.hpp:2052
    +
    virtual void truncate()
    Sets file size - truncates the remainder of file content from the current file position to the end of...
    Definition stream.hpp:1915
    +
    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:1741
    +
    virtual time_point atime() const
    Returns file access time.
    Definition stream.hpp:1941
    +
    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:1908
    +
    virtual void unlock(fpos_t offset, fsize_t length)
    Unlocks file section for exclusive access.
    Definition stream.hpp:1902
    +
    virtual time_point mtime() const
    Returns file modification time.
    Definition stream.hpp:1950
    +
    virtual void close()
    Closes the stream.
    Definition stream.hpp:1856
    +
    virtual void set_mtime(time_point date)
    Sets file modification time.
    Definition stream.hpp:1972
    +
    virtual void lock(fpos_t offset, fsize_t length)
    Locks file section for exclusive access.
    Definition stream.hpp:1896
    +
    virtual void flush()
    Persists volatile element data.
    Definition stream.hpp:1865
    +
    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:1803
    +
    virtual void set_ctime(time_point date)
    Sets file create time.
    Definition stream.hpp:1959
    +
    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:1891
    +
    virtual void set_atime(time_point date)
    Sets file access time.
    Definition stream.hpp:1964
    +
    virtual fpos_t seek(foff_t offset, seek_t how=seek_t::beg)
    Seeks to specified relative file position.
    Definition stream.hpp:1876
    +
    Cached file-system file.
    Definition stream.hpp:2751
    +
    void open(const schar_t *filename, int mode)
    Opens file.
    Definition stream.hpp:2785
    +
    cached_file(const schar_t *filename, int mode, size_t cache_size=default_cache_size)
    Opens file.
    Definition stream.hpp:2767
    +
    Modifies data on the fly when reading from/writing to a source stream.
    Definition stream.hpp:889
    +
    virtual void flush()
    Persists volatile element data.
    Definition stream.hpp:935
    +
    virtual void close()
    Closes the stream.
    Definition stream.hpp:929
    +
    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:913
    +
    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:921
    +
    Compares multiple files to perform the same.
    Definition stream.hpp:3583
    +
    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:3719
    +
    virtual void truncate()
    Sets file size - truncates the remainder of file content from the current file position to the end of...
    Definition stream.hpp:3736
    +
    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:3614
    +
    virtual void close()
    Closes the stream.
    Definition stream.hpp:3647
    +
    virtual void lock(fpos_t offset, fsize_t length)
    Locks file section for exclusive access.
    Definition stream.hpp:3693
    +
    virtual void unlock(fpos_t offset, fsize_t length)
    Unlocks file section for exclusive access.
    Definition stream.hpp:3706
    +
    virtual fpos_t seek(foff_t offset, seek_t how=seek_t::beg)
    Seeks to specified relative file position.
    Definition stream.hpp:3664
    +
    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:3681
    +
    virtual void flush()
    Persists volatile element data.
    Definition stream.hpp:3632
    +
    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:3591
    +
    In-memory FIFO queue.
    Definition stream.hpp:3483
    +
    virtual void close()
    Closes the stream.
    Definition stream.hpp:3554
    +
    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:3531
    +
    size_t size() const
    Returns total size of pending data in the queue.
    Definition stream.hpp:3568
    +
    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:3502
    +
    Limits file reading/writing to a predefined window.
    Definition stream.hpp:1574
    +
    virtual void truncate()
    Sets file size - truncates the remainder of file content from the current file position to the end of...
    Definition stream.hpp:1667
    +
    virtual void flush()
    Persists volatile element data.
    Definition stream.hpp:1617
    +
    virtual void skip(fsize_t amount)
    Skips given amount of bytes of data on the stream.
    Definition stream.hpp:1630
    +
    virtual fpos_t seek(foff_t offset, seek_t how=seek_t::beg)
    Seeks to specified relative file position.
    Definition stream.hpp:1623
    +
    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:1662
    +
    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:1597
    +
    virtual void lock(fpos_t offset, fsize_t length)
    Locks file section for exclusive access.
    Definition stream.hpp:1642
    +
    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:1583
    +
    virtual void unlock(fpos_t offset, fsize_t length)
    Unlocks file section for exclusive access.
    Definition stream.hpp:1652
    +
    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:1636
    +
    virtual void close()
    Closes the stream.
    Definition stream.hpp:1611
    +
    File-system file.
    Definition stream.hpp:2434
    +
    virtual time_point mtime() const
    Returns file modification time.
    Definition stream.hpp:2682
    +
    virtual void unlock(fpos_t offset, fsize_t length)
    Unlocks file section for exclusive access.
    Definition stream.hpp:2575
    +
    file(const schar_t *filename, int mode)
    Opens file.
    Definition stream.hpp:2444
    +
    virtual void set_ctime(time_point date)
    Sets file create time.
    Definition stream.hpp:2696
    +
    virtual time_point atime() const
    Returns file access time.
    Definition stream.hpp:2668
    +
    void open(const schar_t *filename, int mode)
    Opens file.
    Definition stream.hpp:2455
    +
    virtual void set_mtime(time_point date)
    Sets file modification time.
    Definition stream.hpp:2727
    +
    virtual void set_atime(time_point date)
    Sets file access time.
    Definition stream.hpp:2708
    +
    virtual void lock(fpos_t offset, fsize_t length)
    Locks file section for exclusive access.
    Definition stream.hpp:2552
    +
    virtual void truncate()
    Sets file size - truncates the remainder of file content from the current file position to the end of...
    Definition stream.hpp:2618
    +
    virtual time_point ctime() const
    Returns file creation time.
    Definition stream.hpp:2658
    +
    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:2600
    +
    virtual fpos_t seek(foff_t offset, seek_t how=seek_t::beg)
    Seeks to specified relative file position.
    Definition stream.hpp:2513
    +
    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:2534
    +
    Limits reading from/writing to stream to a predefined number of bytes.
    Definition stream.hpp:1415
    +
    fsize_t read_limit
    Number of bytes left that may be read from the stream.
    Definition stream.hpp:1475
    +
    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:1448
    +
    fsize_t write_limit
    Number of bytes left, that can be written to the stream.
    Definition stream.hpp:1476
    +
    In-memory file.
    Definition stream.hpp:2813
    +
    memory_file(const schar_t *filename, int mode)
    Loads content from file-system file.
    Definition stream.hpp:2891
    +
    size_t m_size
    file size
    Definition stream.hpp:3470
    +
    void get(fpos_t offset, T &data)
    Reads data from specified file location This does not move file pointer. It checks for data size asse...
    Definition stream.hpp:3410
    +
    size_t write_stream(basic &stream, size_t amount=SIZE_MAX)
    Writes content of another stream.
    Definition stream.hpp:3235
    +
    uint8_t * m_data
    file data
    Definition stream.hpp:3467
    +
    memory_file & read_data(T &data)
    Reads one primitive data type.
    Definition stream.hpp:3034
    +
    virtual void close()
    Closes the stream.
    Definition stream.hpp:3285
    +
    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:2995
    +
    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:3316
    +
    size_t m_reserved
    reserved file size
    Definition stream.hpp:3471
    +
    memory_file(size_t size, state_t state=state_t::ok)
    Creates an empty file of reserved size.
    Definition stream.hpp:2834
    +
    void reserve(size_t required, bool tight=false) noexcept
    Reallocates memory.
    Definition stream.hpp:2908
    +
    memory_file & read_str(std::basic_string< _Elem, _Traits, _Ax > &data)
    Reads length-prefixed string from the stream.
    Definition stream.hpp:3074
    +
    void write_byte(uint8_t byte, size_t amount=1)
    Writes a byte of data.
    Definition stream.hpp:3129
    +
    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:3376
    +
    size_t m_offset
    file pointer
    Definition stream.hpp:3469
    +
    void save(const schar_t *filename, int mode)
    Saves content to a file-system file.
    Definition stream.hpp:2970
    +
    void load(const schar_t *filename, int mode)
    Loads content from a file-system file.
    Definition stream.hpp:2937
    +
    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:3321
    +
    virtual fpos_t seek(foff_t offset, seek_t how=seek_t::beg)
    Seeks to specified relative file position.
    Definition stream.hpp:3299
    +
    virtual void truncate()
    Sets file size - truncates the remainder of file content from the current file position to the end of...
    Definition stream.hpp:3326
    +
    memory_file & write_data(const T data)
    Writes one primitive data type.
    Definition stream.hpp:3162
    +
    memory_file & write_str(const T *data)
    Writes string to the stream length-prefixed.
    Definition stream.hpp:3200
    +
    bool m_manage
    may reallocate m_data?
    Definition stream.hpp:3468
    +
    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:2881
    +
    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:3105
    +
    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:2858
    +
    const void * data() const
    Returns pointer to data.
    Definition stream.hpp:2993
    +
    Definition stream.hpp:1032
    enum stdex::stream::replicator::worker::op_t op
    Operation to perform.
    -
    size_t num_written
    Number of bytes written.
    Definition stream.hpp:1078
    -
    size_t length
    Byte limit of data to write.
    Definition stream.hpp:1077
    -
    const void * data
    Data to write.
    Definition stream.hpp:1076
    -
    Replicates writing of the same data to multiple streams.
    Definition stream.hpp:948
    -
    void push_back(basic *source)
    Adds stream on the list.
    Definition stream.hpp:967
    -
    virtual void flush()
    Persists volatile element data.
    Definition stream.hpp:1024
    -
    void remove(basic *source)
    Removes stream from the list.
    Definition stream.hpp:975
    -
    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:992
    -
    virtual void close()
    Closes the stream.
    Definition stream.hpp:1019
    -
    Limits reading from/writing to stream to a predefined window.
    Definition stream.hpp:1481
    -
    fpos_t write_offset
    Number of bytes to discard on write.
    Definition stream.hpp:1565
    -
    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:1522
    -
    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:1489
    -
    fpos_t read_offset
    Number of bytes to skip on read.
    Definition stream.hpp:1564
    -
    Operating system object (file, pipe, anything with an OS handle etc.)
    Definition system.hpp:76
    -
    virtual void close()
    Closes object.
    Definition system.hpp:117
    +
    size_t num_written
    Number of bytes written.
    Definition stream.hpp:1080
    +
    size_t length
    Byte limit of data to write.
    Definition stream.hpp:1079
    +
    const void * data
    Data to write.
    Definition stream.hpp:1078
    +
    Replicates writing of the same data to multiple streams.
    Definition stream.hpp:949
    +
    void push_back(basic *source)
    Adds stream on the list.
    Definition stream.hpp:968
    +
    virtual void flush()
    Persists volatile element data.
    Definition stream.hpp:1025
    +
    void remove(basic *source)
    Removes stream from the list.
    Definition stream.hpp:976
    +
    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:993
    +
    virtual void close()
    Closes the stream.
    Definition stream.hpp:1020
    +
    Limits reading from/writing to stream to a predefined window.
    Definition stream.hpp:1483
    +
    fpos_t write_offset
    Number of bytes to discard on write.
    Definition stream.hpp:1567
    +
    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:1524
    +
    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:1491
    +
    fpos_t read_offset
    Number of bytes to skip on read.
    Definition stream.hpp:1566
    +
    Operating system object (file, pipe, anything with an OS handle etc.)
    Definition system.hpp:78
    +
    virtual void close()
    Closes object.
    Definition system.hpp:119
    Numerical interval.
    Definition interval.hpp:18
    bool contains(T x) const
    Is value in interval?
    Definition interval.hpp:70
    bool empty() const
    Is interval empty?
    Definition interval.hpp:54
    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:1390
    -
    Definition stream.hpp:2028
    -
    interval< fpos_t > region
    valid data region
    Definition stream.hpp:2036
    -
    Definition stream.hpp:3575
    +
    Definition stream.hpp:1392
    +
    Definition stream.hpp:2030
    +
    interval< fpos_t > region
    valid data region
    Definition stream.hpp:2038
    +
    Definition stream.hpp:3572
    diff --git a/string_8hpp_source.html b/string_8hpp_source.html index cdb7371a6..995b9fadf 100644 --- a/string_8hpp_source.html +++ b/string_8hpp_source.html @@ -89,816 +89,838 @@ $(document).ready(function() { init_codefold(0); });
    5
    6#pragma once
    7
    -
    8#include "sal.hpp"
    +
    8#include "compat.hpp"
    9#include <assert.h>
    10#include <ctype.h>
    11#include <locale.h>
    12#include <stdarg.h>
    13#include <stdint.h>
    -
    14#include <memory>
    -
    15#include <stdexcept>
    -
    16
    -
    17namespace stdex
    -
    18{
    -
    19#ifdef _WIN32
    -
    20 using locale_t = _locale_t;
    -
    21
    -
    22 inline locale_t create_locale(_In_ int category, _In_z_ const char* locale) { return _create_locale(category, locale); }
    -
    23 inline locale_t create_locale(_In_ int category, _In_z_ const wchar_t* locale) { return _wcreate_locale(category, locale); }
    -
    24 inline void free_locale(_In_opt_ _locale_t locale) { _free_locale(locale); }
    -
    25#else
    -
    26 using locale_t = ::locale_t;
    -
    27#endif
    -
    28
    -
    - -
    33 {
    -
    -
    37 void operator()(_In_ locale_t locale) const
    -
    38 {
    -
    39 free_locale(locale);
    -
    40 }
    +
    14#include <stdio.h>
    +
    15#include <stdarg.h>
    +
    16#ifdef __APPLE__
    +
    17#include <xlocale.h>
    +
    18#endif
    +
    19#include <locale>
    +
    20#include <memory>
    +
    21#include <stdexcept>
    +
    22
    +
    23namespace stdex
    +
    24{
    +
    25#ifdef _WIN32
    +
    26 using locale_t = _locale_t;
    +
    27
    +
    28 inline locale_t create_locale(_In_ int category, _In_z_ const char* locale) { return _create_locale(category, locale); }
    +
    29 inline locale_t create_locale(_In_ int category, _In_z_ const wchar_t* locale) { return _wcreate_locale(category, locale); }
    +
    30 inline void free_locale(_In_opt_ _locale_t locale) { _free_locale(locale); }
    +
    31#else
    +
    32 using locale_t = ::locale_t;
    +
    33#endif
    +
    34
    +
    + +
    39 {
    +
    +
    43 void operator()(_In_ locale_t locale) const
    +
    44 {
    +
    45#ifdef _WIN32
    +
    46 free_locale(locale);
    +
    47#else
    +
    48 freelocale(locale);
    +
    49#endif
    +
    50 }
    -
    41 };
    +
    51 };
    -
    42
    -
    46 using locale = std::unique_ptr<__crt_locale_pointers, free_locale_delete>;
    -
    47
    -
    51 static locale locale_C(_create_locale(LC_ALL, "C"));
    52
    -
    56#ifdef _WIN32
    -
    57 typedef wchar_t utf16_t;
    -
    58#else
    -
    59 typedef char16_t utf16_t;
    -
    60#endif
    -
    61
    -
    67 inline bool is_high_surrogate(_In_ utf16_t chr)
    -
    68 {
    -
    69 return 0xd800 < chr && chr < 0xdc00;
    -
    70 }
    -
    71
    -
    77 inline bool is_low_surrogate(_In_ utf16_t chr)
    -
    78 {
    -
    79 return 0xdc00 < chr && chr < 0xe000;
    -
    80 }
    -
    81
    -
    87 inline bool is_surrogate_pair(_In_reads_(2) const utf16_t* str)
    -
    88 {
    -
    89 return is_high_surrogate(str[0]) && is_low_surrogate(str[1]);
    -
    90 }
    -
    91
    -
    97 inline char32_t surrogate_pair_to_ucs4(_In_reads_(2) const utf16_t* str)
    -
    98 {
    -
    99 assert(is_surrogate_pair(str));
    -
    100 return
    -
    101 ((char32_t)(str[0] - 0xd800) << 10) +
    -
    102 (char32_t)(str[1] - 0xdc00) +
    -
    103 0x10000;
    -
    104 }
    -
    105
    -
    111 inline void ucs4_to_surrogate_pair(_Out_writes_(2) utf16_t* str, _In_ char32_t chr)
    -
    112 {
    -
    113 assert(chr >= 0x10000);
    -
    114 chr -= 0x10000;
    -
    115 str[0] = 0xd800 + (char32_t)((chr >> 10) & 0x3ff);
    -
    116 str[1] = 0xdc00 + (char32_t)(chr & 0x3ff);
    -
    117 }
    -
    118
    -
    124 inline bool iscombining(_In_ char32_t chr)
    -
    125 {
    -
    126 return
    -
    127 0x0300 <= chr && chr < 0x0370 ||
    -
    128 0x1dc0 <= chr && chr < 0x1e00 ||
    -
    129 0x20d0 <= chr && chr < 0x2100 ||
    -
    130 0xfe20 <= chr && chr < 0xfe30;
    -
    131 }
    -
    132
    -
    138 template <class T>
    -
    139 inline size_t islbreak(_In_ T chr)
    -
    140 {
    -
    141 return chr == '\n' || chr == '\r';
    -
    142 }
    -
    143
    -
    150 template <class T>
    -
    151 inline size_t islbreak(_In_reads_or_z_opt_(count) const T* chr, _In_ size_t count)
    -
    152 {
    -
    153 _Analysis_assume_(chr || !count);
    -
    154 if (count >= 2 && (chr[0] == '\r' && chr[1] == '\n' || chr[0] == '\n' && chr[1] == '\r'))
    -
    155 return 2;
    -
    156 if (count > 1 && (chr[0] == '\n' || chr[0] == '\r'))
    -
    157 return 1;
    -
    158 return 0;
    -
    159 }
    -
    160
    -
    167 inline size_t glyphlen(_In_reads_or_z_opt_(count) const wchar_t* glyph, _In_ size_t count)
    -
    168 {
    -
    169 _Analysis_assume_(glyph || !count);
    -
    170 if (count) {
    -
    171#ifdef _WIN32
    -
    172 size_t i = count < 2 || !is_surrogate_pair(glyph) ? 1 : 2;
    -
    173#else
    -
    174 size_t i = 1;
    -
    175#endif
    -
    176 for (; i < count && iscombining(glyph[i]); ++i);
    -
    177 return i;
    -
    178 }
    -
    179 return 0;
    -
    180 }
    -
    181
    -
    189 template <class T>
    -
    190 inline size_t strlen(_In_z_ const T* str)
    -
    191 {
    -
    192 assert(str);
    -
    193 size_t i;
    -
    194 for (i = 0; str[i]; ++i);
    -
    195 return i;
    -
    196 }
    -
    197
    -
    206 template <class T>
    -
    207 inline size_t strnlen(_In_reads_or_z_opt_(count) const T* str, _In_ size_t count)
    -
    208 {
    -
    209 assert(str || !count);
    -
    210 size_t i;
    -
    211 for (i = 0; i < count && str[i]; ++i);
    -
    212 return i;
    -
    213 }
    -
    214
    -
    215 constexpr auto npos{ static_cast<size_t>(-1) };
    -
    216
    -
    225 template <class T>
    -
    226 inline size_t strchr(_In_z_ const T* str, _In_ T chr)
    -
    227 {
    -
    228 assert(str);
    -
    229 for (size_t i = 0; str[i]; ++i)
    -
    230 if (str[i] == chr) return i;
    -
    231 return npos;
    -
    232 }
    -
    233
    -
    243 template <class T>
    -
    244 inline size_t strnchr(
    -
    245 _In_reads_or_z_opt_(count) const T* str,
    -
    246 _In_ size_t count,
    -
    247 _In_ T chr)
    -
    248 {
    -
    249 assert(str || !count);
    -
    250 for (size_t i = 0; i < count && str[i]; ++i)
    -
    251 if (str[i] == chr) return i;
    -
    252 return npos;
    -
    253 }
    -
    254
    -
    264 template <class T>
    -
    265 inline size_t strrnchr(
    -
    266 _In_reads_or_z_opt_(count) const T* str,
    -
    267 _In_ size_t count,
    -
    268 _In_ T chr)
    -
    269 {
    -
    270 assert(str || !count);
    -
    271 size_t z = npos;
    +
    56#if defined(_WIN32)
    +
    57 using locale = std::unique_ptr<__crt_locale_pointers, free_locale_delete>;
    +
    58#elif defined(__APPLE__)
    +
    59 using locale = std::unique_ptr<struct _xlocale, free_locale_delete>;
    +
    60#else
    +
    61 using locale = std::unique_ptr<struct __locale_struct, free_locale_delete>;
    +
    62#endif
    +
    63
    +
    67#if defined(_WIN32)
    +
    68 static locale locale_C(_create_locale(LC_ALL, "C"));
    +
    69#elif defined(__APPLE__)
    +
    70 static locale locale_C(newlocale(LC_ALL_MASK, "C", LC_GLOBAL_LOCALE));
    +
    71#else
    +
    72#error TODO
    +
    73#endif
    +
    74
    +
    78#ifdef _WIN32
    +
    79 typedef wchar_t utf16_t;
    +
    80#else
    +
    81 typedef char16_t utf16_t;
    +
    82#endif
    +
    83
    +
    89 inline bool is_high_surrogate(_In_ utf16_t chr)
    +
    90 {
    +
    91 return 0xd800 < chr && chr < 0xdc00;
    +
    92 }
    +
    93
    +
    99 inline bool is_low_surrogate(_In_ utf16_t chr)
    +
    100 {
    +
    101 return 0xdc00 < chr && chr < 0xe000;
    +
    102 }
    +
    103
    +
    109 inline bool is_surrogate_pair(_In_reads_(2) const utf16_t* str)
    +
    110 {
    +
    111 return is_high_surrogate(str[0]) && is_low_surrogate(str[1]);
    +
    112 }
    +
    113
    +
    119 inline char32_t surrogate_pair_to_ucs4(_In_reads_(2) const utf16_t* str)
    +
    120 {
    +
    121 assert(is_surrogate_pair(str));
    +
    122 return
    +
    123 ((char32_t)(str[0] - 0xd800) << 10) +
    +
    124 (char32_t)(str[1] - 0xdc00) +
    +
    125 0x10000;
    +
    126 }
    +
    127
    +
    133 inline void ucs4_to_surrogate_pair(_Out_writes_(2) utf16_t* str, _In_ char32_t chr)
    +
    134 {
    +
    135 assert(chr >= 0x10000);
    +
    136 chr -= 0x10000;
    +
    137 str[0] = 0xd800 + (char32_t)((chr >> 10) & 0x3ff);
    +
    138 str[1] = 0xdc00 + (char32_t)(chr & 0x3ff);
    +
    139 }
    +
    140
    +
    146 inline bool iscombining(_In_ char32_t chr)
    +
    147 {
    +
    148 return
    +
    149 (0x0300 <= chr && chr < 0x0370) ||
    +
    150 (0x1dc0 <= chr && chr < 0x1e00) ||
    +
    151 (0x20d0 <= chr && chr < 0x2100) ||
    +
    152 (0xfe20 <= chr && chr < 0xfe30);
    +
    153 }
    +
    154
    +
    160 template <class T>
    +
    161 inline size_t islbreak(_In_ T chr)
    +
    162 {
    +
    163 return chr == '\n' || chr == '\r';
    +
    164 }
    +
    165
    +
    172 template <class T>
    +
    173 inline size_t islbreak(_In_reads_or_z_opt_(count) const T* chr, _In_ size_t count)
    +
    174 {
    +
    175 _Analysis_assume_(chr || !count);
    +
    176 if (count >= 2 && ((chr[0] == '\r' && chr[1] == '\n') || (chr[0] == '\n' && chr[1] == '\r')))
    +
    177 return 2;
    +
    178 if (count > 1 && (chr[0] == '\n' || chr[0] == '\r'))
    +
    179 return 1;
    +
    180 return 0;
    +
    181 }
    +
    182
    +
    189 inline size_t glyphlen(_In_reads_or_z_opt_(count) const wchar_t* glyph, _In_ size_t count)
    +
    190 {
    +
    191 _Analysis_assume_(glyph || !count);
    +
    192 if (count) {
    +
    193#ifdef _WIN32
    +
    194 size_t i = count < 2 || !is_surrogate_pair(glyph) ? 1 : 2;
    +
    195#else
    +
    196 size_t i = 1;
    +
    197#endif
    +
    198 for (; i < count && iscombining(glyph[i]); ++i);
    +
    199 return i;
    +
    200 }
    +
    201 return 0;
    +
    202 }
    +
    203
    +
    211 template <class T>
    +
    212 inline size_t strlen(_In_z_ const T* str)
    +
    213 {
    +
    214 assert(str);
    +
    215 size_t i;
    +
    216 for (i = 0; str[i]; ++i);
    +
    217 return i;
    +
    218 }
    +
    219
    +
    228 template <class T>
    +
    229 inline size_t strnlen(_In_reads_or_z_opt_(count) const T* str, _In_ size_t count)
    +
    230 {
    +
    231 assert(str || !count);
    +
    232 size_t i;
    +
    233 for (i = 0; i < count && str[i]; ++i);
    +
    234 return i;
    +
    235 }
    +
    236
    +
    237 constexpr auto npos{ static_cast<size_t>(-1) };
    +
    238
    +
    247 template <class T>
    +
    248 inline size_t strchr(_In_z_ const T* str, _In_ T chr)
    +
    249 {
    +
    250 assert(str);
    +
    251 for (size_t i = 0; str[i]; ++i)
    +
    252 if (str[i] == chr) return i;
    +
    253 return npos;
    +
    254 }
    +
    255
    +
    265 template <class T>
    +
    266 inline size_t strnchr(
    +
    267 _In_reads_or_z_opt_(count) const T* str,
    +
    268 _In_ size_t count,
    +
    269 _In_ T chr)
    +
    270 {
    +
    271 assert(str || !count);
    272 for (size_t i = 0; i < count && str[i]; ++i)
    -
    273 if (str[i] == chr) z = i;
    -
    274 return z;
    +
    273 if (str[i] == chr) return i;
    +
    274 return npos;
    275 }
    276
    286 template <class T>
    -
    287 inline size_t strnichr(
    +
    287 inline size_t strrnchr(
    288 _In_reads_or_z_opt_(count) const T* str,
    289 _In_ size_t count,
    -
    290 _In_ T chr,
    -
    291 _In_ const std::locale& locale)
    -
    292 {
    -
    293 assert(str || !count);
    -
    294 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
    -
    295 chr = ctype.tolower(chr);
    -
    296 for (size_t i = 0; i < count && str[i]; ++i)
    -
    297 if (ctype.tolower(str[i]) == chr) return i;
    -
    298 return npos;
    -
    299 }
    -
    300
    -
    310 template <class T>
    -
    311 inline size_t strrnichr(
    -
    312 _In_reads_or_z_opt_(count) const T* str,
    -
    313 _In_ size_t count,
    -
    314 _In_ T chr,
    -
    315 _In_ const std::locale& locale)
    -
    316 {
    -
    317 assert(str || !count);
    -
    318 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
    -
    319 chr = ctype.tolower(chr);
    -
    320 size_t z = npos;
    -
    321 for (size_t i = 0; i < count && str[i]; ++i)
    -
    322 if (ctype.tolower(str[i]) == chr) z = i;
    -
    323 return z;
    -
    324 }
    -
    325
    -
    336 template <class T1, class T2>
    -
    337 inline int strncmp(
    -
    338 _In_reads_or_z_opt_(count1) const T1* str1, _In_ size_t count1,
    -
    339 _In_reads_or_z_opt_(count2) const T2* str2, _In_ size_t count2)
    -
    340 {
    -
    341 assert(str1 || !count1);
    -
    342 assert(str2 || !count2);
    -
    343 size_t i; T1 a; T2 b;
    -
    344 for (i = 0; i < count1 && i < count2 && ((a = str1[i]) | (b = str2[i])); ++i) {
    -
    345 if (a > b) return +1;
    -
    346 if (a < b) return -1;
    -
    347 }
    -
    348 if (i < count1 && str1[i]) return +1;
    -
    349 if (i < count2 && str2[i]) return -1;
    -
    350 return 0;
    -
    351 }
    -
    352
    -
    363 template <class T>
    -
    364 inline int strncoll(
    -
    365 _In_reads_or_z_opt_(count1) const T* str1, _In_ size_t count1,
    -
    366 _In_reads_or_z_opt_(count2) const T* str2, _In_ size_t count2,
    -
    367 _In_ const std::locale& locale)
    -
    368 {
    -
    369 assert(str1 || !count1);
    -
    370 assert(str2 || !count2);
    -
    371 auto& collate = std::use_facet<std::collate<T>>(locale);
    -
    372 return collate.compare(str1, str1 + count1, str2, str2 + count2);
    +
    290 _In_ T chr)
    +
    291 {
    +
    292 assert(str || !count);
    +
    293 size_t z = npos;
    +
    294 for (size_t i = 0; i < count && str[i]; ++i)
    +
    295 if (str[i] == chr) z = i;
    +
    296 return z;
    +
    297 }
    +
    298
    +
    308 template <class T>
    +
    309 inline size_t strnichr(
    +
    310 _In_reads_or_z_opt_(count) const T* str,
    +
    311 _In_ size_t count,
    +
    312 _In_ T chr,
    +
    313 _In_ const std::locale& locale)
    +
    314 {
    +
    315 assert(str || !count);
    +
    316 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
    +
    317 chr = ctype.tolower(chr);
    +
    318 for (size_t i = 0; i < count && str[i]; ++i)
    +
    319 if (ctype.tolower(str[i]) == chr) return i;
    +
    320 return npos;
    +
    321 }
    +
    322
    +
    332 template <class T>
    +
    333 inline size_t strrnichr(
    +
    334 _In_reads_or_z_opt_(count) const T* str,
    +
    335 _In_ size_t count,
    +
    336 _In_ T chr,
    +
    337 _In_ const std::locale& locale)
    +
    338 {
    +
    339 assert(str || !count);
    +
    340 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
    +
    341 chr = ctype.tolower(chr);
    +
    342 size_t z = npos;
    +
    343 for (size_t i = 0; i < count && str[i]; ++i)
    +
    344 if (ctype.tolower(str[i]) == chr) z = i;
    +
    345 return z;
    +
    346 }
    +
    347
    +
    358 template <class T1, class T2>
    +
    359 inline int strncmp(
    +
    360 _In_reads_or_z_opt_(count1) const T1* str1, _In_ size_t count1,
    +
    361 _In_reads_or_z_opt_(count2) const T2* str2, _In_ size_t count2)
    +
    362 {
    +
    363 assert(str1 || !count1);
    +
    364 assert(str2 || !count2);
    +
    365 size_t i; T1 a; T2 b;
    +
    366 for (i = 0; i < count1 && i < count2 && ((a = str1[i]) | (b = str2[i])); ++i) {
    +
    367 if (a > b) return +1;
    +
    368 if (a < b) return -1;
    +
    369 }
    +
    370 if (i < count1 && str1[i]) return +1;
    +
    371 if (i < count2 && str2[i]) return -1;
    +
    372 return 0;
    373 }
    374
    -
    385 template <class T1, class T2>
    -
    386 inline int strnicmp(
    -
    387 _In_reads_or_z_opt_(count1) const T1* str1, _In_ size_t count1,
    -
    388 _In_reads_or_z_opt_(count2) const T2* str2, _In_ size_t count2,
    +
    385 template <class T>
    +
    386 inline int strncoll(
    +
    387 _In_reads_or_z_opt_(count1) const T* str1, _In_ size_t count1,
    +
    388 _In_reads_or_z_opt_(count2) const T* str2, _In_ size_t count2,
    389 _In_ const std::locale& locale)
    390 {
    391 assert(str1 || !count1);
    392 assert(str2 || !count2);
    -
    393 size_t i; T1 a; T2 b;
    -
    394 const auto& ctype1 = std::use_facet<std::ctype<T1>>(locale);
    -
    395 const auto& ctype2 = std::use_facet<std::ctype<T2>>(locale);
    -
    396 for (i = 0; i < count1 && i < count2 && ((a = ctype1.tolower(str1[i])) | (b = ctype2.tolower(str2[i]))); i++) {
    -
    397 if (a > b) return +1;
    -
    398 if (a < b) return -1;
    -
    399 }
    -
    400 if (i < count1 && str1[i]) return +1;
    -
    401 if (i < count2 && str2[i]) return -1;
    -
    402 return 0;
    -
    403 }
    -
    404
    -
    413 template <class T1, class T2>
    -
    414 inline size_t strstr(
    -
    415 _In_z_ const T1* str,
    -
    416 _In_z_ const T2* sample)
    -
    417 {
    -
    418 assert(str);
    -
    419 assert(sample);
    -
    420 for (size_t offset = 0;; ++offset) {
    -
    421 for (size_t i = offset, j = 0;; ++i, ++j) {
    -
    422 if (!sample[j])
    -
    423 return offset;
    -
    424 if (!str[i])
    -
    425 return npos;
    -
    426 if (str[i] != sample[j])
    -
    427 break;
    -
    428 }
    -
    429 }
    -
    430 }
    -
    431
    -
    441 template <class T1, class T2>
    -
    442 inline size_t strnstr(
    -
    443 _In_reads_or_z_opt_(count) const T1* str,
    -
    444 _In_ size_t count,
    -
    445 _In_z_ const T2* sample)
    -
    446 {
    -
    447 assert(str || !count);
    -
    448 assert(sample);
    -
    449 for (size_t offset = 0;; ++offset) {
    -
    450 for (size_t i = offset, j = 0;; ++i, ++j) {
    -
    451 if (!sample[j])
    -
    452 return offset;
    -
    453 if (i >= count || !str[i])
    -
    454 return npos;
    -
    455 if (str[i] != sample[j])
    -
    456 break;
    -
    457 }
    -
    458 }
    -
    459 }
    -
    460
    -
    469 template <class T1, class T2>
    -
    470 inline size_t stristr(
    -
    471 _In_z_ const T1* str,
    -
    472 _In_z_ const T2* sample,
    -
    473 _In_ const std::locale& locale)
    -
    474 {
    -
    475 assert(str);
    -
    476 assert(sample);
    -
    477 const auto& ctype1 = std::use_facet<std::ctype<T1>>(locale);
    -
    478 const auto& ctype2 = std::use_facet<std::ctype<T2>>(locale);
    -
    479 for (size_t offset = 0;; ++offset) {
    -
    480 for (size_t i = offset, j = 0;; ++i, ++j) {
    -
    481 if (!sample[j])
    -
    482 return offset;
    -
    483 if (!str[i])
    -
    484 return npos;
    -
    485 if (ctype1.tolower(str[i]) != ctype2.tolower(sample[j]))
    -
    486 break;
    -
    487 }
    -
    488 }
    -
    489 }
    -
    490
    -
    500 template <class T1, class T2>
    -
    501 inline size_t strnistr(
    -
    502 _In_reads_or_z_opt_(count) const T1* str,
    -
    503 _In_ size_t count,
    -
    504 _In_z_ const T2* sample,
    -
    505 _In_ const std::locale& locale)
    -
    506 {
    -
    507 assert(str || !count);
    -
    508 assert(sample);
    -
    509 const auto& ctype1 = std::use_facet<std::ctype<T1>>(locale);
    -
    510 const auto& ctype2 = std::use_facet<std::ctype<T2>>(locale);
    -
    511 for (size_t offset = 0;; ++offset) {
    -
    512 for (size_t i = offset, j = 0;; ++i, ++j) {
    -
    513 if (!sample[j])
    -
    514 return offset;
    -
    515 if (i >= count || !str[i])
    -
    516 return npos;
    -
    517 if (ctype1.tolower(str[i]) != ctype2.tolower(sample[j]))
    -
    518 break;
    -
    519 }
    -
    520 }
    -
    521 }
    -
    522
    -
    531 template <class T1, class T2>
    -
    532 inline size_t strcpy(
    -
    533 _Out_writes_z_(_String_length_(src) + 1) T1* dst,
    -
    534 _In_z_ const T2* src)
    -
    535 {
    -
    536 assert(dst && src);
    -
    537 for (size_t i = 0; ; ++i) {
    -
    538 if ((dst[i] = src[i]) == 0)
    -
    539 return i;
    -
    540 }
    -
    541 }
    -
    542
    -
    552 template <class T1, class T2>
    -
    553 inline size_t strncpy(
    -
    554 _Out_writes_(count) _Post_maybez_ T1* dst,
    -
    555 _In_reads_or_z_opt_(count) const T2* src, _In_ size_t count)
    -
    556 {
    -
    557 assert(dst && src || !count);
    -
    558 for (size_t i = 0; ; ++i) {
    -
    559 if (i >= count)
    -
    560 return i;
    -
    561 if ((dst[i] = src[i]) == 0)
    -
    562 return i;
    -
    563 }
    -
    564 }
    -
    565
    -
    576 template <class T1, class T2>
    -
    577 inline size_t strncpy(
    -
    578 _Out_writes_(count_dst) _Post_maybez_ T1* dst, _In_ size_t count_dst,
    -
    579 _In_reads_or_z_opt_(count_src) const T2* src, _In_ size_t count_src)
    -
    580 {
    -
    581 assert(dst || !count_dst);
    -
    582 assert(src || !count_src);
    -
    583 for (size_t i = 0; ; ++i)
    -
    584 {
    -
    585 if (i > count_dst)
    -
    586 return i;
    -
    587 if (i > count_src) {
    -
    588 dst[i] = 0;
    -
    589 return i;
    -
    590 }
    -
    591 if ((dst[i] = src[i]) == 0)
    -
    592 return i;
    -
    593 }
    -
    594 }
    -
    595
    -
    604 template <class T1, class T2>
    -
    605 inline size_t strcat(
    -
    606 _In_z_ _Out_writes_z_(_String_length_(dst) + _String_length_(src) + 1) T1* dst,
    -
    607 _In_z_ const T2* src)
    -
    608 {
    -
    609 assert(dst && src);
    -
    610 for (size_t i = 0, j = stdex::strlen<T1>(dst); ; ++i, ++j) {
    -
    611 if ((dst[j] = src[i]) == 0)
    -
    612 return j;
    -
    613 }
    -
    614 }
    -
    615
    -
    625 template <class T1, class T2>
    -
    626 inline size_t strncat(
    -
    627 _Out_writes_(count) _Post_maybez_ T1* dst,
    -
    628 _In_reads_or_z_opt_(count) const T2* src, _In_ size_t count)
    -
    629 {
    -
    630 assert(dst && src || !count);
    -
    631 for (size_t i = 0, j = stdex::strlen<T1>(dst); ; ++i, ++j) {
    -
    632 if (i >= count)
    -
    633 return j;
    -
    634 if ((dst[j] = src[i]) == 0)
    -
    635 return j;
    -
    636 }
    -
    637 }
    -
    638
    -
    649 template <class T1, class T2>
    -
    650 inline size_t strncat(
    -
    651 _Out_writes_(count_dst) _Post_maybez_ T1* dst, _In_ size_t count_dst,
    -
    652 _In_reads_or_z_opt_(count_src) const T2* src, _In_ size_t count_src)
    -
    653 {
    -
    654 assert(dst || !count_dst);
    -
    655 assert(src || !count_src);
    -
    656 for (size_t i = 0, j = stdex::strnlen<T1>(dst, count_dst); ; ++i, ++j)
    -
    657 {
    -
    658 if (j > count_dst)
    -
    659 return j;
    -
    660 if (i > count_src) {
    -
    661 dst[j] = 0;
    -
    662 return j;
    -
    663 }
    -
    664 if ((dst[j] = src[i]) == 0)
    -
    665 return j;
    -
    666 }
    -
    667 }
    -
    668
    -
    679 template <class T>
    -
    680 inline _Check_return_ _Ret_maybenull_z_ T* strdup(_In_opt_z_ const T* str)
    -
    681 {
    -
    682 if (!str) _Unlikely_
    -
    683 return nullptr;
    -
    684 size_t count = strlen(str) + 1;
    -
    685 T* dst = new T[count];
    -
    686 strncpy(dst, count, str, SIZE_MAX);
    -
    687 return dst;
    -
    688 }
    -
    689
    +
    393 auto& collate = std::use_facet<std::collate<T>>(locale);
    +
    394 return collate.compare(str1, str1 + count1, str2, str2 + count2);
    +
    395 }
    +
    396
    +
    407 template <class T1, class T2>
    +
    408 inline int strnicmp(
    +
    409 _In_reads_or_z_opt_(count1) const T1* str1, _In_ size_t count1,
    +
    410 _In_reads_or_z_opt_(count2) const T2* str2, _In_ size_t count2,
    +
    411 _In_ const std::locale& locale)
    +
    412 {
    +
    413 assert(str1 || !count1);
    +
    414 assert(str2 || !count2);
    +
    415 size_t i; T1 a; T2 b;
    +
    416 const auto& ctype1 = std::use_facet<std::ctype<T1>>(locale);
    +
    417 const auto& ctype2 = std::use_facet<std::ctype<T2>>(locale);
    +
    418 for (i = 0; i < count1 && i < count2 && ((a = ctype1.tolower(str1[i])) | (b = ctype2.tolower(str2[i]))); i++) {
    +
    419 if (a > b) return +1;
    +
    420 if (a < b) return -1;
    +
    421 }
    +
    422 if (i < count1 && str1[i]) return +1;
    +
    423 if (i < count2 && str2[i]) return -1;
    +
    424 return 0;
    +
    425 }
    +
    426
    +
    435 template <class T1, class T2>
    +
    436 inline size_t strstr(
    +
    437 _In_z_ const T1* str,
    +
    438 _In_z_ const T2* sample)
    +
    439 {
    +
    440 assert(str);
    +
    441 assert(sample);
    +
    442 for (size_t offset = 0;; ++offset) {
    +
    443 for (size_t i = offset, j = 0;; ++i, ++j) {
    +
    444 if (!sample[j])
    +
    445 return offset;
    +
    446 if (!str[i])
    +
    447 return npos;
    +
    448 if (str[i] != sample[j])
    +
    449 break;
    +
    450 }
    +
    451 }
    +
    452 }
    +
    453
    +
    463 template <class T1, class T2>
    +
    464 inline size_t strnstr(
    +
    465 _In_reads_or_z_opt_(count) const T1* str,
    +
    466 _In_ size_t count,
    +
    467 _In_z_ const T2* sample)
    +
    468 {
    +
    469 assert(str || !count);
    +
    470 assert(sample);
    +
    471 for (size_t offset = 0;; ++offset) {
    +
    472 for (size_t i = offset, j = 0;; ++i, ++j) {
    +
    473 if (!sample[j])
    +
    474 return offset;
    +
    475 if (i >= count || !str[i])
    +
    476 return npos;
    +
    477 if (str[i] != sample[j])
    +
    478 break;
    +
    479 }
    +
    480 }
    +
    481 }
    +
    482
    +
    491 template <class T1, class T2>
    +
    492 inline size_t stristr(
    +
    493 _In_z_ const T1* str,
    +
    494 _In_z_ const T2* sample,
    +
    495 _In_ const std::locale& locale)
    +
    496 {
    +
    497 assert(str);
    +
    498 assert(sample);
    +
    499 const auto& ctype1 = std::use_facet<std::ctype<T1>>(locale);
    +
    500 const auto& ctype2 = std::use_facet<std::ctype<T2>>(locale);
    +
    501 for (size_t offset = 0;; ++offset) {
    +
    502 for (size_t i = offset, j = 0;; ++i, ++j) {
    +
    503 if (!sample[j])
    +
    504 return offset;
    +
    505 if (!str[i])
    +
    506 return npos;
    +
    507 if (ctype1.tolower(str[i]) != ctype2.tolower(sample[j]))
    +
    508 break;
    +
    509 }
    +
    510 }
    +
    511 }
    +
    512
    +
    522 template <class T1, class T2>
    +
    523 inline size_t strnistr(
    +
    524 _In_reads_or_z_opt_(count) const T1* str,
    +
    525 _In_ size_t count,
    +
    526 _In_z_ const T2* sample,
    +
    527 _In_ const std::locale& locale)
    +
    528 {
    +
    529 assert(str || !count);
    +
    530 assert(sample);
    +
    531 const auto& ctype1 = std::use_facet<std::ctype<T1>>(locale);
    +
    532 const auto& ctype2 = std::use_facet<std::ctype<T2>>(locale);
    +
    533 for (size_t offset = 0;; ++offset) {
    +
    534 for (size_t i = offset, j = 0;; ++i, ++j) {
    +
    535 if (!sample[j])
    +
    536 return offset;
    +
    537 if (i >= count || !str[i])
    +
    538 return npos;
    +
    539 if (ctype1.tolower(str[i]) != ctype2.tolower(sample[j]))
    +
    540 break;
    +
    541 }
    +
    542 }
    +
    543 }
    +
    544
    +
    553 template <class T1, class T2>
    +
    554 inline size_t strcpy(
    +
    555 _Out_writes_z_(_String_length_(src) + 1) T1* dst,
    +
    556 _In_z_ const T2* src)
    +
    557 {
    +
    558 assert(dst && src);
    +
    559 for (size_t i = 0; ; ++i) {
    +
    560 if ((dst[i] = src[i]) == 0)
    +
    561 return i;
    +
    562 }
    +
    563 }
    +
    564
    +
    574 template <class T1, class T2>
    +
    575 inline size_t strncpy(
    +
    576 _Out_writes_(count) _Post_maybez_ T1* dst,
    +
    577 _In_reads_or_z_opt_(count) const T2* src, _In_ size_t count)
    +
    578 {
    +
    579 assert(dst && src || !count);
    +
    580 for (size_t i = 0; ; ++i) {
    +
    581 if (i >= count)
    +
    582 return i;
    +
    583 if ((dst[i] = src[i]) == 0)
    +
    584 return i;
    +
    585 }
    +
    586 }
    +
    587
    +
    598 template <class T1, class T2>
    +
    599 inline size_t strncpy(
    +
    600 _Out_writes_(count_dst) _Post_maybez_ T1* dst, _In_ size_t count_dst,
    +
    601 _In_reads_or_z_opt_(count_src) const T2* src, _In_ size_t count_src)
    +
    602 {
    +
    603 assert(dst || !count_dst);
    +
    604 assert(src || !count_src);
    +
    605 for (size_t i = 0; ; ++i)
    +
    606 {
    +
    607 if (i > count_dst)
    +
    608 return i;
    +
    609 if (i > count_src) {
    +
    610 dst[i] = 0;
    +
    611 return i;
    +
    612 }
    +
    613 if ((dst[i] = src[i]) == 0)
    +
    614 return i;
    +
    615 }
    +
    616 }
    +
    617
    +
    626 template <class T1, class T2>
    +
    627 inline size_t strcat(
    +
    628 _In_z_ _Out_writes_z_(_String_length_(dst) + _String_length_(src) + 1) T1* dst,
    +
    629 _In_z_ const T2* src)
    +
    630 {
    +
    631 assert(dst && src);
    +
    632 for (size_t i = 0, j = stdex::strlen<T1>(dst); ; ++i, ++j) {
    +
    633 if ((dst[j] = src[i]) == 0)
    +
    634 return j;
    +
    635 }
    +
    636 }
    +
    637
    +
    647 template <class T1, class T2>
    +
    648 inline size_t strncat(
    +
    649 _Out_writes_(count) _Post_maybez_ T1* dst,
    +
    650 _In_reads_or_z_opt_(count) const T2* src, _In_ size_t count)
    +
    651 {
    +
    652 assert(dst && src || !count);
    +
    653 for (size_t i = 0, j = stdex::strlen<T1>(dst); ; ++i, ++j) {
    +
    654 if (i >= count)
    +
    655 return j;
    +
    656 if ((dst[j] = src[i]) == 0)
    +
    657 return j;
    +
    658 }
    +
    659 }
    +
    660
    +
    671 template <class T1, class T2>
    +
    672 inline size_t strncat(
    +
    673 _Out_writes_(count_dst) _Post_maybez_ T1* dst, _In_ size_t count_dst,
    +
    674 _In_reads_or_z_opt_(count_src) const T2* src, _In_ size_t count_src)
    +
    675 {
    +
    676 assert(dst || !count_dst);
    +
    677 assert(src || !count_src);
    +
    678 for (size_t i = 0, j = stdex::strnlen<T1>(dst, count_dst); ; ++i, ++j)
    +
    679 {
    +
    680 if (j > count_dst)
    +
    681 return j;
    +
    682 if (i > count_src) {
    +
    683 dst[j] = 0;
    +
    684 return j;
    +
    685 }
    +
    686 if ((dst[j] = src[i]) == 0)
    +
    687 return j;
    +
    688 }
    +
    689 }
    +
    690
    701 template <class T>
    -
    702 inline _Ret_z_ T* strndup(
    -
    703 _In_reads_or_z_opt_(count) const T* str,
    -
    704 _In_ size_t count)
    -
    705 {
    -
    706 T* dst = new T[count];
    -
    707 strncpy(dst, count, str, SIZE_MAX);
    -
    708 return dst;
    -
    709 }
    -
    710
    -
    720 template <class T>
    -
    721 inline size_t crlf2nl(_Out_writes_z_(strlen(src)) T* dst, _In_z_ const T* src)
    -
    722 {
    -
    723 assert(dst);
    -
    724 assert(src);
    -
    725 size_t i, j;
    -
    726 for (i = j = 0; src[j];) {
    -
    727 if (src[j] != '\r' || src[j + 1] != '\n')
    -
    728 dst[i++] = src[j++];
    -
    729 else {
    -
    730 dst[i++] = '\n';
    -
    731 j += 2;
    -
    732 }
    -
    733 }
    -
    734 dst[i] = 0;
    -
    735 return i;
    -
    736 }
    -
    737
    -
    739 template <class T, class T_bin>
    -
    740 inline T_bin strtoint(
    -
    741 _In_reads_or_z_opt_(count) const T* str, _In_ size_t count,
    -
    742 _Out_opt_ size_t* end,
    -
    743 _In_ int radix,
    -
    744 _Out_ uint8_t& flags)
    -
    745 {
    -
    746 assert(str || !count);
    -
    747 assert(radix == 0 || 2 <= radix && radix <= 36);
    -
    748
    -
    749 size_t i = 0;
    -
    750 T_bin value = 0, digit,
    -
    751 max_ui = (T_bin)-1,
    -
    752 max_ui_pre1, max_ui_pre2;
    -
    753
    -
    754 flags = 0;
    -
    755
    -
    756 // Skip leading spaces.
    -
    757 for (;; ++i) {
    -
    758 if (i >= count || !str[i]) goto error;
    -
    759 if (!isspace(str[i])) break;
    -
    760 }
    -
    761
    -
    762 // Read the sign.
    -
    763 if (str[i] == '+') {
    -
    764 flags &= ~0x01;
    -
    765 ++i;
    -
    766 if (i >= count || !str[i]) goto error;
    -
    767 }
    -
    768 else if (str[i] == '-') {
    -
    769 flags |= 0x01;
    -
    770 ++i;
    -
    771 if (i >= count || !str[i]) goto error;
    -
    772 }
    -
    773
    -
    774 if (radix == 16) {
    -
    775 // On hexadecimal, allow leading 0x.
    -
    776 if (str[i] == '0' && i + 1 < count && (str[i + 1] == 'x' || str[i + 1] == 'X')) {
    -
    777 i += 2;
    -
    778 if (i >= count || !str[i]) goto error;
    -
    779 }
    -
    780 }
    -
    781 else if (!radix) {
    -
    782 // Autodetect radix.
    -
    783 if (str[i] == '0') {
    -
    784 ++i;
    -
    785 if (i >= count || !str[i]) goto error;
    -
    786 if (str[i] == 'x' || str[i] == 'X') {
    -
    787 radix = 16;
    -
    788 ++i;
    -
    789 if (i >= count || !str[i]) goto error;
    -
    790 }
    -
    791 else
    -
    792 radix = 8;
    -
    793 }
    -
    794 else
    -
    795 radix = 10;
    -
    796 }
    -
    797
    -
    798 // We have the radix.
    -
    799 max_ui_pre1 = max_ui / (T_bin)radix;
    -
    800 max_ui_pre2 = max_ui % (T_bin)radix;
    -
    801 for (;;) {
    -
    802 if ('0' <= str[i] && str[i] <= '9')
    -
    803 digit = (T_bin)str[i] - '0';
    -
    804 else if ('A' <= str[i] && str[i] <= 'Z')
    -
    805 digit = (T_bin)str[i] - 'A' + '\x0a';
    -
    806 else if ('a' <= str[i] && str[i] <= 'z')
    -
    807 digit = (T_bin)str[i] - 'a' + '\x0a';
    -
    808 else
    -
    809 goto error;
    -
    810 if (digit >= (T_bin)radix)
    -
    811 goto error;
    -
    812
    -
    813 if (value < max_ui_pre1 || // Multiplication nor addition will not overflow.
    -
    814 value == max_ui_pre1 && digit <= max_ui_pre2) // Small digits will not overflow.
    -
    815 value = value * (T_bin)radix + digit;
    -
    816 else {
    -
    817 // Overflow!
    -
    818 flags |= 0x02;
    -
    819 }
    -
    820
    -
    821 ++i;
    -
    822 if (i >= count || !str[i])
    -
    823 goto error;
    -
    824 }
    -
    825
    -
    826 error:
    -
    827 if (end) *end = i;
    -
    828 return value;
    -
    829 }
    -
    831
    -
    842 template <class T, class T_bin>
    -
    843 T_bin strtoint(
    -
    844 _In_reads_or_z_opt_(count) const T* str, _In_ size_t count,
    -
    845 _Out_opt_ size_t* end,
    -
    846 _In_ int radix)
    -
    847 {
    -
    848 uint8_t flags;
    -
    849 T_bin value;
    -
    850
    -
    851 switch (sizeof(T_bin)) {
    -
    852 case 1:
    -
    853 value = (T_bin)strtoint<T, uint8_t>(str, count, end, radix, flags);
    -
    854 if ((flags & 0x01) && (value & 0x80)) {
    -
    855 // Sign bit is 1 => overflow.
    -
    856 flags |= 0x02;
    -
    857 }
    -
    858 return (flags & 0x02) ?
    -
    859 (flags & 0x01) ? (T_bin)0x80 : (T_bin)0x7f :
    -
    860 (flags & 0x01) ? -value : value;
    -
    861
    -
    862 case 2:
    -
    863 value = (T_bin)strtoint<T, uint16_t>(str, count, end, radix, flags);
    -
    864 if ((flags & 0x01) && (value & 0x8000)) {
    -
    865 // Sign bit is 1 => overflow.
    -
    866 flags |= 0x02;
    -
    867 }
    -
    868 return (flags & 0x02) ?
    -
    869 (flags & 0x01) ? (T_bin)0x8000 : (T_bin)0x7fff :
    -
    870 (flags & 0x01) ? -value : value;
    -
    871
    -
    872 case 4:
    -
    873 value = (T_bin)strtoint<T, uint32_t>(str, count, end, radix, flags);
    -
    874 if ((flags & 0x01) && (value & 0x80000000)) {
    -
    875 // Sign bit is 1 => overflow.
    -
    876 flags |= 0x02;
    -
    877 }
    -
    878 return (flags & 0x02) ?
    -
    879 (flags & 0x01) ? (T_bin)0x80000000 : (T_bin)0x7fffffff :
    -
    880 (flags & 0x01) ? -value : value;
    -
    881
    -
    882 case 8:
    -
    883 value = (T_bin)strtoint<T, uint64_t>(str, count, end, radix, flags);
    -
    884 if ((flags & 0x01) && (value & 0x8000000000000000)) {
    -
    885 // Sign bit is 1 => overflow.
    -
    886 flags |= 0x02;
    -
    887 }
    -
    888 return (flags & 0x02) ?
    -
    889 (flags & 0x01) ? (T_bin)0x8000000000000000 : (T_bin)0x7fffffffffffffff :
    -
    890 (flags & 0x01) ? -value : value;
    -
    891
    -
    892 default:
    -
    893 throw std::invalid_argument("Unsupported bit length");
    -
    894 }
    -
    895 }
    -
    896
    -
    907 template <class T, class T_bin>
    -
    908 inline T_bin strtouint(
    -
    909 _In_reads_or_z_opt_(count) const T* str,
    -
    910 _In_ size_t count,
    -
    911 _Out_opt_ size_t* end,
    -
    912 _In_ int radix)
    -
    913 {
    -
    914 uint8_t flags;
    -
    915 T_bin value;
    -
    916
    -
    917 switch (sizeof(T_bin)) {
    -
    918 case 1: value = (T_bin)strtoint<T, uint8_t>(str, count, end, radix, flags); break;
    -
    919 case 2: value = (T_bin)strtoint<T, uint16_t>(str, count, end, radix, flags); break;
    -
    920 case 4: value = (T_bin)strtoint<T, uint32_t>(str, count, end, radix, flags); break;
    -
    921 case 8: value = (T_bin)strtoint<T, uint64_t>(str, count, end, radix, flags); break;
    -
    922 default: throw std::invalid_argument("Unsupported bit length");
    -
    923 }
    -
    924
    -
    925 return (flags & 0x02) ?
    -
    926 (flags & 0x01) ? (T_bin)0 : (T_bin)-1 :
    -
    927 (flags & 0x01) ? ~value : value;
    -
    928 }
    -
    929
    -
    940 template <class T>
    -
    941 inline int32_t strto32(
    -
    942 _In_reads_or_z_opt_(count) const T* str, _In_ size_t count,
    -
    943 _Out_opt_ size_t* end,
    -
    944 _In_ int radix)
    -
    945 {
    -
    946 return strtoint<T, int32_t>(str, count, end, radix);
    -
    947 }
    -
    948
    -
    959 template <class T>
    -
    960 inline int64_t strto64(
    -
    961 _In_reads_or_z_opt_(count) const T* str, _In_ size_t count,
    -
    962 _Out_opt_ size_t* end,
    -
    963 _In_ int radix)
    -
    964 {
    -
    965 return strtoint<T, int64_t>(str, count, end, radix);
    -
    966 }
    -
    967
    -
    979 template <class T>
    -
    980 inline intptr_t strtoi(
    -
    981 _In_reads_or_z_opt_(count) const T* str, _In_ size_t count,
    -
    982 _Out_opt_ size_t* end,
    -
    983 _In_ int radix)
    -
    984 {
    -
    985#if defined(_WIN64) || defined(__LP64__)
    -
    986 return (intptr_t)strto64(str, count, end, radix);
    -
    987#else
    -
    988 return (intptr_t)strto32(str, count, end, radix);
    -
    989#endif
    -
    990 }
    -
    991
    -
    1002 template <class T>
    -
    1003 inline uint32_t strtou32(
    -
    1004 _In_reads_or_z_opt_(count) const T* str, _In_ size_t count,
    -
    1005 _Out_opt_ size_t* end,
    -
    1006 _In_ int radix)
    -
    1007 {
    -
    1008 return strtouint<T, uint32_t>(str, count, end, radix);
    -
    1009 }
    -
    1010
    -
    1021 template <class T>
    -
    1022 inline uint64_t strtou64(
    -
    1023 _In_reads_or_z_opt_(count) const T* str, _In_ size_t count,
    -
    1024 _Out_opt_ size_t* end,
    -
    1025 _In_ int radix)
    -
    1026 {
    -
    1027 return strtouint<T, uint64_t>(str, count, end, radix);
    -
    1028 }
    -
    1029
    -
    1041 template <class T>
    -
    1042 inline size_t strtoui(
    -
    1043 _In_reads_or_z_opt_(count) const T* str, _In_ size_t count,
    -
    1044 _Out_opt_ size_t* end,
    -
    1045 _In_ int radix)
    -
    1046 {
    -
    1047#if defined(_WIN64) || defined(__LP64__)
    -
    1048 return (size_t)strtou64(str, count, end, radix);
    -
    1049#else
    -
    1050 return (size_t)strtou32(str, count, end, radix);
    -
    1051#endif
    -
    1052 }
    -
    1053
    -
    1055 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)
    -
    1056 {
    -
    1057 int r;
    -
    1058#ifdef _WIN32
    -
    1059 // Don't use _vsnprintf_s(). It terminates the string even if we want to print to the edge of the buffer.
    -
    1060#pragma warning(suppress: 4996)
    -
    1061 r = _vsnprintf_l(str, capacity, format, locale, arg);
    -
    1062#else
    -
    1063 r = vsnprintf(str, capacity, format, arg);
    -
    1064#endif
    -
    1065 if (r == -1 && strnlen(str, capacity) == capacity) {
    -
    1066 // Buffer overrun. Estimate buffer size for the next iteration.
    -
    1067 capacity += std::max<size_t>(capacity / 8, 0x80);
    -
    1068 if (capacity > INT_MAX)
    -
    1069 throw std::invalid_argument("string too big");
    -
    1070 return (int)capacity;
    -
    1071 }
    -
    1072 return r;
    -
    1073 }
    -
    1074
    -
    1075 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)
    -
    1076 {
    -
    1077 int r;
    -
    1078
    -
    1079#ifdef _WIN32
    -
    1080 // Don't use _vsnwprintf_s(). It terminates the string even if we want to print to the edge of the buffer.
    -
    1081#pragma warning(suppress: 4996)
    -
    1082 r = _vsnwprintf_l(str, capacity, format, locale, arg);
    -
    1083#else
    -
    1084 r = vswprintf(str, capacity, format, arg);
    -
    1085#endif
    -
    1086 if (r == -1 && strnlen(str, capacity) == capacity) {
    -
    1087 // Buffer overrun. Estimate buffer size for the next iteration.
    -
    1088 capacity += std::max<size_t>(capacity / 8, 0x80);
    -
    1089 if (capacity > INT_MAX)
    -
    1090 throw std::invalid_argument("string too big");
    -
    1091 return (int)capacity;
    -
    1092 }
    -
    1093 return r;
    -
    1094 }
    +
    702 inline _Check_return_ _Ret_maybenull_z_ T* strdup(_In_opt_z_ const T* str)
    +
    703 {
    +
    704 if (!str) _Unlikely_
    +
    705 return nullptr;
    +
    706 size_t count = strlen(str) + 1;
    +
    707 T* dst = new T[count];
    +
    708 strncpy(dst, count, str, SIZE_MAX);
    +
    709 return dst;
    +
    710 }
    +
    711
    +
    723 template <class T>
    +
    724 inline _Ret_z_ T* strndup(
    +
    725 _In_reads_or_z_opt_(count) const T* str,
    +
    726 _In_ size_t count)
    +
    727 {
    +
    728 T* dst = new T[count];
    +
    729 strncpy(dst, count, str, SIZE_MAX);
    +
    730 return dst;
    +
    731 }
    +
    732
    +
    742 template <class T>
    +
    743 inline size_t crlf2nl(_Out_writes_z_(strlen(src)) T* dst, _In_z_ const T* src)
    +
    744 {
    +
    745 assert(dst);
    +
    746 assert(src);
    +
    747 size_t i, j;
    +
    748 for (i = j = 0; src[j];) {
    +
    749 if (src[j] != '\r' || src[j + 1] != '\n')
    +
    750 dst[i++] = src[j++];
    +
    751 else {
    +
    752 dst[i++] = '\n';
    +
    753 j += 2;
    +
    754 }
    +
    755 }
    +
    756 dst[i] = 0;
    +
    757 return i;
    +
    758 }
    +
    759
    +
    761 template <class T, class T_bin>
    +
    762 inline T_bin strtoint(
    +
    763 _In_reads_or_z_opt_(count) const T* str, _In_ size_t count,
    +
    764 _Out_opt_ size_t* end,
    +
    765 _In_ int radix,
    +
    766 _Out_ uint8_t& flags)
    +
    767 {
    +
    768 assert(str || !count);
    +
    769 assert(radix == 0 || 2 <= radix && radix <= 36);
    +
    770
    +
    771 size_t i = 0;
    +
    772 T_bin value = 0, digit,
    +
    773 max_ui = (T_bin)-1,
    +
    774 max_ui_pre1, max_ui_pre2;
    +
    775
    +
    776 flags = 0;
    +
    777
    +
    778 // Skip leading spaces.
    +
    779 for (;; ++i) {
    +
    780 if (i >= count || !str[i]) goto error;
    +
    781 if (!isspace(str[i])) break;
    +
    782 }
    +
    783
    +
    784 // Read the sign.
    +
    785 if (str[i] == '+') {
    +
    786 flags &= ~0x01;
    +
    787 ++i;
    +
    788 if (i >= count || !str[i]) goto error;
    +
    789 }
    +
    790 else if (str[i] == '-') {
    +
    791 flags |= 0x01;
    +
    792 ++i;
    +
    793 if (i >= count || !str[i]) goto error;
    +
    794 }
    +
    795
    +
    796 if (radix == 16) {
    +
    797 // On hexadecimal, allow leading 0x.
    +
    798 if (str[i] == '0' && i + 1 < count && (str[i + 1] == 'x' || str[i + 1] == 'X')) {
    +
    799 i += 2;
    +
    800 if (i >= count || !str[i]) goto error;
    +
    801 }
    +
    802 }
    +
    803 else if (!radix) {
    +
    804 // Autodetect radix.
    +
    805 if (str[i] == '0') {
    +
    806 ++i;
    +
    807 if (i >= count || !str[i]) goto error;
    +
    808 if (str[i] == 'x' || str[i] == 'X') {
    +
    809 radix = 16;
    +
    810 ++i;
    +
    811 if (i >= count || !str[i]) goto error;
    +
    812 }
    +
    813 else
    +
    814 radix = 8;
    +
    815 }
    +
    816 else
    +
    817 radix = 10;
    +
    818 }
    +
    819
    +
    820 // We have the radix.
    +
    821 max_ui_pre1 = max_ui / (T_bin)radix;
    +
    822 max_ui_pre2 = max_ui % (T_bin)radix;
    +
    823 for (;;) {
    +
    824 if ('0' <= str[i] && str[i] <= '9')
    +
    825 digit = (T_bin)str[i] - '0';
    +
    826 else if ('A' <= str[i] && str[i] <= 'Z')
    +
    827 digit = (T_bin)str[i] - 'A' + '\x0a';
    +
    828 else if ('a' <= str[i] && str[i] <= 'z')
    +
    829 digit = (T_bin)str[i] - 'a' + '\x0a';
    +
    830 else
    +
    831 goto error;
    +
    832 if (digit >= (T_bin)radix)
    +
    833 goto error;
    +
    834
    +
    835 if (value < max_ui_pre1 || // Multiplication nor addition will not overflow.
    +
    836 (value == max_ui_pre1 && digit <= max_ui_pre2)) // Small digits will not overflow.
    +
    837 value = value * (T_bin)radix + digit;
    +
    838 else {
    +
    839 // Overflow!
    +
    840 flags |= 0x02;
    +
    841 }
    +
    842
    +
    843 ++i;
    +
    844 if (i >= count || !str[i])
    +
    845 goto error;
    +
    846 }
    +
    847
    +
    848 error:
    +
    849 if (end) *end = i;
    +
    850 return value;
    +
    851 }
    +
    853
    +
    864 template <class T, class T_bin>
    +
    865 T_bin strtoint(
    +
    866 _In_reads_or_z_opt_(count) const T* str, _In_ size_t count,
    +
    867 _Out_opt_ size_t* end,
    +
    868 _In_ int radix)
    +
    869 {
    +
    870 uint8_t flags;
    +
    871 T_bin value;
    +
    872
    +
    873 switch (sizeof(T_bin)) {
    +
    874 case 1:
    +
    875 value = (T_bin)strtoint<T, uint8_t>(str, count, end, radix, flags);
    +
    876 if ((flags & 0x01) && (value & 0x80)) {
    +
    877 // Sign bit is 1 => overflow.
    +
    878 flags |= 0x02;
    +
    879 }
    +
    880 return (flags & 0x02) ?
    +
    881 (flags & 0x01) ? (T_bin)0x80 : (T_bin)0x7f :
    +
    882 (flags & 0x01) ? -value : value;
    +
    883
    +
    884 case 2:
    +
    885 value = (T_bin)strtoint<T, uint16_t>(str, count, end, radix, flags);
    +
    886 if ((flags & 0x01) && (value & 0x8000)) {
    +
    887 // Sign bit is 1 => overflow.
    +
    888 flags |= 0x02;
    +
    889 }
    +
    890 return (flags & 0x02) ?
    +
    891 (flags & 0x01) ? (T_bin)0x8000 : (T_bin)0x7fff :
    +
    892 (flags & 0x01) ? -value : value;
    +
    893
    +
    894 case 4:
    +
    895 value = (T_bin)strtoint<T, uint32_t>(str, count, end, radix, flags);
    +
    896 if ((flags & 0x01) && (value & 0x80000000)) {
    +
    897 // Sign bit is 1 => overflow.
    +
    898 flags |= 0x02;
    +
    899 }
    +
    900 return (flags & 0x02) ?
    +
    901 (flags & 0x01) ? (T_bin)0x80000000 : (T_bin)0x7fffffff :
    +
    902 (flags & 0x01) ? -value : value;
    +
    903
    +
    904 case 8:
    +
    905 value = (T_bin)strtoint<T, uint64_t>(str, count, end, radix, flags);
    +
    906 if ((flags & 0x01) && (value & 0x8000000000000000)) {
    +
    907 // Sign bit is 1 => overflow.
    +
    908 flags |= 0x02;
    +
    909 }
    +
    910 return (flags & 0x02) ?
    +
    911 (flags & 0x01) ? (T_bin)0x8000000000000000 : (T_bin)0x7fffffffffffffff :
    +
    912 (flags & 0x01) ? -value : value;
    +
    913
    +
    914 default:
    +
    915 throw std::invalid_argument("Unsupported bit length");
    +
    916 }
    +
    917 }
    +
    918
    +
    929 template <class T, class T_bin>
    +
    930 inline T_bin strtouint(
    +
    931 _In_reads_or_z_opt_(count) const T* str,
    +
    932 _In_ size_t count,
    +
    933 _Out_opt_ size_t* end,
    +
    934 _In_ int radix)
    +
    935 {
    +
    936 uint8_t flags;
    +
    937 T_bin value;
    +
    938
    +
    939 switch (sizeof(T_bin)) {
    +
    940 case 1: value = (T_bin)strtoint<T, uint8_t>(str, count, end, radix, flags); break;
    +
    941 case 2: value = (T_bin)strtoint<T, uint16_t>(str, count, end, radix, flags); break;
    +
    942 case 4: value = (T_bin)strtoint<T, uint32_t>(str, count, end, radix, flags); break;
    +
    943 case 8: value = (T_bin)strtoint<T, uint64_t>(str, count, end, radix, flags); break;
    +
    944 default: throw std::invalid_argument("Unsupported bit length");
    +
    945 }
    +
    946
    +
    947 return (flags & 0x02) ?
    +
    948 (flags & 0x01) ? (T_bin)0 : (T_bin)-1 :
    +
    949 (flags & 0x01) ? ~value : value;
    +
    950 }
    +
    951
    +
    962 template <class T>
    +
    963 inline int32_t strto32(
    +
    964 _In_reads_or_z_opt_(count) const T* str, _In_ size_t count,
    +
    965 _Out_opt_ size_t* end,
    +
    966 _In_ int radix)
    +
    967 {
    +
    968 return strtoint<T, int32_t>(str, count, end, radix);
    +
    969 }
    +
    970
    +
    981 template <class T>
    +
    982 inline int64_t strto64(
    +
    983 _In_reads_or_z_opt_(count) const T* str, _In_ size_t count,
    +
    984 _Out_opt_ size_t* end,
    +
    985 _In_ int radix)
    +
    986 {
    +
    987 return strtoint<T, int64_t>(str, count, end, radix);
    +
    988 }
    +
    989
    +
    1001 template <class T>
    +
    1002 inline intptr_t strtoi(
    +
    1003 _In_reads_or_z_opt_(count) const T* str, _In_ size_t count,
    +
    1004 _Out_opt_ size_t* end,
    +
    1005 _In_ int radix)
    +
    1006 {
    +
    1007#if defined(_WIN64) || defined(__LP64__)
    +
    1008 return (intptr_t)strto64(str, count, end, radix);
    +
    1009#else
    +
    1010 return (intptr_t)strto32(str, count, end, radix);
    +
    1011#endif
    +
    1012 }
    +
    1013
    +
    1024 template <class T>
    +
    1025 inline uint32_t strtou32(
    +
    1026 _In_reads_or_z_opt_(count) const T* str, _In_ size_t count,
    +
    1027 _Out_opt_ size_t* end,
    +
    1028 _In_ int radix)
    +
    1029 {
    +
    1030 return strtouint<T, uint32_t>(str, count, end, radix);
    +
    1031 }
    +
    1032
    +
    1043 template <class T>
    +
    1044 inline uint64_t strtou64(
    +
    1045 _In_reads_or_z_opt_(count) const T* str, _In_ size_t count,
    +
    1046 _Out_opt_ size_t* end,
    +
    1047 _In_ int radix)
    +
    1048 {
    +
    1049 return strtouint<T, uint64_t>(str, count, end, radix);
    +
    1050 }
    +
    1051
    +
    1063 template <class T>
    +
    1064 inline size_t strtoui(
    +
    1065 _In_reads_or_z_opt_(count) const T* str, _In_ size_t count,
    +
    1066 _Out_opt_ size_t* end,
    +
    1067 _In_ int radix)
    +
    1068 {
    +
    1069#if defined(_WIN64) || defined(__LP64__)
    +
    1070 return (size_t)strtou64(str, count, end, radix);
    +
    1071#else
    +
    1072 return (size_t)strtou32(str, count, end, radix);
    +
    1073#endif
    +
    1074 }
    +
    1075
    +
    1077 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)
    +
    1078 {
    +
    1079 int r;
    +
    1080#ifdef _WIN32
    +
    1081 // Don't use _vsnprintf_s(). It terminates the string even if we want to print to the edge of the buffer.
    +
    1082#pragma warning(suppress: 4996)
    +
    1083 r = _vsnprintf_l(str, capacity, format, locale, arg);
    +
    1084#else
    +
    1085 r = ::vsnprintf(str, capacity, format, arg);
    +
    1086#endif
    +
    1087 if (r == -1 && strnlen(str, capacity) == capacity) {
    +
    1088 // Buffer overrun. Estimate buffer size for the next iteration.
    +
    1089 capacity += std::max<size_t>(capacity / 8, 0x80);
    +
    1090 if (capacity > INT_MAX)
    +
    1091 throw std::invalid_argument("string too big");
    +
    1092 return (int)capacity;
    +
    1093 }
    +
    1094 return r;
    +
    1095 }
    1096
    -
    1105 template<class _Elem, class _Traits, class _Ax>
    -
    1106 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)
    -
    1107 {
    -
    1108 _Elem buf[1024/sizeof(_Elem)];
    -
    1109
    -
    1110 // Try with stack buffer first.
    -
    1111 int count = vsnprintf(buf, _countof(buf) - 1, format, locale, arg);
    -
    1112 if (count >= 0) {
    -
    1113 // Copy from stack.
    -
    1114 str.append(buf, count);
    -
    1115 } else {
    -
    1116 for (size_t capacity = 2*1024/sizeof(_Elem);; capacity *= 2) {
    -
    1117 // Allocate on heap and retry.
    -
    1118 auto buf_dyn = std::make_unique<_Elem[]>(capacity);
    -
    1119 count = vsnprintf(buf_dyn.get(), capacity - 1, format, locale, arg);
    -
    1120 if (count >= 0) {
    -
    1121 str.append(buf_dyn.get(), count);
    -
    1122 break;
    -
    1123 }
    -
    1124 }
    -
    1125 }
    -
    1126 }
    -
    1127
    -
    1135 template<class _Elem, class _Traits, class _Ax>
    -
    1136 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, ...)
    -
    1137 {
    -
    1138 va_list arg;
    -
    1139 va_start(arg, locale);
    -
    1140 vappendf(str, format, locale, arg);
    -
    1141 va_end(arg);
    -
    1142 }
    -
    1143
    -
    1152 template<class _Elem, class _Traits, class _Ax>
    -
    1153 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)
    -
    1154 {
    -
    1155 str.clear();
    -
    1156 vappendf(str, format, locale, arg);
    -
    1157 }
    -
    1158
    -
    1166 template<class _Elem, class _Traits, class _Ax>
    -
    1167 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, ...)
    -
    1168 {
    -
    1169 va_list arg;
    -
    1170 va_start(arg, locale);
    -
    1171 vsprintf(str, format, locale, arg);
    -
    1172 va_end(arg);
    -
    1173 }
    -
    1174
    -
    1184 template<class _Elem, class _Traits = std::char_traits<_Elem>, class _Ax = std::allocator<_Elem>>
    -
    1185 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)
    -
    1186 {
    -
    1187 std::basic_string<_Elem, _Traits, _Ax> str;
    -
    1188 vappendf(str, format, locale, arg);
    -
    1189 return str;
    -
    1190 }
    -
    1191
    -
    1200 template<class _Elem, class _Traits = std::char_traits<_Elem>, class _Ax = std::allocator<_Elem>>
    -
    1201 inline std::basic_string<_Elem, _Traits, _Ax> sprintf(_In_z_ _Printf_format_string_params_(2) const _Elem *format, _In_opt_ locale_t locale, ...)
    -
    1202 {
    -
    1203 va_list arg;
    -
    1204 va_start(arg, locale);
    -
    1205 auto str = vsprintf(format, locale, arg);
    -
    1206 va_end(arg);
    -
    1207 return str;
    -
    1208 }
    -
    1209}
    -
    Deleter for unique_ptr using free_locale.
    Definition string.hpp:33
    -
    void operator()(locale_t locale) const
    Delete a pointer.
    Definition string.hpp:37
    +
    1097 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)
    +
    1098 {
    +
    1099 int r;
    +
    1100
    +
    1101#ifdef _WIN32
    +
    1102 // Don't use _vsnwprintf_s(). It terminates the string even if we want to print to the edge of the buffer.
    +
    1103#pragma warning(suppress: 4996)
    +
    1104 r = _vsnwprintf_l(str, capacity, format, locale, arg);
    +
    1105#else
    +
    1106 r = vswprintf(str, capacity, format, arg);
    +
    1107#endif
    +
    1108 if (r == -1 && strnlen(str, capacity) == capacity) {
    +
    1109 // Buffer overrun. Estimate buffer size for the next iteration.
    +
    1110 capacity += std::max<size_t>(capacity / 8, 0x80);
    +
    1111 if (capacity > INT_MAX)
    +
    1112 throw std::invalid_argument("string too big");
    +
    1113 return (int)capacity;
    +
    1114 }
    +
    1115 return r;
    +
    1116 }
    +
    1118
    +
    1127 template<class _Elem, class _Traits, class _Ax>
    +
    1128 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)
    +
    1129 {
    +
    1130 _Elem buf[1024/sizeof(_Elem)];
    +
    1131
    +
    1132 // Try with stack buffer first.
    +
    1133 int count = vsnprintf(buf, _countof(buf) - 1, format, locale, arg);
    +
    1134 if (count >= 0) {
    +
    1135 // Copy from stack.
    +
    1136 str.append(buf, count);
    +
    1137 } else {
    +
    1138 for (size_t capacity = 2*1024/sizeof(_Elem);; capacity *= 2) {
    +
    1139 // Allocate on heap and retry.
    +
    1140 auto buf_dyn = std::make_unique<_Elem[]>(capacity);
    +
    1141 count = vsnprintf(buf_dyn.get(), capacity - 1, format, locale, arg);
    +
    1142 if (count >= 0) {
    +
    1143 str.append(buf_dyn.get(), count);
    +
    1144 break;
    +
    1145 }
    +
    1146 }
    +
    1147 }
    +
    1148 }
    +
    1149
    +
    1157 template<class _Elem, class _Traits, class _Ax>
    +
    1158 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, ...)
    +
    1159 {
    +
    1160 va_list arg;
    +
    1161 va_start(arg, locale);
    +
    1162 vappendf(str, format, locale, arg);
    +
    1163 va_end(arg);
    +
    1164 }
    +
    1165
    +
    1174 template<class _Elem, class _Traits, class _Ax>
    +
    1175 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)
    +
    1176 {
    +
    1177 str.clear();
    +
    1178 vappendf(str, format, locale, arg);
    +
    1179 }
    +
    1180
    +
    1188 template<class _Elem, class _Traits, class _Ax>
    +
    1189 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, ...)
    +
    1190 {
    +
    1191 va_list arg;
    +
    1192 va_start(arg, locale);
    +
    1193 vsprintf(str, format, locale, arg);
    +
    1194 va_end(arg);
    +
    1195 }
    +
    1196
    +
    1206 template<class _Elem, class _Traits = std::char_traits<_Elem>, class _Ax = std::allocator<_Elem>>
    +
    1207 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)
    +
    1208 {
    +
    1209 std::basic_string<_Elem, _Traits, _Ax> str;
    +
    1210 vappendf(str, format, locale, arg);
    +
    1211 return str;
    +
    1212 }
    +
    1213
    +
    1222 template<class _Elem, class _Traits = std::char_traits<_Elem>, class _Ax = std::allocator<_Elem>>
    +
    1223 inline std::basic_string<_Elem, _Traits, _Ax> sprintf(_In_z_ _Printf_format_string_params_(2) const _Elem *format, _In_opt_ locale_t locale, ...)
    +
    1224 {
    +
    1225 va_list arg;
    +
    1226 va_start(arg, locale);
    +
    1227 auto str = vsprintf(format, locale, arg);
    +
    1228 va_end(arg);
    +
    1229 return str;
    +
    1230 }
    +
    1231}
    +
    Deleter for unique_ptr using free_locale.
    Definition string.hpp:39
    +
    void operator()(locale_t locale) const
    Delete a pointer.
    Definition string.hpp:43
    diff --git a/structstdex_1_1chrono_1_1aosn__date-members.html b/structstdex_1_1chrono_1_1aosn__date-members.html index fb65e56a7..5dfa5171a 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 74f7f85e3..ce5f976a9 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 de0748863..b5bc4a450 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 57e3b9222..d69d135b6 100644 --- a/structstdex_1_1chrono_1_1aosn__timestamp.html +++ b/structstdex_1_1chrono_1_1aosn__timestamp.html @@ -197,7 +197,7 @@ static constexpr rep p_wee
    diff --git a/structstdex_1_1free__locale__delete-members.html b/structstdex_1_1free__locale__delete-members.html index d1c01dde3..2ee153a2b 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 4bac319f9..a5028db09 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 ca7f643eb..9dcaf4a64 100644 --- a/structstdex_1_1interval-members.html +++ b/structstdex_1_1interval-members.html @@ -92,7 +92,7 @@ $(function() {
    diff --git a/structstdex_1_1interval.html b/structstdex_1_1interval.html index 0cce57fbf..22f13da67 100644 --- a/structstdex_1_1interval.html +++ b/structstdex_1_1interval.html @@ -344,7 +344,7 @@ template<class T >
    diff --git a/structstdex_1_1mapping-members.html b/structstdex_1_1mapping-members.html index 300aa979c..67b09db05 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 019194ae6..a5e0650ab 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 80be41b33..1874e40c8 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 a5dfaf55c..81a375442 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 3cf30393f..22a4855e1 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 c97bcdc12..ebfc74956 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 81de5aab0..267e97cb0 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 9639294c1..4add37b24 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 d6f402581..8c9c059ce 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 13bae4aa7..dca4d6290 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_1cache_1_1cache__t-members.html b/structstdex_1_1stream_1_1cache_1_1cache__t-members.html index 6dabd4e4c..72c67cde8 100644 --- a/structstdex_1_1stream_1_1cache_1_1cache__t-members.html +++ b/structstdex_1_1stream_1_1cache_1_1cache__t-members.html @@ -90,7 +90,7 @@ $(function() {
    diff --git a/structstdex_1_1stream_1_1cache_1_1cache__t.html b/structstdex_1_1stream_1_1cache_1_1cache__t.html index fe0954b99..5029698c2 100644 --- a/structstdex_1_1stream_1_1cache_1_1cache__t.html +++ b/structstdex_1_1stream_1_1cache_1_1cache__t.html @@ -119,7 +119,7 @@ enum stdex::stream::cache::cache_t::status_t  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 688c0f86d..c3824fb04 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 e3008069e..1a2bd5021 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/system_8hpp_source.html b/system_8hpp_source.html index 6ded12eda..b0afb77f3 100644 --- a/system_8hpp_source.html +++ b/system_8hpp_source.html @@ -96,185 +96,187 @@ $(document).ready(function() { init_codefold(0); });
    12#include <oaidl.h>
    13#include <tchar.h>
    14#else
    -
    15#include <unistd.h>
    -
    16#endif
    -
    17#include "sal.hpp"
    -
    18#include <assert.h>
    -
    19#include <stdexcept>
    -
    20#include <string>
    -
    21
    -
    22// In case somebody #included <windows.h> before us and didn't #define NOMINMAX
    -
    23#ifdef _WIN32
    -
    24#ifdef min
    -
    25#undef min
    -
    26#endif
    -
    27#ifdef max
    -
    28#undef max
    -
    29#endif
    -
    30#endif
    -
    31
    -
    32namespace stdex
    -
    33{
    -
    37#if defined(_WIN32)
    -
    38 using sys_handle = HANDLE;
    -
    39 const sys_handle invalid_handle = INVALID_HANDLE_VALUE;
    -
    40#else
    -
    41 using sys_handle = int;
    -
    42 const sys_handle invalid_handle = (sys_handle)-1;
    -
    43#endif
    -
    44
    -
    48#if defined(_WIN32)
    -
    49 using schar_t = TCHAR;
    -
    50#else
    -
    51 using schar_t = char;
    -
    52#define _T(x) x
    -
    53#endif
    -
    54
    -
    59 using sys_char = schar_t;
    -
    60
    -
    64 using sstring = std::basic_string<stdex::schar_t>;
    -
    65
    -
    70 using sys_string = sstring;
    -
    71
    -
    - -
    76 {
    -
    77 public:
    -
    78 sys_object(_In_opt_ sys_handle h = invalid_handle) : m_h(h) {}
    -
    79
    -
    80 sys_object(_In_ const sys_object& other) : m_h(other.m_h != invalid_handle ? duplicate(other.m_h, false) : invalid_handle) {}
    +
    15#define _LARGEFILE64_SOURCE
    +
    16#include <sys/types.h>
    +
    17#include <unistd.h>
    +
    18#endif
    +
    19#include "compat.hpp"
    +
    20#include <assert.h>
    +
    21#include <stdexcept>
    +
    22#include <string>
    +
    23
    +
    24// In case somebody #included <windows.h> before us and didn't #define NOMINMAX
    +
    25#ifdef _WIN32
    +
    26#ifdef min
    +
    27#undef min
    +
    28#endif
    +
    29#ifdef max
    +
    30#undef max
    +
    31#endif
    +
    32#endif
    +
    33
    +
    34namespace stdex
    +
    35{
    +
    39#if defined(_WIN32)
    +
    40 using sys_handle = HANDLE;
    +
    41 const sys_handle invalid_handle = INVALID_HANDLE_VALUE;
    +
    42#else
    +
    43 using sys_handle = int;
    +
    44 const sys_handle invalid_handle = (sys_handle)-1;
    +
    45#endif
    +
    46
    +
    50#if defined(_WIN32)
    +
    51 using schar_t = TCHAR;
    +
    52#else
    +
    53 using schar_t = char;
    +
    54#define _T(x) x
    +
    55#endif
    +
    56
    +
    61 using sys_char = schar_t;
    +
    62
    +
    66 using sstring = std::basic_string<stdex::schar_t>;
    +
    67
    +
    72 using sys_string = sstring;
    +
    73
    +
    + +
    78 {
    +
    79 public:
    +
    80 sys_object(_In_opt_ sys_handle h = invalid_handle) : m_h(h) {}
    81
    -
    82 sys_object& operator =(_In_ const sys_object& other)
    -
    83 {
    -
    84 if (this != std::addressof(other)) {
    -
    85 if (m_h != invalid_handle)
    -
    86 close(m_h);
    -
    87 m_h = other.m_h != invalid_handle ? duplicate(other.m_h, false) : invalid_handle;
    -
    88 }
    -
    89 return *this;
    -
    90 }
    -
    91
    -
    92 sys_object(_Inout_ sys_object&& other) noexcept : m_h(other.m_h)
    -
    93 {
    -
    94 other.m_h = invalid_handle;
    -
    95 }
    -
    96
    -
    97 sys_object& operator =(_Inout_ sys_object&& other) noexcept
    -
    98 {
    -
    99 if (this != std::addressof(other)) {
    -
    100 if (m_h != invalid_handle)
    -
    101 close(m_h);
    -
    102 m_h = other.m_h;
    -
    103 other.m_h = invalid_handle;
    -
    104 }
    -
    105 return *this;
    -
    106 }
    -
    107
    -
    108 virtual ~sys_object()
    -
    109 {
    -
    110 if (m_h != invalid_handle)
    -
    111 close(m_h);
    -
    112 }
    -
    113
    -
    -
    117 virtual void close()
    -
    118 {
    -
    119 if (m_h != invalid_handle) {
    -
    120 close(m_h);
    -
    121 m_h = invalid_handle;
    -
    122 }
    -
    123 }
    +
    82 sys_object(_In_ const sys_object& other) : m_h(other.m_h != invalid_handle ? duplicate(other.m_h, false) : invalid_handle) {}
    +
    83
    +
    84 sys_object& operator =(_In_ const sys_object& other)
    +
    85 {
    +
    86 if (this != std::addressof(other)) {
    +
    87 if (m_h != invalid_handle)
    +
    88 close(m_h);
    +
    89 m_h = other.m_h != invalid_handle ? duplicate(other.m_h, false) : invalid_handle;
    +
    90 }
    +
    91 return *this;
    +
    92 }
    +
    93
    +
    94 sys_object(_Inout_ sys_object&& other) noexcept : m_h(other.m_h)
    +
    95 {
    +
    96 other.m_h = invalid_handle;
    +
    97 }
    +
    98
    +
    99 sys_object& operator =(_Inout_ sys_object&& other) noexcept
    +
    100 {
    +
    101 if (this != std::addressof(other)) {
    +
    102 if (m_h != invalid_handle)
    +
    103 close(m_h);
    +
    104 m_h = other.m_h;
    +
    105 other.m_h = invalid_handle;
    +
    106 }
    +
    107 return *this;
    +
    108 }
    +
    109
    +
    110 virtual ~sys_object()
    +
    111 {
    +
    112 if (m_h != invalid_handle)
    +
    113 close(m_h);
    +
    114 }
    +
    115
    +
    +
    119 virtual void close()
    +
    120 {
    +
    121 if (m_h != invalid_handle) {
    +
    122 close(m_h);
    +
    123 m_h = invalid_handle;
    +
    124 }
    +
    125 }
    -
    124
    -
    128 inline operator bool() const noexcept { return m_h != invalid_handle; }
    -
    129
    -
    133 inline sys_handle get() const noexcept { return m_h; }
    -
    134
    -
    135 protected:
    -
    -
    139 static void close(_In_ sys_handle h)
    -
    140 {
    -
    141#ifdef _WIN32
    -
    142 if (CloseHandle(h) || GetLastError() == ERROR_INVALID_HANDLE)
    -
    143#else
    -
    144 if (::close(h) >= 0 || errno == EBADF)
    -
    145#endif
    -
    146 return;
    -
    147 throw std::runtime_error("failed to close handle");
    -
    148 }
    +
    126
    +
    130 inline operator bool() const noexcept { return m_h != invalid_handle; }
    +
    131
    +
    135 inline sys_handle get() const noexcept { return m_h; }
    +
    136
    +
    137 protected:
    +
    +
    141 static void close(_In_ sys_handle h)
    +
    142 {
    +
    143#ifdef _WIN32
    +
    144 if (CloseHandle(h) || GetLastError() == ERROR_INVALID_HANDLE)
    +
    145#else
    +
    146 if (::close(h) >= 0 || errno == EBADF)
    +
    147#endif
    +
    148 return;
    +
    149 throw std::runtime_error("failed to close handle");
    +
    150 }
    -
    149
    -
    -
    153 static sys_handle duplicate(_In_ sys_handle h, _In_ bool inherit)
    -
    154 {
    -
    155 sys_handle h_new;
    -
    156#ifdef _WIN32
    -
    157 HANDLE process = GetCurrentProcess();
    -
    158 if (DuplicateHandle(process, h, process, &h_new, 0, inherit, DUPLICATE_SAME_ACCESS))
    -
    159#else
    -
    160 _Unreferenced_(inherit);
    -
    161 if ((h_new = dup(h)) >= 0)
    -
    162#endif
    -
    163 return h_new;
    -
    164 throw std::runtime_error("failed to duplicate handle");
    -
    165 }
    +
    151
    +
    +
    155 static sys_handle duplicate(_In_ sys_handle h, _In_ bool inherit)
    +
    156 {
    +
    157 sys_handle h_new;
    +
    158#ifdef _WIN32
    +
    159 HANDLE process = GetCurrentProcess();
    +
    160 if (DuplicateHandle(process, h, process, &h_new, 0, inherit, DUPLICATE_SAME_ACCESS))
    +
    161#else
    +
    162 _Unreferenced_(inherit);
    +
    163 if ((h_new = dup(h)) >= 0)
    +
    164#endif
    +
    165 return h_new;
    +
    166 throw std::runtime_error("failed to duplicate handle");
    +
    167 }
    -
    166
    -
    167 protected:
    -
    168 sys_handle m_h;
    -
    169 };
    +
    168
    +
    169 protected:
    +
    170 sys_handle m_h;
    +
    171 };
    -
    170
    -
    171#ifdef _WIN32
    -
    172 template <class T>
    -
    173 class safearray_accessor
    -
    174 {
    -
    175 public:
    -
    176 safearray_accessor(_In_ LPSAFEARRAY sa) : m_sa(sa)
    -
    177 {
    -
    178 HRESULT hr = SafeArrayAccessData(sa, reinterpret_cast<void HUGEP**>(&m_data));
    -
    179 if (FAILED(hr))
    -
    180 throw std::invalid_argument("SafeArrayAccessData failed");
    -
    181 }
    -
    182
    -
    183 ~safearray_accessor()
    -
    184 {
    -
    185 SafeArrayUnaccessData(m_sa);
    -
    186 }
    -
    187
    -
    188 T* data() const { return m_data; }
    +
    172
    +
    173#ifdef _WIN32
    +
    174 template <class T>
    +
    175 class safearray_accessor
    +
    176 {
    +
    177 public:
    +
    178 safearray_accessor(_In_ LPSAFEARRAY sa) : m_sa(sa)
    +
    179 {
    +
    180 HRESULT hr = SafeArrayAccessData(sa, reinterpret_cast<void HUGEP**>(&m_data));
    +
    181 if (FAILED(hr))
    +
    182 throw std::invalid_argument("SafeArrayAccessData failed");
    +
    183 }
    +
    184
    +
    185 ~safearray_accessor()
    +
    186 {
    +
    187 SafeArrayUnaccessData(m_sa);
    +
    188 }
    189
    -
    190 protected:
    -
    191 LPSAFEARRAY m_sa;
    -
    192 T* m_data;
    -
    193 };
    -
    194
    -
    198 struct SafeArrayDestroy_delete
    -
    199 {
    -
    203 void operator()(_In_ LPSAFEARRAY sa) const
    -
    204 {
    -
    205 SafeArrayDestroy(sa);
    -
    206 }
    -
    207 };
    -
    208
    -
    212 struct SysFreeString_delete
    -
    213 {
    -
    217 void operator()(_In_ BSTR sa) const
    -
    218 {
    -
    219 SysFreeString(sa);
    -
    220 }
    -
    221 };
    -
    222#endif
    -
    223}
    -
    Operating system object (file, pipe, anything with an OS handle etc.)
    Definition system.hpp:76
    -
    sys_handle get() const noexcept
    Returns object handle.
    Definition system.hpp:133
    -
    virtual void close()
    Closes object.
    Definition system.hpp:117
    -
    static sys_handle duplicate(sys_handle h, bool inherit)
    Duplicates given object.
    Definition system.hpp:153
    -
    static void close(sys_handle h)
    Closes object.
    Definition system.hpp:139
    +
    190 T* data() const { return m_data; }
    +
    191
    +
    192 protected:
    +
    193 LPSAFEARRAY m_sa;
    +
    194 T* m_data;
    +
    195 };
    +
    196
    +
    200 struct SafeArrayDestroy_delete
    +
    201 {
    +
    205 void operator()(_In_ LPSAFEARRAY sa) const
    +
    206 {
    +
    207 SafeArrayDestroy(sa);
    +
    208 }
    +
    209 };
    +
    210
    +
    214 struct SysFreeString_delete
    +
    215 {
    +
    219 void operator()(_In_ BSTR sa) const
    +
    220 {
    +
    221 SysFreeString(sa);
    +
    222 }
    +
    223 };
    +
    224#endif
    +
    225}
    +
    Operating system object (file, pipe, anything with an OS handle etc.)
    Definition system.hpp:78
    +
    sys_handle get() const noexcept
    Returns object handle.
    Definition system.hpp:135
    +
    virtual void close()
    Closes object.
    Definition system.hpp:119
    +
    static sys_handle duplicate(sys_handle h, bool inherit)
    Duplicates given object.
    Definition system.hpp:155
    +
    static void close(sys_handle h)
    Closes object.
    Definition system.hpp:141
    diff --git a/unicode_8cpp_source.html b/unicode_8cpp_source.html new file mode 100644 index 000000000..30a295532 --- /dev/null +++ b/unicode_8cpp_source.html @@ -0,0 +1,141 @@ + + + + + + + +stdex: UnitTests/unicode.cpp Source File + + + + + + + + + +
    +
    + + + + + + +
    +
    stdex +
    +
    Additional custom or not Standard C++ covered algorithms
    +
    +
    + + + + + + + + + +
    +
    + + +
    +
    +
    +
    +
    +
    Loading...
    +
    Searching...
    +
    No Matches
    +
    +
    +
    +
    + + +
    +
    +
    unicode.cpp
    +
    +
    +
    1/*
    +
    2 SPDX-License-Identifier: MIT
    +
    3 Copyright © 2023 Amebis
    +
    4*/
    +
    5
    +
    6#include "pch.h"
    +
    7
    +
    8using namespace std;
    +
    9#ifdef _WIN32
    +
    10using namespace Microsoft::VisualStudio::CppUnitTestFramework;
    +
    11#endif
    +
    12
    +
    13namespace UnitTests
    +
    14{
    +
    15 TEST_CLASS(unicode)
    +
    16 {
    +
    17 public:
    +
    18 TEST_METHOD(str2wstr)
    +
    19 {
    +
    20 Assert::AreEqual(
    +
    21 L"This is a test.",
    +
    22 stdex::str2wstr("This is a test.", stdex::charset_id::utf8).c_str());
    +
    23 Assert::AreEqual(
    +
    24 L"Th\u00ed\u0161 i\u22c5 a te\u0073\u0304t. 😀😅",
    +
    25 stdex::str2wstr("Thíš i⋅ a tes̄t. 😀😅", stdex::charset_id::utf8).c_str());
    +
    26 Assert::AreEqual(
    +
    27 L"",
    +
    28 stdex::str2wstr("test", 0, stdex::charset_id::utf8).c_str());
    +
    29 Assert::AreEqual(
    +
    30 L"",
    +
    31 stdex::str2wstr(nullptr, 0, stdex::charset_id::utf8).c_str());
    +
    32 }
    +
    33
    +
    34 TEST_METHOD(wstr2str)
    +
    35 {
    +
    36 Assert::AreEqual(
    +
    37 "This is a test.",
    +
    38 stdex::wstr2str(L"This is a test.", stdex::charset_id::utf8).c_str());
    +
    39 Assert::AreEqual(
    +
    40 "Th\xc3\xad\xc5\xa1 i\xe2\x8b\x85 a tes\xcc\x84t. \xf0\x9f\x98\x80\xf0\x9f\x98\x85",
    +
    41 stdex::wstr2str(L"Thíš i⋅ a tes̄t. 😀😅", stdex::charset_id::utf8).c_str());
    +
    42 Assert::AreEqual(
    +
    43 "",
    +
    44 stdex::wstr2str(L"test", 0, stdex::charset_id::utf8).c_str());
    +
    45 Assert::AreEqual(
    +
    46 "",
    +
    47 stdex::wstr2str(nullptr, 0, stdex::charset_id::utf8).c_str());
    +
    48 }
    +
    49 };
    +
    50}
    +
    + + + + diff --git a/unicode_8hpp_source.html b/unicode_8hpp_source.html index b1e2973ac..d6af3d782 100644 --- a/unicode_8hpp_source.html +++ b/unicode_8hpp_source.html @@ -89,220 +89,290 @@ $(document).ready(function() { init_codefold(0); });
    5
    6#pragma once
    7
    -
    8#include "sal.hpp"
    -
    9#include "system.hpp"
    -
    10#include <assert.h>
    -
    11#include <stdint.h>
    -
    12#include <memory>
    -
    13#include <string>
    -
    14
    -
    15namespace stdex
    -
    16{
    -
    17 enum class charset_id : uint16_t {
    -
    18#ifdef _WIN32
    -
    19 default = CP_ACP,
    -
    20 utf8 = CP_UTF8,
    -
    21 utf16 = 1200 /*CP_WINUNICODE*/,
    -
    22#else
    -
    23 default = 0,
    -
    24#endif
    -
    25 };
    -
    26
    -
    37 inline void strcat(
    -
    38 _Inout_ std::wstring& dst,
    -
    39 _In_reads_or_z_opt_(count_src) const char* src, _In_ size_t count_src,
    -
    40 _In_ charset_id charset = charset_id::default)
    +
    8#include "compat.hpp"
    +
    9#include "endian.hpp"
    +
    10#include "math.hpp"
    +
    11#include "system.hpp"
    +
    12#include <assert.h>
    +
    13#include <stdint.h>
    +
    14#ifndef _WIN32
    +
    15#include <iconv.h>
    +
    16#endif
    +
    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 utf8 = CP_UTF8,
    +
    26 utf16 = 1200 /*CP_WINUNICODE*/,
    +
    27#else
    +
    28 system = 0,
    +
    29 utf8,
    +
    30 utf16,
    +
    31 utf32,
    +
    32#endif
    +
    33 };
    +
    34
    +
    35#ifndef _WIN32
    +
    39 template <typename T_from, typename T_to>
    +
    +
    41 {
    -
    42 assert(src || !count_src);
    -
    43#ifdef _WIN32
    -
    44 assert(count_src < INT_MAX || count_src == SIZE_MAX);
    -
    45 constexpr DWORD dwFlags = MB_PRECOMPOSED;
    -
    46
    -
    47 // Try to convert to stack buffer first.
    -
    48 WCHAR szStackBuffer[1024/sizeof(WCHAR)];
    -
    49#pragma warning(suppress: 6387) // Testing indicates src may be NULL when count_src is also 0. Is SAL of the lpMultiByteStr parameter wrong?
    -
    50 int cch = MultiByteToWideChar(static_cast<UINT>(charset), dwFlags, src, static_cast<int>(count_src), szStackBuffer, _countof(szStackBuffer));
    -
    51 if (cch) {
    -
    52 // Append from stack.
    -
    53 dst.append(szStackBuffer, count_src != SIZE_MAX ? wcsnlen(szStackBuffer, cch) : (size_t)cch - 1);
    -
    54 } else if (::GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
    -
    55 // Query the required output size. Allocate buffer. Then convert again.
    -
    56 cch = MultiByteToWideChar(static_cast<UINT>(charset), dwFlags, src, static_cast<int>(count_src), NULL, 0);
    -
    57 std::unique_ptr<WCHAR[]> szBuffer(new WCHAR[cch]);
    -
    58 cch = MultiByteToWideChar(static_cast<UINT>(charset), dwFlags, src, static_cast<int>(count_src), szBuffer.get(), cch);
    -
    59 dst.append(szBuffer.get(), count_src != SIZE_MAX ? wcsnlen(szBuffer.get(), cch) : (size_t)cch - 1);
    -
    60 }
    -
    61#else
    -
    62 throw std::exception("not implemented");
    -
    63#endif
    -
    64 }
    -
    65
    -
    66 inline _Deprecated_("Use stdex::strcat") void str2wstr(
    -
    67 _Inout_ std::wstring& dst,
    -
    68 _In_reads_or_z_opt_(count_src) const char* src, _In_ size_t count_src,
    -
    69 _In_ charset_id charset = charset_id::default)
    -
    70 {
    -
    71 strcat(dst, src, count_src, charset);
    -
    72 }
    -
    73
    -
    83 inline void strcat(
    -
    84 _Inout_ std::wstring& dst,
    -
    85 _In_ const std::string& src,
    -
    86 _In_ charset_id charset = charset_id::default)
    -
    87 {
    -
    88 strcat(dst, src.data(), src.size(), charset);
    -
    89 }
    -
    90
    -
    91 inline _Deprecated_("Use stdex::strcat") void str2wstr(
    -
    92 _Inout_ std::wstring& dst,
    -
    93 _In_ const std::string& src,
    -
    94 _In_ charset_id charset = charset_id::default)
    -
    95 {
    -
    96 strcat(dst, src, charset);
    -
    97 }
    -
    98
    -
    109 inline void strcpy(
    -
    110 _Inout_ std::wstring& dst,
    -
    111 _In_reads_or_z_opt_(count_src) const char* src, _In_ size_t count_src,
    -
    112 _In_ charset_id charset = charset_id::default)
    -
    113 {
    -
    114 dst.clear();
    -
    115 strcat(dst, src, count_src, charset);
    -
    116 }
    -
    117
    -
    127 inline void strcpy(
    -
    128 _Inout_ std::wstring& dst,
    -
    129 _In_ const std::string& src,
    -
    130 _In_ charset_id charset = charset_id::default)
    -
    131 {
    -
    132 strcpy(dst, src.data(), src.size(), charset);
    -
    133 }
    -
    134
    -
    143 inline std::wstring str2wstr(
    -
    144 _In_z_ const char* src,
    -
    145 _In_ charset_id charset = charset_id::default)
    -
    146 {
    -
    147 std::wstring dst;
    -
    148 strcat(dst, src, SIZE_MAX, charset);
    -
    149 return dst;
    -
    150 }
    -
    151
    -
    161 inline std::wstring str2wstr(
    -
    162 _In_reads_or_z_opt_(count_src) const char* src, _In_ size_t count_src,
    -
    163 _In_ charset_id charset = charset_id::default)
    -
    164 {
    -
    165 std::wstring dst;
    -
    166 strcat(dst, src, count_src, charset);
    -
    167 return dst;
    -
    168 }
    -
    169
    -
    178 inline std::wstring str2wstr(
    -
    179 _In_ const std::string& src,
    -
    180 _In_ charset_id charset = charset_id::default)
    -
    181 {
    -
    182 return str2wstr(src.c_str(), src.size(), charset);
    -
    183 }
    -
    184
    -
    193 inline void strcat(
    -
    194 _Inout_ std::string& dst,
    -
    195 _In_reads_or_z_opt_(count_src) const wchar_t* src, _In_ size_t count_src,
    -
    196 _In_ charset_id charset = charset_id::default)
    -
    197 {
    -
    198 assert(src || !count_src);
    -
    199#ifdef _WIN32
    -
    200 assert(count_src < INT_MAX || count_src == SIZE_MAX);
    -
    201 constexpr DWORD dwFlags = 0;
    -
    202 constexpr LPCCH lpDefaultChar = NULL;
    -
    203
    -
    204 // Try to convert to stack buffer first.
    -
    205 CHAR szStackBuffer[1024/sizeof(CHAR)];
    -
    206#pragma warning(suppress: 6387) // Testing indicates src may be NULL when count_src is also 0. Is SAL of the lpWideCharStr parameter wrong?
    -
    207 int cch = WideCharToMultiByte(static_cast<UINT>(charset), dwFlags, src, static_cast<int>(count_src), szStackBuffer, _countof(szStackBuffer), lpDefaultChar, NULL);
    -
    208 if (cch) {
    -
    209 // Copy from stack. Be careful not to include zero terminator.
    -
    210 dst.append(szStackBuffer, count_src != SIZE_MAX ? strnlen(szStackBuffer, cch) : (size_t)cch - 1);
    -
    211 } else if (::GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
    -
    212 // Query the required output size. Allocate buffer. Then convert again.
    -
    213 cch = WideCharToMultiByte(static_cast<UINT>(charset), dwFlags, src, static_cast<int>(count_src), NULL, 0, lpDefaultChar, NULL);
    -
    214 std::unique_ptr<CHAR[]> szBuffer(new CHAR[cch]);
    -
    215 cch = WideCharToMultiByte(static_cast<UINT>(charset), dwFlags, src, static_cast<int>(count_src), szBuffer.get(), cch, lpDefaultChar, NULL);
    -
    216 dst.append(szBuffer.get(), count_src != SIZE_MAX ? strnlen(szBuffer.get(), cch) : (size_t)cch - 1);
    -
    217 }
    -
    218#else
    -
    219 throw std::exception("not implemented");
    -
    220#endif
    -
    221 }
    -
    222
    -
    223 inline _Deprecated_("Use stdex::strcat") void wstr2str(
    -
    224 _Inout_ std::string& dst,
    -
    225 _In_reads_or_z_opt_(count_src) const wchar_t* src, _In_ size_t count_src,
    -
    226 _In_ charset_id charset = charset_id::default)
    -
    227 {
    -
    228 strcat(dst, src, count_src, charset);
    -
    229 }
    -
    230
    -
    238 inline void strcat(
    -
    239 _Inout_ std::string& dst,
    -
    240 _In_ const std::wstring& src,
    -
    241 _In_ charset_id charset = charset_id::default)
    -
    242 {
    -
    243 strcat(dst, src.c_str(), src.size(), charset);
    -
    244 }
    -
    245
    -
    246 inline _Deprecated_("Use stdex::strcat") void wstr2str(
    -
    247 _Inout_ std::string& dst,
    -
    248 _In_ const std::wstring& src,
    -
    249 _In_ charset_id charset = charset_id::default)
    -
    250 {
    -
    251 strcat(dst, src, charset);
    -
    252 }
    -
    253
    -
    262 inline void strcpy(
    -
    263 _Inout_ std::string& dst,
    -
    264 _In_reads_or_z_opt_(count_src) const wchar_t* src, _In_ size_t count_src,
    -
    265 _In_ charset_id charset = charset_id::default)
    -
    266 {
    -
    267 dst.clear();
    -
    268 strcat(dst, src, count_src, charset);
    -
    269 }
    -
    270
    -
    278 inline void strcpy(
    -
    279 _Inout_ std::string& dst,
    -
    280 _In_ const std::wstring& src,
    -
    281 _In_ charset_id charset = charset_id::default)
    -
    282 {
    -
    283 strcpy(dst, src.data(), src.size(), charset);
    -
    284 }
    -
    285
    -
    294 inline std::string wstr2str(
    -
    295 _In_z_ const wchar_t* src,
    -
    296 _In_ charset_id charset = charset_id::default)
    -
    297 {
    -
    298 std::string dst;
    -
    299 strcat(dst, src, SIZE_MAX, charset);
    -
    300 return dst;
    -
    301 }
    -
    302
    -
    312 inline std::string wstr2str(
    -
    313 _In_reads_or_z_opt_(count_src) const wchar_t* src, _In_ size_t count_src,
    -
    314 _In_ charset_id charset = charset_id::default)
    -
    315 {
    -
    316 std::string dst;
    -
    317 strcat(dst, src, count_src, charset);
    -
    318 return dst;
    -
    319 }
    -
    320
    -
    329 inline std::string wstr2str(
    -
    330 _In_ const std::wstring& src,
    -
    331 _In_ charset_id charset = charset_id::default)
    -
    332 {
    -
    333 return wstr2str(src.c_str(), src.size(), charset);
    -
    334 }
    -
    335}
    +
    42 public:
    +
    43 iconverter(_In_ charset_id from, _In_ charset_id to)
    +
    44 {
    +
    45 m_handle = iconv_open(to_encoding(to), to_encoding(from));
    +
    46 if (m_handle == (iconv_t)-1)
    +
    47 throw std::runtime_error("iconv_open failed");
    +
    48 }
    +
    49
    + +
    51 {
    +
    52 iconv_close(m_handle);
    +
    53 }
    +
    54
    +
    55 void convert(_Inout_ std::basic_string<T_to> &dst, _In_reads_or_z_opt_(count) const T_from* src, _In_ size_t count_src) const
    +
    56 {
    +
    57 T_to buf[0x100];
    +
    58 count_src = stdex::strnlen(src, count_src);
    +
    59 size_t src_size = stdex::mul(sizeof(T_from), count_src);
    +
    60 do {
    +
    61 T_to* output = &buf[0];
    +
    62 size_t output_size = sizeof(buf);
    +
    63 errno = 0;
    +
    64 iconv(m_handle, (char**)&src, &src_size, (char**)&output, &output_size);
    +
    65 if (errno)
    +
    66 throw std::runtime_error("iconv failed");
    +
    67 dst.insert(dst.end(), buf, (T_to*)((char*)buf + sizeof(buf) - output_size));
    +
    68 } while (src_size);
    +
    69 }
    +
    70
    +
    71 protected:
    +
    72 static const char* to_encoding(_In_ charset_id charset)
    +
    73 {
    +
    74 switch (charset) {
    +
    75 case charset_id::system:
    +
    76 case charset_id::utf8: return "UTF-8";
    +
    77#if BYTE_ORDER == BIG_ENDIAN
    +
    78 case charset_id::utf16: return "UTF-16BE";
    +
    79 case charset_id::utf32: return "UTF-32BE";
    +
    80#else
    +
    81 case charset_id::utf16: return "UTF-16LE";
    +
    82 case charset_id::utf32: return "UTF-32LE";
    +
    83#endif
    +
    84 default: throw std::invalid_argument("unsupported charset");
    +
    85 }
    +
    86 }
    +
    87
    +
    88 protected:
    +
    89 iconv_t m_handle;
    +
    90 };
    +
    +
    91#endif
    +
    92
    +
    101 inline void strcat(
    +
    102 _Inout_ std::wstring& dst,
    +
    103 _In_reads_or_z_opt_(count_src) const char* src, _In_ size_t count_src,
    +
    104 _In_ charset_id charset = charset_id::system)
    +
    105 {
    +
    106 assert(src || !count_src);
    +
    107#ifdef _WIN32
    +
    108 assert(count_src < INT_MAX || count_src == SIZE_MAX);
    +
    109 constexpr DWORD dwFlags = MB_PRECOMPOSED;
    +
    110
    +
    111 // Try to convert to stack buffer first.
    +
    112 WCHAR szStackBuffer[1024/sizeof(WCHAR)];
    +
    113#pragma warning(suppress: 6387) // Testing indicates src may be NULL when count_src is also 0. Is SAL of the lpMultiByteStr parameter wrong?
    +
    114 int cch = MultiByteToWideChar(static_cast<UINT>(charset), dwFlags, src, static_cast<int>(count_src), szStackBuffer, _countof(szStackBuffer));
    +
    115 if (cch) {
    +
    116 // Append from stack.
    +
    117 dst.append(szStackBuffer, count_src != SIZE_MAX ? wcsnlen(szStackBuffer, cch) : (size_t)cch - 1);
    +
    118 } else if (::GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
    +
    119 // Query the required output size. Allocate buffer. Then convert again.
    +
    120 cch = MultiByteToWideChar(static_cast<UINT>(charset), dwFlags, src, static_cast<int>(count_src), NULL, 0);
    +
    121 std::unique_ptr<WCHAR[]> szBuffer(new WCHAR[cch]);
    +
    122 cch = MultiByteToWideChar(static_cast<UINT>(charset), dwFlags, src, static_cast<int>(count_src), szBuffer.get(), cch);
    +
    123 dst.append(szBuffer.get(), count_src != SIZE_MAX ? wcsnlen(szBuffer.get(), cch) : (size_t)cch - 1);
    +
    124 }
    +
    125#else
    +
    126 iconverter<char, wchar_t>(charset, charset_id::utf32).convert(dst, src, count_src);
    +
    127#endif
    +
    128 }
    +
    129
    +
    130 _Deprecated_("Use stdex::strcat")
    +
    131 inline void str2wstr(
    +
    132 _Inout_ std::wstring& dst,
    +
    133 _In_reads_or_z_opt_(count_src) const char* src, _In_ size_t count_src,
    +
    134 _In_ charset_id charset = charset_id::system)
    +
    135 {
    +
    136 strcat(dst, src, count_src, charset);
    +
    137 }
    +
    138
    +
    146 inline void strcat(
    +
    147 _Inout_ std::wstring& dst,
    +
    148 _In_ const std::string& src,
    +
    149 _In_ charset_id charset = charset_id::system)
    +
    150 {
    +
    151 strcat(dst, src.data(), src.size(), charset);
    +
    152 }
    +
    153
    +
    154 _Deprecated_("Use stdex::strcat")
    +
    155 inline void str2wstr(
    +
    156 _Inout_ std::wstring& dst,
    +
    157 _In_ const std::string& src,
    +
    158 _In_ charset_id charset = charset_id::system)
    +
    159 {
    +
    160 strcat(dst, src, charset);
    +
    161 }
    +
    162
    +
    171 inline void strcpy(
    +
    172 _Inout_ std::wstring& dst,
    +
    173 _In_reads_or_z_opt_(count_src) const char* src, _In_ size_t count_src,
    +
    174 _In_ charset_id charset = charset_id::system)
    +
    175 {
    +
    176 dst.clear();
    +
    177 strcat(dst, src, count_src, charset);
    +
    178 }
    +
    179
    +
    187 inline void strcpy(
    +
    188 _Inout_ std::wstring& dst,
    +
    189 _In_ const std::string& src,
    +
    190 _In_ charset_id charset = charset_id::system)
    +
    191 {
    +
    192 strcpy(dst, src.data(), src.size(), charset);
    +
    193 }
    +
    194
    +
    203 inline std::wstring str2wstr(
    +
    204 _In_z_ const char* src,
    +
    205 _In_ charset_id charset = charset_id::system)
    +
    206 {
    +
    207 std::wstring dst;
    +
    208 strcat(dst, src, SIZE_MAX, charset);
    +
    209 return dst;
    +
    210 }
    +
    211
    +
    221 inline std::wstring str2wstr(
    +
    222 _In_reads_or_z_opt_(count_src) const char* src, _In_ size_t count_src,
    +
    223 _In_ charset_id charset = charset_id::system)
    +
    224 {
    +
    225 std::wstring dst;
    +
    226 strcat(dst, src, count_src, charset);
    +
    227 return dst;
    +
    228 }
    +
    229
    +
    238 inline std::wstring str2wstr(
    +
    239 _In_ const std::string& src,
    +
    240 _In_ charset_id charset = charset_id::system)
    +
    241 {
    +
    242 return str2wstr(src.c_str(), src.size(), charset);
    +
    243 }
    +
    244
    +
    253 inline void strcat(
    +
    254 _Inout_ std::string& dst,
    +
    255 _In_reads_or_z_opt_(count_src) const wchar_t* src, _In_ size_t count_src,
    +
    256 _In_ charset_id charset = charset_id::system)
    +
    257 {
    +
    258 assert(src || !count_src);
    +
    259#ifdef _WIN32
    +
    260 assert(count_src < INT_MAX || count_src == SIZE_MAX);
    +
    261 constexpr DWORD dwFlags = 0;
    +
    262 constexpr LPCCH lpDefaultChar = NULL;
    +
    263
    +
    264 // Try to convert to stack buffer first.
    +
    265 CHAR szStackBuffer[1024/sizeof(CHAR)];
    +
    266#pragma warning(suppress: 6387) // Testing indicates src may be NULL when count_src is also 0. Is SAL of the lpWideCharStr parameter wrong?
    +
    267 int cch = WideCharToMultiByte(static_cast<UINT>(charset), dwFlags, src, static_cast<int>(count_src), szStackBuffer, _countof(szStackBuffer), lpDefaultChar, NULL);
    +
    268 if (cch) {
    +
    269 // Copy from stack. Be careful not to include zero terminator.
    +
    270 dst.append(szStackBuffer, count_src != SIZE_MAX ? strnlen(szStackBuffer, cch) : (size_t)cch - 1);
    +
    271 } else if (::GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
    +
    272 // Query the required output size. Allocate buffer. Then convert again.
    +
    273 cch = WideCharToMultiByte(static_cast<UINT>(charset), dwFlags, src, static_cast<int>(count_src), NULL, 0, lpDefaultChar, NULL);
    +
    274 std::unique_ptr<CHAR[]> szBuffer(new CHAR[cch]);
    +
    275 cch = WideCharToMultiByte(static_cast<UINT>(charset), dwFlags, src, static_cast<int>(count_src), szBuffer.get(), cch, lpDefaultChar, NULL);
    +
    276 dst.append(szBuffer.get(), count_src != SIZE_MAX ? strnlen(szBuffer.get(), cch) : (size_t)cch - 1);
    +
    277 }
    +
    278#else
    +
    279 iconverter<wchar_t, char>(charset_id::utf32, charset).convert(dst, src, count_src);
    +
    280#endif
    +
    281 }
    +
    282
    +
    283 _Deprecated_("Use stdex::strcat")
    +
    284 inline void wstr2str(
    +
    285 _Inout_ std::string& dst,
    +
    286 _In_reads_or_z_opt_(count_src) const wchar_t* src, _In_ size_t count_src,
    +
    287 _In_ charset_id charset = charset_id::system)
    +
    288 {
    +
    289 strcat(dst, src, count_src, charset);
    +
    290 }
    +
    291
    +
    299 inline void strcat(
    +
    300 _Inout_ std::string& dst,
    +
    301 _In_ const std::wstring& src,
    +
    302 _In_ charset_id charset = charset_id::system)
    +
    303 {
    +
    304 strcat(dst, src.c_str(), src.size(), charset);
    +
    305 }
    +
    306
    +
    307 _Deprecated_("Use stdex::strcat")
    +
    308 inline void wstr2str(
    +
    309 _Inout_ std::string& dst,
    +
    310 _In_ const std::wstring& src,
    +
    311 _In_ charset_id charset = charset_id::system)
    +
    312 {
    +
    313 strcat(dst, src, charset);
    +
    314 }
    +
    315
    +
    324 inline void strcpy(
    +
    325 _Inout_ std::string& dst,
    +
    326 _In_reads_or_z_opt_(count_src) const wchar_t* src, _In_ size_t count_src,
    +
    327 _In_ charset_id charset = charset_id::system)
    +
    328 {
    +
    329 dst.clear();
    +
    330 strcat(dst, src, count_src, charset);
    +
    331 }
    +
    332
    +
    340 inline void strcpy(
    +
    341 _Inout_ std::string& dst,
    +
    342 _In_ const std::wstring& src,
    +
    343 _In_ charset_id charset = charset_id::system)
    +
    344 {
    +
    345 strcpy(dst, src.data(), src.size(), charset);
    +
    346 }
    +
    347
    +
    356 inline std::string wstr2str(
    +
    357 _In_z_ const wchar_t* src,
    +
    358 _In_ charset_id charset = charset_id::system)
    +
    359 {
    +
    360 std::string dst;
    +
    361 strcat(dst, src, SIZE_MAX, charset);
    +
    362 return dst;
    +
    363 }
    +
    364
    +
    374 inline std::string wstr2str(
    +
    375 _In_reads_or_z_opt_(count_src) const wchar_t* src, _In_ size_t count_src,
    +
    376 _In_ charset_id charset = charset_id::system)
    +
    377 {
    +
    378 std::string dst;
    +
    379 strcat(dst, src, count_src, charset);
    +
    380 return dst;
    +
    381 }
    +
    382
    +
    391 inline std::string wstr2str(
    +
    392 _In_ const std::wstring& src,
    +
    393 _In_ charset_id charset = charset_id::system)
    +
    394 {
    +
    395 return wstr2str(src.c_str(), src.size(), charset);
    +
    396 }
    +
    397}
    +
    Unicode converter context.
    Definition unicode.hpp:41
    diff --git a/vector__queue_8hpp_source.html b/vector__queue_8hpp_source.html index 3d56e69b4..97b1b4396 100644 --- a/vector__queue_8hpp_source.html +++ b/vector__queue_8hpp_source.html @@ -89,7 +89,7 @@ $(document).ready(function() { init_codefold(0); });
    5
    6#pragma once
    7
    -
    8#include "sal.hpp"
    +
    8#include "compat.hpp"
    9
    10namespace stdex
    11{
    @@ -451,7 +451,7 @@ $(document).ready(function() { init_codefold(0); });