]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/json/test/basic_parser.cpp
import quincy beta 17.1.0
[ceph.git] / ceph / src / boost / libs / json / test / basic_parser.cpp
1 //
2 // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
3 // Copyright (c) 2020 Krystian Stasiowski (sdkrystian@gmail.com)
4 //
5 // Distributed under the Boost Software License, Version 1.0. (See accompanying
6 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 //
8 // Official repository: https://github.com/boostorg/json
9 //
10
11 // Test that header file is self-contained.
12 #include <boost/json/basic_parser_impl.hpp>
13
14 #include <memory>
15 #include <string>
16 #include <utility>
17
18 #include "parse-vectors.hpp"
19 #include "test.hpp"
20 #include "test_suite.hpp"
21
22 BOOST_JSON_NS_BEGIN
23
24 BOOST_STATIC_ASSERT( std::is_nothrow_destructible<basic_parser<int>>::value );
25
26 namespace base64 {
27
28 std::size_t constexpr
29 decoded_size(std::size_t n)
30 {
31 return n / 4 * 3; // requires n&3==0, smaller
32 }
33
34 signed char const*
35 get_inverse()
36 {
37 static signed char constexpr tab[] = {
38 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0-15
39 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 16-31
40 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, // 32-47
41 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, // 48-63
42 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, // 64-79
43 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, // 80-95
44 -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, // 96-111
45 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, // 112-127
46 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 128-143
47 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 144-159
48 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 160-175
49 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 176-191
50 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 192-207
51 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 208-223
52 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 224-239
53 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 // 240-255
54 };
55 return &tab[0];
56 }
57
58 std::pair<std::size_t, std::size_t>
59 decode(void* dest, char const* src, std::size_t len)
60 {
61 char* out = static_cast<char*>(dest);
62 auto in = reinterpret_cast<unsigned char const*>(src);
63 unsigned char c3[3], c4[4];
64 int i = 0;
65 int j = 0;
66
67 auto const inverse = base64::get_inverse();
68
69 while(len-- && *in != '=')
70 {
71 auto const v = inverse[*in];
72 if(v == -1)
73 break;
74 ++in;
75 c4[i] = v;
76 if(++i == 4)
77 {
78 c3[0] = (c4[0] << 2) + ((c4[1] & 0x30) >> 4);
79 c3[1] = ((c4[1] & 0xf) << 4) + ((c4[2] & 0x3c) >> 2);
80 c3[2] = ((c4[2] & 0x3) << 6) + c4[3];
81
82 for(i = 0; i < 3; i++)
83 *out++ = c3[i];
84 i = 0;
85 }
86 }
87
88 if(i)
89 {
90 c3[0] = ( c4[0] << 2) + ((c4[1] & 0x30) >> 4);
91 c3[1] = ((c4[1] & 0xf) << 4) + ((c4[2] & 0x3c) >> 2);
92 c3[2] = ((c4[2] & 0x3) << 6) + c4[3];
93
94 for(j = 0; j < i - 1; j++)
95 *out++ = c3[j];
96 }
97
98 return {out - static_cast<char*>(dest),
99 in - reinterpret_cast<unsigned char const*>(src)};
100 }
101
102 } // base64
103
104 namespace {
105
106 bool
107 validate( string_view s )
108 {
109 // Parse with the null parser and return false on error
110 null_parser p;
111 error_code ec;
112 p.write( s.data(), s.size(), ec );
113 if( ec )
114 return false;
115
116 // The string is valid JSON.
117 return true;
118 }
119
120 parse_options
121 make_options(
122 bool comments,
123 bool commas,
124 bool utf8)
125 {
126 parse_options opt;
127 opt.allow_comments = comments;
128 opt.allow_trailing_commas = commas;
129 opt.allow_invalid_utf8 = utf8;
130 return opt;
131 }
132
133 } // (anon)
134
135 class basic_parser_test
136 {
137 public:
138 ::test_suite::log_type log;
139
140 void
141 grind_one(
142 string_view s,
143 bool good,
144 parse_options po)
145 {
146 error_code ec;
147 fail_parser p(po);
148 p.write(false,
149 s.data(), s.size(), ec);
150 BOOST_TEST((good && !ec) ||
151 (! good && ec));
152 }
153
154 void
155 grind_one(
156 string_view s,
157 bool good,
158 const std::vector<parse_options>& configs)
159 {
160 for (const parse_options& po : configs)
161 grind_one(s, good, po);
162 }
163
164 void
165 grind(
166 string_view s,
167 bool good,
168 parse_options po)
169 {
170 grind_one(s, good, po);
171
172 // split/errors matrix
173 if(! s.empty())
174 {
175 for(std::size_t i = 1;
176 i < s.size(); ++i)
177 {
178 for(std::size_t j = 1;;++j)
179 {
180 error_code ec;
181 fail_parser p(j, po);
182 p.write(true, s.data(), i, ec);
183 if(ec == error::test_failure)
184 continue;
185 if(! ec)
186 {
187 p.write(false, s.data() + i,
188 s.size() - i, ec);
189 if(ec == error::test_failure)
190 continue;
191 }
192 BOOST_TEST((good && !ec) || (
193 ! good && ec));
194 break;
195 }
196 }
197 }
198
199 // split/exceptions matrix
200 if(! s.empty())
201 {
202 for(std::size_t i = 1;
203 i < s.size(); ++i)
204 {
205 for(std::size_t j = 1;;++j)
206 {
207 error_code ec;
208 throw_parser p(j, po);
209 try
210 {
211 p.write(
212 true, s.data(), i, ec);
213 if(! ec)
214 p.write(
215 false, s.data() + i,
216 s.size() - i, ec);
217 BOOST_TEST((good && !ec) || (
218 ! good && ec));
219 break;
220 }
221 catch(test_exception const&)
222 {
223 continue;
224 }
225 catch(std::exception const& e)
226 {
227 BOOST_TEST_FAIL();
228 log << " " <<
229 e.what() << std::endl;
230 }
231 }
232 }
233 }
234 }
235
236 void
237 grind(
238 string_view s,
239 bool good,
240 const std::vector<parse_options>& configs)
241 {
242 for (const parse_options& po : configs)
243 grind(s, good, po);
244 }
245
246 void
247 bad(string_view s)
248 {
249 grind(s, false, parse_options());
250 }
251
252 void
253 good(string_view s)
254 {
255 grind(s, true, parse_options());
256 }
257
258 void
259 bad(
260 string_view s,
261 const parse_options& po)
262 {
263 grind(s, false, po);
264 }
265
266 void
267 good(
268 string_view s,
269 const parse_options& po)
270 {
271 grind(s, true, po);
272 }
273
274 void
275 bad_one(
276 string_view s,
277 const parse_options& po)
278 {
279 grind_one(s, false, po);
280 }
281
282 void
283 good_one(
284 string_view s,
285 const parse_options& po)
286 {
287 grind_one(s, true, po);
288 }
289
290 void
291 bad_one(string_view s)
292 {
293 grind_one(s, false, parse_options());
294 }
295
296 void
297 good_one(string_view s)
298 {
299 grind_one(s, true, parse_options());
300 }
301
302 //------------------------------------------------------
303
304 void
305 testNull()
306 {
307 good("null");
308 good(" null");
309 good("null ");
310 good("\tnull");
311 good("null\t");
312 good("\r\n\t null\r\n\t ");
313
314 bad ("n ");
315 bad ("nu ");
316 bad ("nul ");
317 bad ("n--- ");
318 bad ("nu-- ");
319 bad ("nul- ");
320
321 bad ("NULL");
322 bad ("Null");
323 bad ("nulls");
324 }
325
326 void
327 testBoolean()
328 {
329 good("true");
330 good(" true");
331 good("true ");
332 good("\ttrue");
333 good("true\t");
334 good("\r\n\t true\r\n\t ");
335
336 bad ("t ");
337 bad ("tr ");
338 bad ("tru ");
339 bad ("t--- ");
340 bad ("tr-- ");
341 bad ("tru- ");
342 bad ("TRUE");
343 bad ("True");
344 bad ("truer");
345
346 good("false");
347 good(" false");
348 good("false ");
349 good("\tfalse");
350 good("false\t");
351 good("\r\n\t false\r\n\t ");
352
353 bad ("f ");
354 bad ("fa ");
355 bad ("fal ");
356 bad ("fals ");
357 bad ("f---- ");
358 bad ("fa--- ");
359 bad ("fal-- ");
360 bad ("fals- ");
361 bad ("FALSE");
362 bad ("False");
363 bad ("falser");
364 }
365
366 void
367 testString()
368 {
369 good(R"jv( "x" )jv");
370 good(R"jv( "xy" )jv");
371 good(R"jv( "x y" )jv");
372
373 // escapes
374 good(R"jv(" \" ")jv");
375 good(R"jv(" \\ ")jv");
376 good(R"jv(" \/ ")jv");
377 good(R"jv(" \b ")jv");
378 good(R"jv(" \f ")jv");
379 good(R"jv(" \n ")jv");
380 good(R"jv(" \r ")jv");
381 good(R"jv(" \t ")jv");
382
383 // utf-16 escapes
384 good(R"jv( " \u0000 " )jv");
385 good(R"jv( " \ud7ff " )jv");
386 good(R"jv( " \ue000 " )jv");
387 good(R"jv( " \uffff " )jv");
388 good(R"jv( " \ud800\udc00 " )jv");
389 good(R"jv( " \udbff\udfff " )jv");
390 good(R"jv( " \n\u0000 " )jv");
391
392 // escape in key
393 good(R"jv( {" \n":null} )jv");
394
395 // incomplete
396 bad ("\"");
397
398 // illegal control character
399 bad ({ "\"" "\x00" "\"", 3 });
400 bad ("\"" "\x1f" "\"");
401 bad ("\"" "\\n" "\x1f" "\"");
402
403 // incomplete escape
404 bad (R"jv( "\" )jv");
405
406 // invalid escape
407 bad (R"jv( "\z" )jv");
408
409 // utf-16 escape, fast path,
410 // invalid surrogate
411 bad (R"jv( " \u---- " )jv");
412 bad (R"jv( " \ud--- " )jv");
413 bad (R"jv( " \ud8-- " )jv");
414 bad (R"jv( " \ud80- " )jv");
415 // invalid low surrogate
416 bad (R"jv( " \ud800------ " )jv");
417 bad (R"jv( " \ud800\----- " )jv");
418 bad (R"jv( " \ud800\u---- " )jv");
419 bad (R"jv( " \ud800\ud--- " )jv");
420 bad (R"jv( " \ud800\udc-- " )jv");
421 bad (R"jv( " \ud800\udc0- " )jv");
422 // illegal leading surrogate
423 bad (R"jv( " \udc00 " )jv");
424 bad (R"jv( " \udfff " )jv");
425 // illegal trailing surrogate
426 bad (R"jv( " \ud800\udbff " )jv");
427 bad (R"jv( " \ud800\ue000 " )jv");
428 }
429
430 void
431 testNumber()
432 {
433 good("0");
434 good("0 ");
435 good("0e0 ");
436 good("0E0 ");
437 good("0e00 ");
438 good("0E01 ");
439 good("0e+0 ");
440 good("0e-0 ");
441 good("0.0 ");
442 good("0.01 ");
443 good("0.0e0 ");
444 good("0.01e+0 ");
445 good("0.02E-0 ");
446 good("1 ");
447 good("12 ");
448 good("1e0 ");
449 good("1E0 ");
450 good("1e00 ");
451 good("1E01 ");
452 good("1e+0 ");
453 good("1e-0 ");
454 good("1.0 ");
455 good("1.01 ");
456 good("1.0e0 ");
457 good("1.01e+0 ");
458 good("1.02E-0 ");
459 good("1.0");
460
461 good("-0 ");
462 good("-0e0 ");
463 good("-0E0 ");
464 good("-0e00 ");
465 good("-0E01 ");
466 good("-0e+0 ");
467 good("-0e-0 ");
468 good("-0.0 ");
469 good("-0.01 ");
470 good("-0.0e0 ");
471 good("-0.01e+0 ");
472 good("-0.02E-0 ");
473 good("-1 ");
474 good("-12 ");
475 good("-1 ");
476 good("-1e0 ");
477 good("-1E0 ");
478 good("-1e00 ");
479 good("-1E01 ");
480 good("-1e+0 ");
481 good("-1e-0 ");
482 good("-1.0 ");
483 good("-1.01 ");
484 good("-1.0e0 ");
485 good("-1.01e+0 ");
486 good("-1.02E-0 ");
487 good("-1.0");
488
489 good("1.1e309 ");
490 good("9223372036854775807 ");
491 good("-9223372036854775807 ");
492 good("18446744073709551615 ");
493 good("-18446744073709551615 ");
494
495 good("1234567890123456");
496 good("-1234567890123456");
497 good("10000000000000000000000000");
498
499 good("0.900719925474099178 ");
500
501 // non-significant digits
502 good("1000000000000000000000000 ");
503 good("1000000000000000000000000e1 ");
504 good("1000000000000000000000000.0 ");
505 good("1000000000000000000000000.00 ");
506 good("1000000000000000000000000.000000000001");
507 good("1000000000000000000000000.0e1 ");
508 good("1000000000000000000000000.0 ");
509
510 good("1000000000.1000000000 ");
511
512 bad("");
513 bad("- ");
514 bad("00 ");
515 bad("01 ");
516 bad("00. ");
517 bad("00.0 ");
518 bad("-00 ");
519 bad("-01 ");
520 bad("-00. ");
521 bad("-00.0 ");
522 bad("1a ");
523 bad("-a ");
524 bad(". ");
525 bad("1. ");
526 bad("1+ ");
527 bad("0.0+ ");
528 bad("0.0e+ ");
529 bad("0.0e- ");
530 bad("0.0e0- ");
531 bad("0.0e ");
532 bad("1eX ");
533 bad("1000000000000000000000000.e ");
534 bad("0.");
535 bad("0.0e+");
536 bad("0.0e2147483648");
537 }
538
539 void
540 testArray()
541 {
542 good("[]");
543 good("[ ]");
544 good("[ \t ]");
545 good("[ \"\" ]");
546 good("[ \" \" ]");
547 good("[ \"x\" ]");
548 good("[ \"x\", \"y\" ]");
549 good("[1,2,3]");
550 good(" [1,2,3]");
551 good("[1,2,3] ");
552 good(" [1,2,3] ");
553 good("[1,2,3]");
554 good("[ 1,2,3]");
555 good("[1 ,2,3]");
556 good("[1, 2,3]");
557 good("[1,2 ,3]");
558 good("[1,2, 3]");
559 good("[1,2,3 ]");
560 good(" [ 1 , 2 \t\n , \n3]");
561
562 bad ("[");
563 bad (" [");
564 bad (" []]");
565 bad ("[{]");
566 bad (R"jv( [ null ; 1 ] )jv");
567 }
568
569 void
570 testObject()
571 {
572 good("{}");
573 good("{ }");
574 good("{ \t }");
575 good("{\"x\":null}");
576 good("{ \"x\":null}");
577 good("{\"x\" :null}");
578 good("{\"x\": null}");
579 good("{\"x\":null }");
580 good("{ \"x\" : null }");
581 good("{ \"x\" : {} }");
582 good("{ \"x\" : [] }");
583 good("{ \"x\" : { \"y\" : null } }");
584 good("{ \"x\" : [{}] }");
585 good("{\"x\\ny\\u0022\":null}");
586 good("{ \"x\":1, \"y\":null}");
587 good("{\"x\":1,\"y\":2,\"z\":3}");
588 good(" {\"x\":1,\"y\":2,\"z\":3}");
589 good("{\"x\":1,\"y\":2,\"z\":3} ");
590 good(" {\"x\":1,\"y\":2,\"z\":3} ");
591 good("{ \"x\":1,\"y\":2,\"z\":3}");
592 good("{\"x\" :1,\"y\":2,\"z\":3}");
593 good("{\"x\":1 ,\"y\":2,\"z\":3}");
594 good("{\"x\":1,\"y\" :2,\"z\":3}");
595 good("{\"x\":1,\"y\": 2,\"z\":3}");
596 good("{\"x\":1,\"y\":2 ,\"z\":3}");
597 good("{\"x\":1,\"y\":2, \"z\":3}");
598 good("{\"x\":1,\"y\":2, \"z\" :3}");
599 good("{\"x\":1,\"y\":2, \"z\": 3}");
600 good("{\"x\":1,\"y\":2, \"z\":3 }");
601 good(" \t { \"x\" \n : 1, \"y\" :2, \"z\" : 3} \n");
602
603 good("[{\"x\":[{\"y\":null}]}]");
604
605 bad ("{");
606 bad (" {");
607 bad (" {}}");
608 bad ("{{}}");
609 bad ("{[]}");
610
611 bad (R"jv( {"x";null} )jv");
612 bad (R"jv( {"x":null . "y":0} )jv");
613 }
614
615 void
616 testParser()
617 {
618 auto const check =
619 [this]( string_view s,
620 bool done)
621 {
622 fail_parser p;
623 error_code ec;
624 p.write_some(
625 true,
626 s.data(), s.size(),
627 ec);
628 if(! BOOST_TEST(! ec))
629 {
630 log << " failed to parse: " << s << '\n';
631 return;
632 }
633 BOOST_TEST(done == p.done());
634 };
635
636 // done()
637
638 check("{}", true);
639 check("{} ", true);
640 check("{}x", true);
641 check("{} x", true);
642
643 check("[]", true);
644 check("[] ", true);
645 check("[]x", true);
646 check("[] x", true);
647
648 check("\"a\"", true);
649 check("\"a\" ", true);
650 check("\"a\"x", true);
651 check("\"a\" x", true);
652
653 check("0", false);
654 check("0 ", true);
655 check("0x", true);
656 check("0 x", true);
657 check("0.", false);
658 check("0.0", false);
659 check("0.0 ", true);
660 check("0.0 x", true);
661
662 check("true", true);
663 check("true ", true);
664 check("truex", true);
665 check("true x", true);
666
667 check("false", true);
668 check("false ", true);
669 check("falsex", true);
670 check("false x", true);
671
672 check("null", true);
673 check("null ", true);
674 check("nullx", true);
675 check("null x", true);
676
677 // flush
678 {
679 {
680 for(auto esc :
681 { "\\\"", "\\\\", "\\/", "\\b",
682 "\\f", "\\n", "\\r", "\\t", "\\u0000"
683 })
684 {
685 std::string const big =
686 "\\\"" + std::string(
687 BOOST_JSON_STACK_BUFFER_SIZE-4, '*') + esc;
688 std::string const s =
689 "{\"" + big + "\":\"" + big + "\"}";
690 good_one(s);
691 }
692 }
693 {
694 std::string big;
695 big = "\\\"" +
696 std::string(
697 BOOST_JSON_STACK_BUFFER_SIZE+ 1, '*');
698 std::string s;
699 s = "{\"" + big + "\":\"" + big + "\"}";
700 good_one(s);
701 }
702 }
703
704 // no input
705 {
706 error_code ec;
707 fail_parser p;
708 p.write(false, nullptr, 0, ec);
709 BOOST_TEST(ec);
710 }
711 }
712
713 void
714 testMembers()
715 {
716 fail_parser p;
717 std::size_t n;
718 error_code ec;
719 n = p.write_some(true, "null", 4, ec );
720 if(BOOST_TEST(! ec))
721 {
722 BOOST_TEST(n == 4);
723 BOOST_TEST(p.done());
724 n = p.write_some(false, " \t42", 4, ec);
725 BOOST_TEST(n == 2);
726 BOOST_TEST(! ec);
727 }
728 p.reset();
729 n = p.write_some(false, "[1,2,3]", 7, ec);
730 if(BOOST_TEST(! ec))
731 {
732 BOOST_TEST(n == 7);
733 BOOST_TEST(p.done());
734 }
735 }
736
737 void
738 testParseVectors()
739 {
740 std::vector<parse_options> all_configs =
741 {
742 make_options(false, false, true),
743 make_options(true, false, true),
744 make_options(false, true, true),
745 make_options(true, true, true),
746 make_options(false, false, false),
747 make_options(true, false, false),
748 make_options(false, true, false),
749 make_options(true, true, false)
750 };
751 parse_vectors pv;
752 for(auto const& v : pv)
753 {
754 // skip these , because basic_parser
755 // doesn't have a max_depth setting.
756 if( v.name == "structure_100000_opening_arrays" ||
757 v.name == "structure_open_array_object")
758 {
759 continue;
760 }
761 for (const parse_options& po : all_configs)
762 {
763 if(v.result == 'i')
764 {
765 error_code ec;
766 fail_parser p(po);
767 p.write(
768 false,
769 v.text.data(),
770 v.text.size(),
771 ec);
772 if(! ec)
773 good_one(v.text, po);
774 else
775 bad_one(v.text, po);
776 }
777 else if(v.result == 'y')
778 good_one(v.text, po);
779 else
780 bad_one(v.text, po);
781 }
782 }
783 }
784
785 // https://github.com/boostorg/json/issues/13
786 void
787 testIssue13()
788 {
789 validate("\"~QQ36644632 {n");
790 }
791
792 void
793 testIssue20()
794 {
795 string_view s =
796 "WyL//34zOVx1ZDg0ZFx1ZGM4M2RcdWQ4M2RcdWRlM2M4dWRlMTlcdWQ4M2RcdWRlMzlkZWUzOVx1"
797 "ZDg0ZFx1ZGM4M2RcdWQ4M2RcdWRlMzlcXHVkY2M4M1x1ZDg5ZFx1ZGUzOVx1ZDgzZFx1ZGUzOWRb"
798 "IGZhbHNlLDMzMzMzMzMzMzMzMzMzMzMzNDMzMzMzMTY1MzczNzMwLDMzMzMzMzMzMzMzMzMzMzMz"
799 "MzM3ODAsMzMzMzMzMzMzMzM0MzMzMzMxNjUzNzM3MzAsMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMz"
800 "MzM3ODAsMzMzMzMzMzMzMzMzMzQzMzMzMzE2NTM3MzczMCwzMzMzMzMzMzMzMzMzMzMzMzMzNzgw"
801 "LDMzMzMzMzM4MzU1MzMwNzQ3NDYwLDMzMTY2NTAwMDAzMzMzMzMwNzQ3MzMzMzMzMzc3OSwzMzMz"
802 "MzMzMzMzMzMzMzMzNDMzMzMzMzMwNzQ3NDYwLDMzMzMzMzMzMzMzMzMzMzMzMzMzNzgwLDMzMzMz"
803 "MzMzMzMzMzMzMzA4ODM1NTMzMDc0Mzc4MCwzMzMzMzMzMzMzMzMzMzMwODgzNTUzMzA3NDc0NjAs"
804 "MzMzMzMzMzMxNjY1MDAwMDMzMzMzNDc0NjAsMzMzMzMzMzMzMzMzMzMzMzMzMzc4MCwzMzMzMzMz"
805 "MzMzMzM3MzMzMzE2NjUwMDAwMzMzMzMzMDc0NzMzMzMzMzM3NzksMzMzMzMzMzMzMzMzMzMzMzQz"
806 "MzMzMzMwNzQ3NDYwLDMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzc4MCwzMzMzMzMzMzMzNzgw"
807 "LDMzMzMzMzMzMzMzMzA4ODM1NTMzMDc0NzQ2MCwzMzE2NjUwMDAwMzMzMzMzMDc0NzMzMzMzMzM3"
808 "NzksMzMzMzMzMzMzMzMzMzMzMzQzMzMzMzMwNzQ3NDYwLDMzMzMzMzMzMzMzMzMzMzMzMzMzNzgw"
809 "LDMzMzMzMzMzMzMzMzMzMzA4ODM1NTMzMDc0Mzc4MCwzMzMzMzMzMzMzMzMzMzMzMzMwODgzNTUz"
810 "MzA3NDM3ODAsMzMzMzMzMzMzMzMzMzMzMDg4MzU1MzMwNzQ3NDYwLDMzMzMzMzMzMzMzMDczMzM3"
811 "NDc0NjAsMzMzMzMzMzMzMzMzMzMzMzMzNzgwLDMzMzMzMzMzMzMzMzA4ODM1NTMzMDc0NzQ2MCwz"
812 "MzE2NjUwMDAwMzMzMzMzMDc0NzMzMzMzMzM3NzksMzMzMzMzMzMzMzMzMzMzMzQzMzMzMzMzMDc0"
813 "NzQ2MCwzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzM3ODAsMzMzMzMzMzMzMzMzMzMzMDg4"
814 "MzU1MzMwNzQzNzgwLDMzMzMzMzMzMzMzMzMzMzA4ODM1NTMzMDc0NzQ2MCwzMzMzMzMzMzMzMzMz"
815 "MzMzMzM0MjQ3LDMzMzMzMzMzMzMzMzMzMzQzMzMzMzMzMzMzMzMzMzM3MzMzMzQzMzMzMzMzMDc0"
816 "NzQ2MCwzMzMzMzMzMzMzMzMzMzMzMzMzNzgwLDMzMzMzMzMzMzMzMzA4ODM1NTMzMDc0NzQ2MCwz"
817 "MzE2NjUwMDAwMzMzMzMzMDc0NzMzMzMzMzM3NzksMzMzMzMzMzMzMzMzMzMzMzQzMzMzMzMwNzQ3"
818 "NDYwLDMzMzMzMzMzMzMzMzMzMzMzMzMzNzgwLDMzMzMzMzMzMzMzMzMzMzA4ODM1NTMzMDc0Mzc4"
819 "MCwzMzMzMzMzMzMzMzMzMzMwODgzNTUzMzA3NDc0NjAsMzMzMzMzMzMzLDMzMzMzMzMzMzMzMzMz"
820 "MzMzMzM3ODAsMzMzMzMzMzMzMzc4MCwzMzMzMzMzMzMzMzMwODgzNTUzMzA3NDc0NjAsMzMxNjY1"
821 "MDAwMDMzMzMzMzA3NDczMzMzMzMzNzc5LDMzMzMzMzMzMzM3ODAsMzMzMzMzMzgzNTUzMzA3NDc0"
822 "NjAsMzMxNjY1MDAwMDMzMzMzMzA3NDczMzMzMzMzNzc5LDMzMzMzMzMzMzMzMzMzMzM0MzMzMzMz"
823 "MzA3NDc0NjAsMzMzMzMzMzMzMzMzMzMzMzMzMzM3ODAsMzMzMzMzMzMzMzMzMzMzMDg4MzU1MzMw"
824 "NzQzNzgwLDMzMzMzMzMzMzMzMzMzMzA4ODM1NTMzMDc0NzQ2MCwzMzMzMzMzMzE2NjUwMDAwMzMz"
825 "MzM0NzQ2MCwzMzMzMzMzMzMzMzMzMzMzMzMzNzgwLDMzMzMzMzMzMzMzMzM0MzMzMzMxNjUzNzM3"
826 "MzAsMzMzMzMzMzMzMzMzMzMzMzMzMzc4MCwzMzMzMzMzODM1NTMzMDc0NzQ2MCwzMzE2NjUwMDAw"
827 "MzMzMzMzMDc0NzMzMzMzMzM3NzksMzMzMzMzMzMzMzMzMzMzMzQzMzMzMzMzMDc0NzQ2MCwzMzMz"
828 "MzMzMzMzMzMzMzMzMzMzMzc4MCwzMzMzMzMzMzMzMzMzMzMwODgzNTUzMzA3NDM3ODAsMzMzMzMz"
829 "MzMzMzMzMzMzMDg4MzU1MzMwNzQ3NDYwLDMzMzMzMzMzMTY2NTAwMDAzMzMzMzQ3NDYwLDMzMzMz"
830 "MzMzMzMzMzMzMzMzMzM3ODAsMzMzMzMzMzMzMzMzNzMzMzM0MzMzMzMzMzA3NDc0NjAsMzMzMzMz"
831 "MzMzMzMzMzMzMzMzMzc4MCwzMzMzMzMzMzMzMzMwODgzNTUzMzA3NDc0NjAsMzMxNjY1MDAwMDMz"
832 "MzMzMzA3NDczMzMzMzMzNzc5LDMzMzMzMzMzMzMzMzMzMzM0MzMzMzNcdWQ4N2RcdWRlZGV1ZGM4"
833 "ZGUzOVx1ZDg0ZFx1ZGM4M2RcdWQ4OGRcdWRlMzlcdWQ4OWRcdWRlMjM5MzMzZWUzOVxk";
834 auto const len = base64::decoded_size(s.size());
835 std::unique_ptr<char[]> p(new char[len]);
836 base64::decode(
837 p.get(), s.data(), s.size());
838 string_view const js(p.get(), len);
839 BOOST_TEST(! validate(js));
840 }
841
842 void
843 testIssue113()
844 {
845 string_view s =
846 "\"\\r\\n section id='description'>\\r\\nAll mbers form the uncountable set "
847 "\\u211D. Among its subsets, relatively simple are the convex sets, each expressed "
848 "as a range between two real numbers <i>a</i> and <i>b</i> where <i>a</i> \\u2264 <i>"
849 "b</i>. There are actually four cases for the meaning of \\\"between\\\", depending "
850 "on open or closed boundary:\\r\\n\\r\\n<ul>\\r\\n <li>[<i>a</i>, <i>b</i>]: {<i>"
851 "x</i> | <i>a</i> \\u2264 <i>x</i> and <i>x</i> \\u2264 <i>b</i> }</li>\\r\\n <li>"
852 "(<i>a</i>, <i>b</i>): {<i>x</i> | <i>a</i> < <i>x</i> and <i>x</i> < <i>b</i> }"
853 "</li>\\r\\n <li>[<i>a</i>, <i>b</i>): {<i>x</i> | <i>a</i> \\u2264 <i>x</i> and "
854 "<i>x</i> < <i>b</i> }</li>\\r\\n <li>(<i>a</i>, <i>b</i>]: {<i>x</i> | <i>a</i> "
855 "< <i>x</i> and <i>x</i> \\u2264 <i>b</i> }</li>\\r\\n</ul>\\r\\n\\r\\nNote that "
856 "if <i>a</i> = <i>b</i>, of the four only [<i>a</i>, <i>a</i>] would be non-empty."
857 "\\r\\n\\r\\n<strong>Task</strong>\\r\\n\\r\\n<ul>\\r\\n <li>Devise a way to "
858 "represent any set of real numbers, for the definition of \\\"any\\\" in the "
859 "implementation notes below.</li>\\r\\n <li>Provide methods for these common "
860 "set operations (<i>x</i> is a real number; <i>A</i> and <i>B</i> are sets):</li>"
861 "\\r\\n <ul>\\r\\n <li>\\r\\n <i>x</i> \\u2208 <i>A</i>: determine if <i>"
862 "x</i> is an element of <i>A</i><br>\\r\\n example: 1 is in [1, 2), while 2, "
863 "3, ... are not.\\r\\n </li>\\r\\n <li>\\r\\n <i>A</i> \\u222A <i>B</i>: "
864 "union of <i>A</i> and <i>B</i>, i.e. {<i>x</i> | <i>x</i> \\u2208 <i>A</i> or <i>x"
865 "</i> \\u2208 <i>B</i>}<br>\\r\\n example: [0, 2) \\u222A (1, 3) = [0, 3); "
866 "[0, 1) \\u222A (2, 3] = well, [0, 1) \\u222A (2, 3]\\r\\n </li>\\r\\n <li>"
867 "\\r\\n <i>A</i> \\u2229 <i>B</i>: intersection of <i>A</i> and <i>B</i>, i.e. "
868 "{<i>x</i> | <i>x</i> \\u2208 <i>A</i> and <i>x</i> \\u2208 <i>B</i>}<br>\\r\\n "
869 "example: [0, 2) \\u2229 (1, 3) = (1, 2); [0, 1) \\u2229 (2, 3] = empty set\\r\\n "
870 "</li>\\r\\n <li>\\r\\n <i>A</i> - <i>B</i>: difference between <i>A</i> and "
871 "<i>B</i>, also written as <i>A</i> \\\\ <i>B</i>, i.e. {<i>x</i> | <i>x</i> \\u2208 "
872 "<i>A</i> and <i>x</i> \\u2209 <i>B</i>}<br>\\r\\n example: [0, 2) \\u2212 (1, "
873 "3) = [0, 1]\\r\\n </li>\\r\\n </ul>\\r\\n</ul>\\r\\n</section>\\r\\n\"\n";
874 good_one(s);
875 }
876
877 class comment_parser
878 {
879 struct handler
880 {
881 constexpr static std::size_t max_object_size = std::size_t(-1);
882 constexpr static std::size_t max_array_size = std::size_t(-1);
883 constexpr static std::size_t max_key_size = std::size_t(-1);
884 constexpr static std::size_t max_string_size = std::size_t(-1);
885
886 std::string captured = "";
887 bool on_document_begin( error_code& ) { return true; }
888 bool on_document_end( error_code& ) { return true; }
889 bool on_object_begin( error_code& ) { return true; }
890 bool on_object_end( std::size_t, error_code& ) { return true; }
891 bool on_array_begin( error_code& ) { return true; }
892 bool on_array_end( std::size_t, error_code& ) { return true; }
893 bool on_key_part( string_view, std::size_t, error_code& ) { return true; }
894 bool on_key( string_view, std::size_t, error_code& ) { return true; }
895 bool on_string_part( string_view, std::size_t, error_code& ) { return true; }
896 bool on_string( string_view, std::size_t, error_code& ) { return true; }
897 bool on_number_part( string_view, error_code&) { return true; }
898 bool on_int64( std::int64_t, string_view, error_code& ) { return true; }
899 bool on_uint64( std::uint64_t, string_view, error_code& ) { return true; }
900 bool on_double( double, string_view, error_code& ) { return true; }
901 bool on_bool( bool, error_code& ) { return true; }
902 bool on_null( error_code& ) { return true; }
903 bool on_comment_part( string_view s, error_code& )
904 {
905 captured.append(s.data(), s.size());
906 return true;
907 }
908 bool on_comment( string_view s, error_code& )
909 {
910 captured.append(s.data(), s.size());
911 return true;
912 }
913 };
914
915 basic_parser<handler> p_;
916
917 public:
918 comment_parser()
919 : p_(make_options(true, false, false))
920 {
921 }
922
923 std::size_t
924 write(
925 char const* data,
926 std::size_t size,
927 error_code& ec)
928 {
929 auto const n = p_.write_some(
930 false, data, size, ec);
931 if(! ec && n < size)
932 ec = error::extra_data;
933 return n;
934 }
935
936 string_view
937 captured() const noexcept
938 {
939 return p_.handler().captured;
940 }
941 };
942
943 void
944 testComments()
945 {
946 parse_options disabled;
947 parse_options enabled;
948 enabled.allow_comments = true;
949
950 const auto replace_and_test =
951 [&](string_view s)
952 {
953 static std::vector<string_view> comments =
954 {
955 "//\n",
956 "// \n",
957 "//aaaa\n",
958 "// aaaa\n",
959 "// /* \n",
960 "// /**/ \n",
961 "/**/",
962 "/*//*/",
963 "/*/*/",
964 "/******/",
965 "/*** ***/",
966 "/**aaaa***/",
967 "/*** aaaa***/"
968 };
969
970 std::string formatted = "";
971 std::string just_comments = "";
972 std::size_t guess = std::count(
973 s.begin(), s.end(), '@') * 12;
974 formatted.reserve(guess + s.size());
975 just_comments.reserve(guess);
976 std::size_t n = 0;
977 for (char c : s)
978 {
979 if (c == '@')
980 {
981 string_view com =
982 comments[((formatted.size() + n) % s.size()) % comments.size()];
983 formatted.append(com.data(), n = com.size());
984 just_comments.append(com.data(), com.size());
985 continue;
986 }
987 formatted += c;
988 }
989 bad(formatted, disabled);
990 good(formatted, enabled);
991
992 {
993 // test the handler
994 comment_parser p;
995 error_code ec;
996 p.write( formatted.data(), formatted.size(), ec );
997 BOOST_TEST(! ec);
998 BOOST_TEST(p.captured() == just_comments);
999 }
1000 };
1001
1002 replace_and_test("@1");
1003 replace_and_test("1@");
1004 replace_and_test("@1@");
1005 replace_and_test("[@1]");
1006 replace_and_test("[1@]");
1007 replace_and_test("[1,2@]");
1008 replace_and_test("[1,@2]");
1009 replace_and_test("[1@,2]");
1010 replace_and_test("@[@1@,@2@]@");
1011 replace_and_test("{@\"a\":1}");
1012 replace_and_test("{\"a\"@:1}");
1013 replace_and_test("{\"a\":1@}");
1014 replace_and_test("{\"a\":1@,\"b\":2}");
1015 replace_and_test("{\"a\":1,@\"b\":2}");
1016 replace_and_test("@{@\"a\"@:@1@,@\"b\"@:@2@}");
1017
1018 // no following token
1019 bad("1/", enabled);
1020 // bad second token
1021 bad("1/x", enabled);
1022 // no comment close
1023 bad("1/*", enabled);
1024 bad("1/**", enabled);
1025 bad("[1 //, 2]", enabled);
1026
1027 // just comment
1028 bad("//\n", enabled);
1029 bad("//", enabled);
1030 bad("/**/", enabled);
1031
1032 // no newline at EOF
1033 good("1//", enabled);
1034 }
1035
1036 void
1037 testAllowTrailing()
1038 {
1039 parse_options disabled;
1040 parse_options enabled;
1041 enabled.allow_trailing_commas = true;
1042
1043 bad("[1,]", disabled);
1044 good("[1,]", enabled);
1045
1046 bad("[1,[],]", disabled);
1047 good("[1,[],]", enabled);
1048
1049 bad("[1,{},]", disabled);
1050 good("[1,{},]", enabled);
1051
1052 bad("[1,{\"a\":1,},]", disabled);
1053 good("[1,{\"a\":1,},]", enabled);
1054
1055 bad("{\"a\":1,}", disabled);
1056 good("{\"a\":1,}", enabled);
1057
1058 bad("{\"a\":[1,],}", disabled);
1059 good("{\"a\":[1,],}", enabled);
1060
1061 bad("{\"a\":[],}", disabled);
1062 good("{\"a\":[],}", enabled);
1063
1064 bad("{\"a\":[{}, [1,]],}", disabled);
1065 good("{\"a\":[{}, [1,]],}", enabled);
1066
1067 bad("[[[[[[[],],],],],],]", disabled);
1068 good("[[[[[[[],],],],],],]", enabled);
1069
1070 bad("{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{},},},},},},}", disabled);
1071 good("{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{},},},},},},}", enabled);
1072 }
1073
1074 class utf8_parser
1075 {
1076 struct handler
1077 {
1078 constexpr static std::size_t max_object_size = std::size_t(-1);
1079 constexpr static std::size_t max_array_size = std::size_t(-1);
1080 constexpr static std::size_t max_key_size = std::size_t(-1);
1081 constexpr static std::size_t max_string_size = std::size_t(-1);
1082
1083 std::string captured = "";
1084 bool on_document_begin( error_code& ) { return true; }
1085 bool on_document_end( error_code& ) { return true; }
1086 bool on_object_begin( error_code& ) { return true; }
1087 bool on_object_end( std::size_t, error_code& ) { return true; }
1088 bool on_array_begin( error_code& ) { return true; }
1089 bool on_array_end( std::size_t, error_code& ) { return true; }
1090 bool on_key_part( string_view, std::size_t, error_code& ) { return true; }
1091 bool on_key( string_view, std::size_t, error_code& ) { return true; }
1092 bool on_string_part( string_view sv, std::size_t, error_code& )
1093 {
1094 captured.append(sv.data(), sv.size());
1095 return true;
1096 }
1097 bool on_string( string_view sv, std::size_t, error_code& )
1098 {
1099 captured.append(sv.data(), sv.size());
1100 return true;
1101 }
1102 bool on_number_part( string_view, error_code&) { return true; }
1103 bool on_int64( std::int64_t, string_view, error_code& ) { return true; }
1104 bool on_uint64( std::uint64_t, string_view, error_code& ) { return true; }
1105 bool on_double( double, string_view, error_code& ) { return true; }
1106 bool on_bool( bool, error_code& ) { return true; }
1107 bool on_null( error_code& ) { return true; }
1108 bool on_comment_part( string_view, error_code& ) { return true; }
1109 bool on_comment( string_view, error_code& ) { return true; }
1110 };
1111
1112 basic_parser<handler> p_;
1113
1114 public:
1115 utf8_parser()
1116 : p_(parse_options())
1117 {
1118 }
1119
1120 std::size_t
1121 write(
1122 bool more,
1123 char const* data,
1124 std::size_t size,
1125 error_code& ec)
1126 {
1127 auto const n = p_.write_some(
1128 more, data, size, ec);
1129 if(! ec && n < size)
1130 ec = error::extra_data;
1131 return n;
1132 }
1133
1134 string_view
1135 captured() const noexcept
1136 {
1137 return p_.handler().captured;
1138 }
1139 };
1140
1141 void
1142 testUTF8Validation()
1143 {
1144 good("\"\xc2\x80----------\"");
1145 good("\"\xc2\xbf----------\"");
1146 good("\"\xdf\x80----------\"");
1147 good("\"\xdf\xbf----------\"");
1148
1149 good("\"\xcf\x90----------\"");
1150
1151 good("\"\xe0\xa0\x80----------\"");
1152 good("\"\xe0\xa0\xbf----------\"");
1153 good("\"\xe0\xbf\x80----------\"");
1154 good("\"\xe0\xbf\xbf----------\"");
1155
1156 good("\"\xe0\xb0\x90----------\"");
1157
1158 good("\"\xe1\x80\x80----------\"");
1159 good("\"\xe1\xbf\x80----------\"");
1160 good("\"\xec\x80\x80----------\"");
1161 good("\"\xec\xbf\x80----------\"");
1162 good("\"\xe1\x80\xbf----------\"");
1163 good("\"\xe1\xbf\xbf----------\"");
1164 good("\"\xec\x80\xbf----------\"");
1165 good("\"\xec\xbf\xbf----------\"");
1166
1167 good("\"\xe6\x90\x90----------\"");
1168
1169 good("\"\xed\x80\x80----------\"");
1170 good("\"\xed\x80\xbf----------\"");
1171 good("\"\xed\x9f\x80----------\"");
1172 good("\"\xed\x9f\xbf----------\"");
1173
1174 good("\"\xed\x90\x90----------\"");
1175
1176 good("\"\xee\x80\x80----------\"");
1177 good("\"\xee\xbf\x80----------\"");
1178 good("\"\xef\x80\x80----------\"");
1179 good("\"\xef\xbf\x80----------\"");
1180 good("\"\xee\x80\xbf----------\"");
1181 good("\"\xee\xbf\xbf----------\"");
1182 good("\"\xef\x80\xbf----------\"");
1183 good("\"\xef\xbf\xbf----------\"");
1184
1185 good("\"\xee\x90\x90----------\"");
1186 good("\"\xef\x90\x90----------\"");
1187
1188 good("\"\xf0\x90\x80\x80----------\"");
1189 good("\"\xf0\x90\xbf\x80----------\"");
1190 good("\"\xf0\x90\xbf\xbf----------\"");
1191 good("\"\xf0\x90\x80\xbf----------\"");
1192 good("\"\xf0\xbf\x80\x80----------\"");
1193 good("\"\xf0\xbf\xbf\x80----------\"");
1194 good("\"\xf0\xbf\xbf\xbf----------\"");
1195 good("\"\xf0\xbf\x80\xbf----------\"");
1196
1197 good("\"\xf0\xA0\x90\x90----------\"");
1198
1199 good("\"\xf4\x80\x80\x80----------\"");
1200 good("\"\xf4\x80\xbf\x80----------\"");
1201 good("\"\xf4\x80\xbf\xbf----------\"");
1202 good("\"\xf4\x80\x80\xbf----------\"");
1203 good("\"\xf4\x8f\x80\x80----------\"");
1204 good("\"\xf4\x8f\xbf\x80----------\"");
1205 good("\"\xf4\x8f\xbf\xbf----------\"");
1206 good("\"\xf4\x8f\x80\xbf----------\"");
1207
1208 good("\"\xf4\x88\x90\x90----------\"");
1209
1210 good("\"\xf1\x80\x80\x80----------\"");
1211 good("\"\xf1\x80\xbf\x80----------\"");
1212 good("\"\xf1\x80\xbf\xbf----------\"");
1213 good("\"\xf1\x80\x80\xbf----------\"");
1214 good("\"\xf1\xbf\x80\x80----------\"");
1215 good("\"\xf1\xbf\xbf\x80----------\"");
1216 good("\"\xf1\xbf\xbf\xbf----------\"");
1217 good("\"\xf1\xbf\x80\xbf----------\"");
1218 good("\"\xf3\x80\x80\x80----------\"");
1219 good("\"\xf3\x80\xbf\x80----------\"");
1220 good("\"\xf3\x80\xbf\xbf----------\"");
1221 good("\"\xf3\x80\x80\xbf----------\"");
1222 good("\"\xf3\xbf\x80\x80----------\"");
1223 good("\"\xf3\xbf\xbf\x80----------\"");
1224 good("\"\xf3\xbf\xbf\xbf----------\"");
1225 good("\"\xf3\xbf\x80\xbf----------\"");
1226
1227 good("\"\xf2\x90\x90\x90----------\"");
1228
1229 bad("\"\xc0\x80----------\"");
1230 bad("\"\xc2\xc0----------\"");
1231 bad("\"\xef\x80----------\"");
1232 bad("\"\xdf\x70----------\"");
1233
1234 bad("\"\xff\x90----------\"");
1235
1236 bad("\"\xe0\x9f\x80----------\"");
1237 bad("\"\xe0\xa0\xfe----------\"");
1238 bad("\"\xc0\xff\xff----------\"");
1239 bad("\"\xc0\xbf\x76----------\"");
1240
1241 bad("\"\xe0\xde\x90----------\"");
1242
1243 bad("\"\xe1\x80\x7f----------\"");
1244 bad("\"\xe1\x7f\x80----------\"");
1245 bad("\"\xec\xff\x80----------\"");
1246 bad("\"\xef\x7f\x80----------\"");
1247 bad("\"\xe1\x80\xff----------\"");
1248 bad("\"\xe1\xbf\x0f----------\"");
1249 bad("\"\xec\x01\xff----------\"");
1250 bad("\"\xec\xff\xff----------\"");
1251
1252 bad("\"\xe6\x60\x90----------\"");
1253
1254 bad("\"\xed\x7f\x80----------\"");
1255 bad("\"\xed\xa0\xbf----------\"");
1256 bad("\"\xed\xbf\x80----------\"");
1257 bad("\"\xed\x9f\x7f----------\"");
1258
1259 bad("\"\xed\xce\xbf----------\"");
1260
1261 bad("\"\xee\x7f\x80----------\"");
1262 bad("\"\xee\xcc\x80----------\"");
1263 bad("\"\xef\x80\xcc----------\"");
1264 bad("\"\xef\xbf\x0a----------\"");
1265 bad("\"\xee\x50\xbf----------\"");
1266 bad("\"\xee\xef\xbf----------\"");
1267 bad("\"\xef\xf0\xff----------\"");
1268 bad("\"\xef\xaa\xee----------\"");
1269
1270 bad("\"\xc0\x90\x90----------\"");
1271 bad("\"\xc1\x90\x90----------\"");
1272
1273 bad("\"\xff\x90\x80\x80----------\"");
1274 bad("\"\xfe\x90\xbf\x80----------\"");
1275 bad("\"\xfd\x90\xbf\xbf----------\"");
1276 bad("\"\xf0\xff\x80\xbf----------\"");
1277 bad("\"\xf0\xfe\x80\x80----------\"");
1278 bad("\"\xf0\xfd\xbf\x80----------\"");
1279 bad("\"\xf0\x90\x80\xff----------\"");
1280 bad("\"\xf0\x90\x5f\x80----------\"");
1281
1282 bad("\"\xf4\x70\x80\x80----------\"");
1283 bad("\"\xf4\x80\x70\x80----------\"");
1284 bad("\"\xf4\x80\xbf\x70----------\"");
1285 bad("\"\xf4\xce\x80\xbf----------\"");
1286 bad("\"\xf4\x8f\xce\x80----------\"");
1287 bad("\"\xf4\x8f\xbf\xce----------\"");
1288
1289 bad("\"\xf1\x7f\xbf\xbf----------\"");
1290 bad("\"\xf2\x80\x7f\xbf----------\"");
1291 bad("\"\xf3\x80\xbf\xce----------\"");
1292
1293 // utf8 after escape
1294 good("\"\\u0000 \xf3\xbf\x80\xbf\xf3\xbf\x80\xbf\"");
1295 good("\"\\ud7ff\xf4\x80\xbf\xbf \"");
1296 good("\"\\ue000 \xef\xbf\x80\"");
1297 good("\"\xef\xbf\x80 \\uffff \xef\xbf\x80\"");
1298 good("\"\xc2\x80\xc2\x80\xc2\x80\xc2\x80\xc2\x80\\ud800\\udc00 \"");
1299 good("\"\\udbff\\udfff \xe1\x80\xbf \\udbff\\udfff \xe1\x80\xbf\"");
1300 good("\"\\u0000\xe1\x80\xbf \"");
1301 bad("\"\\t\\t\xf4\x70\x80\x80----------\"");
1302 bad("\"\\n\xf4\x80\x70\x80----------\"");
1303 bad("\"\\n\xf4\x80\xbf\x70-\\n\xf4\x80\xbf\x70\"");
1304
1305 const auto check =
1306 [this](string_view expected)
1307 {
1308 good(expected);
1309 for (std::size_t write_size : {2, 4, 8})
1310 {
1311 utf8_parser p;
1312 for(std::size_t i = 0; i < expected.size(); i += write_size)
1313 {
1314 error_code ec;
1315 write_size = (std::min)(write_size, expected.size() - i);
1316 auto more = (i < expected.size() - write_size);
1317 auto written = p.write(more,
1318 expected.data() + i, write_size, ec);
1319 BOOST_TEST(written == write_size);
1320 BOOST_TEST(! ec);
1321 }
1322 BOOST_TEST(p.captured() ==
1323 expected.substr(1, expected.size() - 2));
1324 }
1325 };
1326
1327 check("\"\xd1\x82\"");
1328 check("\"\xd1\x82\xd0\xb5\xd1\x81\xd1\x82\"");
1329 check("\"\xc3\x0b1""and\xc3\xba\"");
1330 }
1331
1332 void
1333 testMaxDepth()
1334 {
1335 {
1336 string_view s = "[[[[[]]]]]";
1337 parse_options opt;
1338 opt.max_depth = 4;
1339 null_parser p(opt);
1340 error_code ec;
1341 p.write(s.data(), s.size(), ec);
1342 BOOST_TEST(ec == error::too_deep);
1343 }
1344 {
1345 string_view s = "[[[[]]], [[[[]]]]]";
1346 parse_options opt;
1347 opt.max_depth = 4;
1348 null_parser p(opt);
1349 error_code ec;
1350 p.write(s.data(), s.size(), ec);
1351 BOOST_TEST(ec == error::too_deep);
1352 }
1353 {
1354 string_view s =
1355 "{\"a\":{\"b\":{\"c\":{}}},\"b\":{\"c\":{\"d\":{\"e\":{}}}}}";
1356 parse_options opt;
1357 opt.max_depth = 4;
1358 null_parser p(opt);
1359 error_code ec;
1360 p.write(s.data(), s.size(), ec);
1361 BOOST_TEST(ec == error::too_deep);
1362 }
1363 {
1364 string_view s =
1365 "{\"a\":{\"b\":{\"c\":{\"d\":{}}}}}";
1366 parse_options opt;
1367 opt.max_depth = 4;
1368 null_parser p(opt);
1369 error_code ec;
1370 p.write(s.data(), s.size(), ec);
1371 BOOST_TEST(ec == error::too_deep);
1372 }
1373 }
1374
1375 class literal_parser
1376 {
1377 struct handler
1378 {
1379 constexpr static std::size_t max_object_size = std::size_t(-1);
1380 constexpr static std::size_t max_array_size = std::size_t(-1);
1381 constexpr static std::size_t max_key_size = std::size_t(-1);
1382 constexpr static std::size_t max_string_size = std::size_t(-1);
1383
1384 std::string captured = "";
1385 bool on_document_begin( error_code& ) { return true; }
1386 bool on_document_end( error_code& ) { return true; }
1387 bool on_object_begin( error_code& ) { return true; }
1388 bool on_object_end( std::size_t, error_code& ) { return true; }
1389 bool on_array_begin( error_code& ) { return true; }
1390 bool on_array_end( std::size_t, error_code& ) { return true; }
1391 bool on_key_part( string_view, std::size_t, error_code& ) { return true; }
1392 bool on_key( string_view, std::size_t, error_code& ) { return true; }
1393 bool on_string_part( string_view, std::size_t, error_code& ) { return true; }
1394 bool on_string( string_view, std::size_t, error_code& ) { return true; }
1395 bool on_number_part( string_view sv, error_code&)
1396 {
1397 captured.append(sv.data(), sv.size());
1398 return true;
1399 }
1400 bool on_int64( std::int64_t, string_view sv, error_code& )
1401 {
1402 captured.append(sv.data(), sv.size());
1403 captured += 's';
1404 return true;
1405 }
1406 bool on_uint64( std::uint64_t, string_view sv, error_code& )
1407 {
1408 captured.append(sv.data(), sv.size());
1409 captured += 'u';
1410 return true;
1411 }
1412 bool on_double( double, string_view sv, error_code& )
1413 {
1414 captured.append(sv.data(), sv.size());
1415 captured += 'd';
1416 return true;
1417 }
1418 bool on_bool( bool, error_code& ) { return true; }
1419 bool on_null( error_code& ) { return true; }
1420 bool on_comment_part( string_view, error_code& ) { return true; }
1421 bool on_comment( string_view, error_code& ) { return true; }
1422 };
1423
1424 basic_parser<handler> p_;
1425
1426 public:
1427 literal_parser()
1428 : p_(make_options(true, false, false))
1429 {
1430 }
1431
1432 std::size_t
1433 write(
1434 bool more,
1435 char const* data,
1436 std::size_t size,
1437 error_code& ec)
1438 {
1439 auto const n = p_.write_some(
1440 more, data, size, ec);
1441 if(! ec && n < size)
1442 ec = error::extra_data;
1443 return n;
1444 }
1445
1446 string_view
1447 captured()
1448 {
1449 return p_.handler().captured;
1450 }
1451 };
1452
1453 void
1454 testNumberLiteral()
1455 {
1456 const auto check =
1457 [](string_view expected)
1458 {
1459 string_view sv = expected;
1460 sv.remove_suffix(1);
1461 for(std::size_t i = 0;
1462 i < sv.size(); ++i)
1463 {
1464 literal_parser p;
1465 error_code ec;
1466 if(i != 0)
1467 {
1468 p.write(true,
1469 sv.data(), i, ec);
1470 }
1471 if(BOOST_TEST(! ec))
1472 {
1473 p.write(false,
1474 sv.data() + i,
1475 sv.size() - i, ec);
1476 }
1477 BOOST_TEST(! ec);
1478 BOOST_TEST(p.captured() == expected);
1479 }
1480 };
1481
1482 check("1s");
1483 check("-1s");
1484 check("0s");
1485 check("0s");
1486 check("123456s");
1487 check("-123456s");
1488 check("9223372036854775808u");
1489
1490 check("1.0d");
1491 check("-1.0d");
1492 check("0.0d");
1493 check("1.0e3d");
1494 check("1e1d");
1495 check("1e+1d");
1496 check("1e-1d");
1497 check("-100000000000000000000000d");
1498 check("100000000000000000000000d");
1499 check("10000000000.10000000000000d");
1500 check("-10000000000.10000000000000d");
1501 check("1000000000000000.0e1000000d");
1502 }
1503
1504 void
1505 testStickyErrors()
1506 {
1507 {
1508 null_parser p;
1509 error_code ec;
1510 p.write("*", 1, ec);
1511 BOOST_TEST(ec);
1512 error_code ec2;
1513 p.write("[]", 2, ec2);
1514 BOOST_TEST(ec2 == ec);
1515 p.reset();
1516 p.write("[]", 2, ec2);
1517 BOOST_TEST(! ec2);
1518 }
1519
1520 // exceptions do not cause UB
1521 {
1522 throw_parser p(1);
1523 try
1524 {
1525 error_code ec;
1526 p.write(false, "null", 4, ec);
1527 BOOST_TEST_FAIL();
1528 }
1529 catch(std::exception const&)
1530 {
1531 error_code ec;
1532 p.write(false, "null", 4, ec);
1533 BOOST_TEST(ec == error::exception);
1534 }
1535 }
1536 }
1537
1538 void
1539 run()
1540 {
1541 testNull();
1542 testBoolean();
1543 testString();
1544 testNumber();
1545 testArray();
1546 testObject();
1547 testParser();
1548 testMembers();
1549 testParseVectors();
1550 testIssue13();
1551 testIssue20();
1552 testIssue113();
1553 testAllowTrailing();
1554 testComments();
1555 testUTF8Validation();
1556 testMaxDepth();
1557 testNumberLiteral();
1558 testStickyErrors();
1559 }
1560 };
1561
1562 TEST_SUITE(basic_parser_test, "boost.json.basic_parser");
1563
1564 BOOST_JSON_NS_END