stdex
Additional custom or not Standard C++ covered algorithms
Loading...
Searching...
No Matches
parser.cpp
1/*
2 SPDX-License-Identifier: MIT
3 Copyright © 2023-2024 Amebis
4*/
5
6#include "pch.hpp"
7
8using namespace std;
9#ifdef _WIN32
10using namespace Microsoft::VisualStudio::CppUnitTestFramework;
11
12namespace Microsoft {
13 namespace VisualStudio {
14 namespace CppUnitTestFramework {
15 static wstring ToString(const stdex::interval<size_t>& q)
16 {
17 return stdex::sprintf(L"<%zu, %zu>", nullptr, q.start, q.end);
18 }
19 }
20 }
21}
22#endif
23
24namespace UnitTests
25{
26 TEST_CLASS(parser)
27 {
28 public:
29 TEST_METHOD(wtest)
30 {
31 static const wchar_t text[] = L"This is a test.\nSecond line.";
32
33 {
35 Assert::IsTrue(p.match(text));
36 Assert::AreEqual((size_t)0, p.interval.start);
37 Assert::AreEqual((size_t)0, p.interval.end);
38 }
39
40 {
41 stdex::parser::wcu p(L't');
42 Assert::IsFalse(p.match(text));
43 Assert::IsTrue(p.match(text, 0, _countof(text), stdex::parser::match_case_insensitive));
44 Assert::AreEqual((size_t)0, p.interval.start);
45 Assert::AreEqual((size_t)1, p.interval.end);
46 }
47
48 {
50 Assert::IsFalse(p.match(text));
51 Assert::IsTrue(p.match(text, 4));
52 Assert::AreEqual((size_t)4, p.interval.start);
53 Assert::AreEqual((size_t)5, p.interval.end);
54 }
55
56 {
58 Assert::IsFalse(p.match(text));
59 Assert::IsTrue(p.match(text, 14));
60 Assert::AreEqual((size_t)14, p.interval.start);
61 Assert::AreEqual((size_t)15, p.interval.end);
62 }
63
64 {
66 Assert::IsFalse(p.match(text));
67 Assert::IsTrue(p.match(text, 4));
68 Assert::AreEqual((size_t)4, p.interval.start);
69 Assert::AreEqual((size_t)5, p.interval.end);
70 Assert::IsTrue(p.match(text, 14));
71 Assert::AreEqual((size_t)14, p.interval.start);
72 Assert::AreEqual((size_t)15, p.interval.end);
73 }
74
75 {
77 Assert::IsTrue(p.match(text));
78 Assert::AreEqual((size_t)0, p.interval.start);
79 Assert::AreEqual((size_t)0, p.interval.end);
80 Assert::IsFalse(p.match(text, 1));
81 Assert::IsFalse(p.match(text, 15));
82 Assert::IsTrue(p.match(text, 16));
83 Assert::AreEqual((size_t)16, p.interval.start);
84 Assert::AreEqual((size_t)16, p.interval.end);
85 }
86
87 {
89 Assert::IsFalse(p.match(text));
90 Assert::IsFalse(p.match(text, 1));
91 Assert::IsTrue(p.match(text, 15));
92 Assert::AreEqual((size_t)15, p.interval.start);
93 Assert::AreEqual((size_t)15, p.interval.end);
94 Assert::IsFalse(p.match(text, 16));
95 }
96
97 {
98 stdex::parser::wcu_set p(L"abcD");
99 Assert::IsFalse(p.match(text));
100 Assert::IsTrue(p.match(text, 8));
101 Assert::AreEqual((size_t)8, p.interval.start);
102 Assert::AreEqual((size_t)9, p.interval.end);
103 Assert::AreEqual((size_t)0, p.hit_offset);
104 Assert::IsFalse(p.match(text, 21));
105 Assert::IsTrue(p.match(text, 21, _countof(text), stdex::parser::match_case_insensitive));
106 Assert::AreEqual((size_t)21, p.interval.start);
107 Assert::AreEqual((size_t)22, p.interval.end);
108 Assert::AreEqual((size_t)3, p.hit_offset);
109 }
110
111 {
112 stdex::parser::wstring p(L"this");
113 Assert::IsFalse(p.match(text));
114 Assert::IsTrue(p.match(text, 0, sizeof(text), stdex::parser::match_case_insensitive));
115 Assert::AreEqual((size_t)0, p.interval.start);
116 Assert::AreEqual((size_t)4, p.interval.end);
117 }
118
119 {
121 stdex::parser::witerations p(stdex::make_shared_no_delete(&chr), 1, 5);
122 Assert::IsTrue(p.match(text));
123 Assert::AreEqual((size_t)0, p.interval.start);
124 Assert::AreEqual((size_t)5, p.interval.end);
125 }
126
127 {
128 stdex::parser::wspace_cu nospace(true);
129 stdex::parser::witerations p(stdex::make_shared_no_delete(&nospace), 1);
130 Assert::IsTrue(p.match(text));
131 Assert::AreEqual((size_t)0, p.interval.start);
132 Assert::AreEqual((size_t)4, p.interval.end);
133 }
134
135 {
136 stdex::parser::wcu chr_t(L't'), chr_h(L'h'), chr_i(L'i'), chr_s(L's');
139 stdex::make_shared_no_delete(&chr_t),
140 stdex::make_shared_no_delete(&chr_h),
141 stdex::make_shared_no_delete(&chr_i),
142 stdex::make_shared_no_delete(&chr_s),
143 stdex::make_shared_no_delete(&space) });
144 Assert::IsFalse(p.match(text));
145 Assert::IsTrue(p.match(text, 0, _countof(text), stdex::parser::match_case_insensitive));
146 Assert::AreEqual((size_t)0, p.interval.start);
147 Assert::AreEqual((size_t)5, p.interval.end);
148 }
149
150 {
151 stdex::parser::wstring apple(L"apple"), orange(L"orange"), _this(L"this");
154 stdex::make_shared_no_delete(&apple),
155 stdex::make_shared_no_delete(&orange),
156 stdex::make_shared_no_delete(&_this),
157 stdex::make_shared_no_delete(&space) });
158 Assert::IsFalse(p.match(text));
159 Assert::IsTrue(p.match(text, 0, _countof(text), stdex::parser::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 stdex::parser::wstring_branch p(L"apple", L"orange", L"this", nullptr);
167 Assert::IsFalse(p.match(text));
168 Assert::IsTrue(p.match(text, 0, _countof(text), stdex::parser::match_case_insensitive));
169 Assert::AreEqual((size_t)2, p.hit_offset);
170 Assert::AreEqual((size_t)0, p.interval.start);
171 Assert::AreEqual((size_t)4, p.interval.end);
172 }
173
174 {
175 stdex::parser::wcu chr_s(L's'), chr_h(L'h'), chr_i(L'i'), chr_t(L't');
177 stdex::make_shared_no_delete(&chr_s),
178 stdex::make_shared_no_delete(&chr_h),
179 stdex::make_shared_no_delete(&chr_i),
180 stdex::make_shared_no_delete(&chr_t) });
181 Assert::IsFalse(p.match(text));
182 Assert::IsTrue(p.match(text, 0, _countof(text), stdex::parser::match_case_insensitive));
183 Assert::AreEqual((size_t)0, p.interval.start);
184 Assert::AreEqual((size_t)4, p.interval.end);
185 }
186
187 {
188 std::locale locale_slSI("sl_SI");
189 stdex::parser::wspace_cu space(false, locale_slSI);
190 stdex::parser::wiban p(stdex::make_shared_no_delete(&space), locale_slSI);
191 Assert::IsTrue(p.match(L"SI56023120015226972", 0, SIZE_MAX));
192 Assert::IsTrue(p.is_valid);
193 Assert::AreEqual(L"SI", p.country);
194 Assert::AreEqual(L"56", p.check_digits);
195 Assert::AreEqual(L"023120015226972", p.bban);
196 Assert::IsTrue(p.match(L"SI56 0231 2001 5226 972", 0, SIZE_MAX));
197 Assert::IsTrue(p.is_valid);
198 Assert::AreEqual(L"SI", p.country);
199 Assert::AreEqual(L"56", p.check_digits);
200 Assert::AreEqual(L"023120015226972", p.bban);
201 Assert::IsFalse(p.match(L"si56 0231 2001 5226 972", 0, SIZE_MAX));
202 Assert::IsFalse(p.is_valid);
203 Assert::IsTrue(p.match(L"si56 0231 2001 5226 972", 0, SIZE_MAX, stdex::parser::match_case_insensitive));
204 Assert::IsTrue(p.is_valid);
205 Assert::IsTrue(p.match(L"SI56 0231 2001 5226 9720", 0, SIZE_MAX));
206 Assert::AreEqual(stdex::interval<size_t>(0, 23), p.interval);
207 Assert::IsTrue(p.is_valid);
208 Assert::IsTrue(p.match(L"...SI56 0231 2001 5226 972...", 3, SIZE_MAX));
209 Assert::IsTrue(p.is_valid);
210 Assert::IsTrue(p.match(L"SI56 0231 2001 5226 972", 0, SIZE_MAX)); // no-break space
211 Assert::IsTrue(p.is_valid);
212
213 Assert::IsTrue(p.match(L"BE71 0961 2345 6769", 0, SIZE_MAX));
214 Assert::IsTrue(p.is_valid);
215 Assert::IsTrue(p.match(L"BR15 0000 0000 0000 1093 2840 814 P2", 0, SIZE_MAX));
216 Assert::IsTrue(p.is_valid);
217 Assert::IsTrue(p.match(L"CR99 0000 0000 0000 8888 88", 0, SIZE_MAX));
218 Assert::IsFalse(p.is_valid);
219 Assert::IsTrue(p.match(L"FR76 3000 6000 0112 3456 7890 189", 0, SIZE_MAX));
220 Assert::IsTrue(p.is_valid);
221 Assert::IsTrue(p.match(L"IE12 BOFI 9000 0112 3456 78", 0, SIZE_MAX));
222 Assert::IsFalse(p.is_valid);
223 Assert::IsTrue(p.match(L"DE91 1000 0000 0123 4567 89", 0, SIZE_MAX));
224 Assert::IsTrue(p.is_valid);
225 Assert::IsTrue(p.match(L"GR96 0810 0010 0000 0123 4567 890", 0, SIZE_MAX));
226 Assert::IsTrue(p.is_valid);
227 Assert::IsTrue(p.match(L"MU43 BOMM 0101 1234 5678 9101 000 MUR", 0, SIZE_MAX));
228 Assert::IsTrue(p.is_valid);
229 Assert::IsTrue(p.match(L"PK70 BANK 0000 1234 5678 9000", 0, SIZE_MAX));
230 Assert::IsTrue(p.is_valid);
231 Assert::IsTrue(p.match(L"PL10 1050 0099 7603 1234 5678 9123", 0, SIZE_MAX));
232 Assert::IsTrue(p.is_valid);
233 Assert::IsTrue(p.match(L"RO09 BCYP 0000 0012 3456 7890", 0, SIZE_MAX));
234 Assert::IsTrue(p.is_valid);
235 Assert::IsTrue(p.match(L"LC14 BOSL 1234 5678 9012 3456 7890 1234", 0, SIZE_MAX));
236 Assert::IsTrue(p.is_valid);
237 Assert::IsTrue(p.match(L"SA44 2000 0001 2345 6789 1234", 0, SIZE_MAX));
238 Assert::IsTrue(p.is_valid);
239 Assert::IsTrue(p.match(L"ES79 2100 0813 6101 2345 6789", 0, SIZE_MAX));
240 Assert::IsTrue(p.is_valid);
241 Assert::IsTrue(p.match(L"SE87 3000 0000 0101 2345 6789", 0, SIZE_MAX));
242 Assert::IsFalse(p.is_valid);
243 Assert::IsTrue(p.match(L"CH56 0483 5012 3456 7800 9", 0, SIZE_MAX));
244 Assert::IsTrue(p.is_valid);
245 Assert::IsTrue(p.match(L"GB98 MIDL 0700 9312 3456 78", 0, SIZE_MAX));
246 Assert::IsTrue(p.is_valid);
247 }
248
249 {
250 std::locale locale_slSI("sl_SI");
251 stdex::parser::wspace_cu space(false, locale_slSI);
252 stdex::parser::wcreditor_reference p(stdex::make_shared_no_delete(&space), locale_slSI);
253 Assert::IsTrue(p.match(L"RF18539007547034", 0, SIZE_MAX));
254 Assert::IsTrue(p.is_valid);
255 Assert::AreEqual(L"18", p.check_digits);
256 Assert::AreEqual(L"000000000539007547034", p.reference);
257 Assert::IsTrue(p.match(L"RF18 5390 0754 7034", 0, SIZE_MAX));
258 Assert::IsTrue(p.is_valid);
259 Assert::AreEqual(L"18", p.check_digits);
260 Assert::AreEqual(L"000000000539007547034", p.reference);
261 Assert::IsFalse(p.match(L"rf18 5390 0754 7034", 0, SIZE_MAX));
262 Assert::IsFalse(p.is_valid);
263 Assert::IsTrue(p.match(L"rf18 5390 0754 7034", 0, SIZE_MAX, stdex::parser::match_case_insensitive));
264 Assert::IsTrue(p.is_valid);
265 Assert::IsTrue(p.match(L"RF18 5390 0754 70340", 0, SIZE_MAX));
266 Assert::IsFalse(p.is_valid);
267 Assert::IsTrue(p.match(L"...RF18 5390 0754 7034...", 3, SIZE_MAX));
268 Assert::IsTrue(p.is_valid);
269 Assert::IsTrue(p.match(L"RF18 5390 0754 7034", 0, SIZE_MAX)); // no-break space
270 Assert::IsTrue(p.is_valid);
271 }
272
273 {
274 std::locale locale_slSI("sl_SI");
275 stdex::parser::wspace_cu space(false, locale_slSI);
276 stdex::parser::wsi_reference p(stdex::make_shared_no_delete(&space), locale_slSI);
277 Assert::IsTrue(p.match(L"SI121234567890120", 0, SIZE_MAX));
278 Assert::IsTrue(p.is_valid);
279 Assert::AreEqual(L"12", p.model);
280 Assert::AreEqual(stdex::interval<size_t>(4, 17), p.part1.interval);
281 Assert::IsTrue(p.match(L"SI12 1234567890120", 0, SIZE_MAX));
282 Assert::IsTrue(p.is_valid);
283 Assert::AreEqual(L"12", p.model);
284 Assert::AreEqual(stdex::interval<size_t>(5, 18), p.part1.interval);
285 Assert::IsFalse(p.match(L"si12 1234567890120", 0, SIZE_MAX));
286 Assert::IsTrue(p.match(L"si12 1234567890120", 0, SIZE_MAX, stdex::parser::match_case_insensitive));
287 Assert::IsTrue(p.match(L"...SI12 1234567890120...", 3, SIZE_MAX));
288 Assert::IsTrue(p.match(L"SI12 1234567890120", 0, SIZE_MAX)); // no-break space
289 }
290 }
291
292 TEST_METHOD(sgml_test)
293 {
294 std::locale locale_slSI("sl_SI");
295 static const char text[] = "V ko&zcaron;u&scaron;&ccaron;ku zlobnega mizarja stopiclja fant\nin kli&ccaron;e&nbsp;1234567890.";
296
297 {
299 Assert::IsTrue(p.match(text));
300 Assert::AreEqual((size_t)0, p.interval.start);
301 Assert::AreEqual((size_t)0, p.interval.end);
302 }
303
304 {
306 Assert::IsFalse(p.match(text));
307 Assert::IsTrue(p.match(text, 0, _countof(text), stdex::parser::match_case_insensitive));
308 Assert::AreEqual((size_t)0, p.interval.start);
309 Assert::AreEqual((size_t)1, p.interval.end);
310 }
311
312 {
313 stdex::parser::sgml_cp p("&Zcaron;", SIZE_MAX, false, locale_slSI);
314 Assert::IsFalse(p.match(text, 4));
315 Assert::IsTrue(p.match(text, 4, _countof(text), stdex::parser::match_case_insensitive));
316 Assert::AreEqual((size_t)4, p.interval.start);
317 Assert::AreEqual((size_t)12, p.interval.end);
318 }
319
320 {
321 stdex::parser::sgml_space_cp p(false, locale_slSI);
322 Assert::IsFalse(p.match(text));
323 Assert::IsTrue(p.match(text, 1));
324 Assert::AreEqual((size_t)1, p.interval.start);
325 Assert::AreEqual((size_t)2, p.interval.end);
326 Assert::IsTrue(p.match(text, 79));
327 Assert::AreEqual((size_t)79, p.interval.start);
328 Assert::AreEqual((size_t)85, p.interval.end);
329 }
330
331 {
332 stdex::parser::sgml_string_branch p(locale_slSI, "apple", "orange", "Ko&Zcaron;u&Scaron;&ccaron;Ku", nullptr);
333 Assert::IsFalse(p.match(text, 2));
334 Assert::IsTrue(p.match(text, 2, _countof(text), stdex::parser::match_case_insensitive));
335 Assert::AreEqual((size_t)2, p.hit_offset);
336 Assert::AreEqual((size_t)2, p.interval.start);
337 Assert::AreEqual((size_t)31, p.interval.end);
338 }
339
340 {
341 stdex::parser::sgml_space_cp space(false, locale_slSI);
342 stdex::parser::sgml_iban p(stdex::make_shared_no_delete(&space), locale_slSI);
343 Assert::IsTrue(p.match("SI56023120015226972", 0, SIZE_MAX));
344 Assert::IsTrue(p.is_valid);
345 Assert::AreEqual("SI", p.country);
346 Assert::AreEqual("56", p.check_digits);
347 Assert::AreEqual("023120015226972", p.bban);
348 Assert::IsTrue(p.match("SI56 0231 2001 5226 972", 0, SIZE_MAX));
349 Assert::IsTrue(p.is_valid);
350 Assert::AreEqual("SI", p.country);
351 Assert::AreEqual("56", p.check_digits);
352 Assert::AreEqual("023120015226972", p.bban);
353 Assert::IsFalse(p.match("si56 0231 2001 5226 972", 0, SIZE_MAX));
354 Assert::IsFalse(p.is_valid);
355 Assert::IsTrue(p.match("si56 0231 2001 5226 972", 0, SIZE_MAX, stdex::parser::match_case_insensitive));
356 Assert::IsTrue(p.is_valid);
357 Assert::IsTrue(p.match("SI56 0231 2001 5226 9720", 0, SIZE_MAX));
358 Assert::AreEqual(stdex::interval<size_t>(0, 23), p.interval);
359 Assert::IsTrue(p.is_valid);
360 Assert::IsTrue(p.match("...SI56 0231 2001 5226 972...", 3, SIZE_MAX));
361 Assert::IsTrue(p.is_valid);
362 Assert::IsTrue(p.match("SI56&nbsp;0231&nbsp;2001&nbsp;5226&nbsp;972", 0, SIZE_MAX));
363 Assert::IsTrue(p.is_valid);
364 }
365
366 {
367 stdex::parser::sgml_space_cp space(false, locale_slSI);
368 stdex::parser::sgml_creditor_reference p(stdex::make_shared_no_delete(&space), locale_slSI);
369 Assert::IsTrue(p.match("RF18539007547034", 0, SIZE_MAX));
370 Assert::IsTrue(p.is_valid);
371 Assert::AreEqual("18", p.check_digits);
372 Assert::AreEqual("000000000539007547034", p.reference);
373 Assert::IsTrue(p.match("RF18 5390 0754 7034", 0, SIZE_MAX));
374 Assert::IsTrue(p.is_valid);
375 Assert::AreEqual("18", p.check_digits);
376 Assert::AreEqual("000000000539007547034", p.reference);
377 Assert::IsFalse(p.match("rf18 5390 0754 7034", 0, SIZE_MAX));
378 Assert::IsFalse(p.is_valid);
379 Assert::IsTrue(p.match("rf18 5390 0754 7034", 0, SIZE_MAX, stdex::parser::match_case_insensitive));
380 Assert::IsTrue(p.is_valid);
381 Assert::IsTrue(p.match("RF18 5390 0754 70340", 0, SIZE_MAX));
382 Assert::IsFalse(p.is_valid);
383 Assert::IsTrue(p.match("...RF18 5390 0754 7034...", 3, SIZE_MAX));
384 Assert::IsTrue(p.is_valid);
385 Assert::IsTrue(p.match("RF18&nbsp;5390&nbsp;0754&nbsp;7034", 0, SIZE_MAX));
386 Assert::IsTrue(p.is_valid);
387 }
388
389 {
390 stdex::parser::sgml_space_cp space(false, locale_slSI);
391 stdex::parser::sgml_si_reference p(stdex::make_shared_no_delete(&space), locale_slSI);
392 Assert::IsTrue(p.match("SI121234567890120", 0, SIZE_MAX));
393 Assert::IsTrue(p.is_valid);
394 Assert::AreEqual("12", p.model);
395 Assert::AreEqual(stdex::interval<size_t>(4, 17), p.part1.interval);
396 Assert::IsTrue(p.match("SI12 1234567890120", 0, SIZE_MAX));
397 Assert::IsTrue(p.is_valid);
398 Assert::AreEqual("12", p.model);
399 Assert::AreEqual(stdex::interval<size_t>(5, 18), p.part1.interval);
400 Assert::IsFalse(p.match("si12 1234567890120", 0, SIZE_MAX));
401 Assert::IsTrue(p.match("si12 1234567890120", 0, SIZE_MAX, stdex::parser::match_case_insensitive));
402 Assert::IsTrue(p.match("...SI12 1234567890120...", 3, SIZE_MAX));
403 Assert::IsTrue(p.match("SI12&nbsp;1234567890120", 0, SIZE_MAX));
404 }
405 }
406
407 TEST_METHOD(http_test)
408 {
409 static const std::locale locale("en_US.UTF-8");
410 static const char request[] =
411 "GET / HTTP/2\r\n"
412 "Host: stackoverflow.com\r\n"
413 "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/110.0\r\n"
414 "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8\r\n"
415 "Accept-Language: sl,en-US;q=0.8,en;q=0.6,de-DE;q=0.4,de;q=0.2\r\n"
416 "Accept-Encoding: gzip, deflate, br\r\n"
417 "DNT: 1\r\n"
418 "Connection: keep-alive\r\n"
419 "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"
420 "Upgrade-Insecure-Requests: 1\r\n"
421 "Sec-Fetch-Dest: document\r\n"
422 "Sec-Fetch-Mode: navigate\r\n"
423 "Sec-Fetch-Site: none\r\n"
424 "Sec-Fetch-User: ?1\r\n"
425 "Pragma: no-cache\r\n"
426 "Cache-Control: no-cache\r\n"
427 "\r\n";
428
429 {
431 Assert::IsTrue(p.match(request));
432 Assert::AreEqual((size_t)0, p.interval.start);
433 Assert::AreEqual((size_t)14, p.interval.end);
434 Assert::AreEqual((size_t)0, p.verb.start);
435 Assert::AreEqual((size_t)3, p.verb.end);
436 Assert::AreEqual((size_t)4, p.url.interval.start);
437 Assert::AreEqual((size_t)5, p.url.interval.end);
438 Assert::AreEqual((size_t)6, p.protocol.interval.start);
439 Assert::AreEqual((size_t)12, p.protocol.interval.end);
440 Assert::AreEqual((uint16_t)0x200, p.protocol.version);
441 }
442
443 {
444 list<stdex::parser::http_header> hdrs;
445 size_t offset = 14;
446 for (;;) {
448 if (h.match(request, offset)) {
449 offset = h.interval.end;
450 hdrs.push_back(std::move(h));
451 }
452 else
453 break;
454 }
455 Assert::AreEqual((size_t)15, hdrs.size());
457 for (const auto& h : hdrs)
458 if (stdex::strnicmp(request + h.name.start, h.name.size(), "Accept-Language", SIZE_MAX, locale) == 0)
459 langs.insert(request, h.value.start, h.value.end);
460 Assert::IsTrue(!langs.empty());
461 {
462 const vector<string> control = {
463 "sl", "en-US", "en", "de-DE", "de"
464 };
465 auto c = control.cbegin();
466 auto l = langs.cbegin();
467 for (; c != control.cend() && l != langs.cend(); ++c, ++l)
468 Assert::IsTrue(stdex::strnicmp(request + l->value.interval.start, l->value.interval.size(), c->c_str(), c->size(), locale) == 0);
469 Assert::IsTrue(c == control.cend());
470 Assert::IsTrue(l == langs.cend());
471 }
472 }
473
474 //static const char response[] =
475 // "HTTP/2 200 OK\r\n"
476 // "cache-control: private\r\n"
477 // "content-type: text/html; charset=utf-8\r\n"
478 // "content-encoding: gzip\r\n"
479 // "strict-transport-security: max-age=15552000\r\n"
480 // "x-frame-options: SAMEORIGIN\r\n"
481 // "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"
482 // "set-cookie: prov_tgt=; expires=Tue, 14 Mar 2023 10:23:00 GMT; domain=.stackoverflow.com; path=/; secure; samesite=none; httponly\r\n"
483 // "x-request-guid: a6536a49-b473-4c6f-b313-c1e7c0d8f600\r\n"
484 // "feature-policy: microphone 'none'; speaker 'none'\r\n"
485 // "content-security-policy: upgrade-insecure-requests; frame-ancestors 'self' https://stackexchange.com\r\n"
486 // "accept-ranges: bytes\r\n"
487 // "date: Thu, 16 Mar 2023 10:23:00 GMT\r\n"
488 // "via: 1.1 varnish\r\n"
489 // "x-served-by: cache-vie6354-VIE\r\n"
490 // "x-cache: MISS\r\n"
491 // "x-cache-hits: 0\r\n"
492 // "x-timer: S1678962181.533907,VS0,VE144\r\n"
493 // "vary: Accept-Encoding,Fastly-SSL\r\n"
494 // "x-dns-prefetch-control: off\r\n"
495 // "X-Firefox-Spdy: h2\r\n"
496 // "\r\n";
497 }
498 };
499}
stdex::interval< size_t > interval
Region of the last match.
Definition parser.hpp:116
Test for given string.
Definition parser.hpp:831
Test for HTTP header.
Definition parser.hpp:7069
Test for HTTP request.
Definition parser.hpp:6937
Test for specific SGML code point.
Definition parser.hpp:353
Test for any SGML space code point.
Definition parser.hpp:440
Numerical interval.
Definition interval.hpp:18
T end
interval end
Definition interval.hpp:20