1//     __ _____ _____ _____
2//  __|  |   __|     |   | |  JSON for Modern C++ (supporting code)
3// |  |  |__   |  |  | | | |  version 3.11.2
4// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
5//
6// Copyright (c) 2013-2022 Niels Lohmann <http://nlohmann.me>.
7// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
8// SPDX-License-Identifier: MIT
9
10#include "doctest_compatibility.h"
11
12#include <nlohmann/json.hpp>
13using nlohmann::json;
14#ifdef JSON_TEST_NO_GLOBAL_UDLS
15    using namespace nlohmann::literals; // NOLINT(google-build-using-namespace)
16#endif
17
18#include <iostream>
19#include <iterator>
20#include <sstream>
21#include <valarray>
22
23namespace
24{
25struct SaxEventLogger : public nlohmann::json_sax<json>
26{
27    bool null() override
28    {
29        events.emplace_back("null()");
30        return true;
31    }
32
33    bool boolean(bool val) override
34    {
35        events.emplace_back(val ? "boolean(true)" : "boolean(false)");
36        return true;
37    }
38
39    bool number_integer(json::number_integer_t val) override
40    {
41        events.push_back("number_integer(" + std::to_string(val) + ")");
42        return true;
43    }
44
45    bool number_unsigned(json::number_unsigned_t val) override
46    {
47        events.push_back("number_unsigned(" + std::to_string(val) + ")");
48        return true;
49    }
50
51    bool number_float(json::number_float_t /*val*/, const std::string& s) override
52    {
53        events.push_back("number_float(" + s + ")");
54        return true;
55    }
56
57    bool string(std::string& val) override
58    {
59        events.push_back("string(" + val + ")");
60        return true;
61    }
62
63    bool binary(json::binary_t& val) override
64    {
65        std::string binary_contents = "binary(";
66        std::string comma_space;
67        for (auto b : val)
68        {
69            binary_contents.append(comma_space);
70            binary_contents.append(std::to_string(static_cast<int>(b)));
71            comma_space = ", ";
72        }
73        binary_contents.append(")");
74        events.push_back(binary_contents);
75        return true;
76    }
77
78    bool start_object(std::size_t elements) override
79    {
80        if (elements == static_cast<std::size_t>(-1))
81        {
82            events.emplace_back("start_object()");
83        }
84        else
85        {
86            events.push_back("start_object(" + std::to_string(elements) + ")");
87        }
88        return true;
89    }
90
91    bool key(std::string& val) override
92    {
93        events.push_back("key(" + val + ")");
94        return true;
95    }
96
97    bool end_object() override
98    {
99        events.emplace_back("end_object()");
100        return true;
101    }
102
103    bool start_array(std::size_t elements) override
104    {
105        if (elements == static_cast<std::size_t>(-1))
106        {
107            events.emplace_back("start_array()");
108        }
109        else
110        {
111            events.push_back("start_array(" + std::to_string(elements) + ")");
112        }
113        return true;
114    }
115
116    bool end_array() override
117    {
118        events.emplace_back("end_array()");
119        return true;
120    }
121
122    bool parse_error(std::size_t position, const std::string& /*last_token*/, const json::exception& /*ex*/) override
123    {
124        events.push_back("parse_error(" + std::to_string(position) + ")");
125        return false;
126    }
127
128    std::vector<std::string> events {};
129};
130
131struct SaxEventLoggerExitAfterStartObject : public SaxEventLogger
132{
133    bool start_object(std::size_t elements) override
134    {
135        if (elements == static_cast<std::size_t>(-1))
136        {
137            events.emplace_back("start_object()");
138        }
139        else
140        {
141            events.push_back("start_object(" + std::to_string(elements) + ")");
142        }
143        return false;
144    }
145};
146
147struct SaxEventLoggerExitAfterKey : public SaxEventLogger
148{
149    bool key(std::string& val) override
150    {
151        events.push_back("key(" + val + ")");
152        return false;
153    }
154};
155
156struct SaxEventLoggerExitAfterStartArray : public SaxEventLogger
157{
158    bool start_array(std::size_t elements) override
159    {
160        if (elements == static_cast<std::size_t>(-1))
161        {
162            events.emplace_back("start_array()");
163        }
164        else
165        {
166            events.push_back("start_array(" + std::to_string(elements) + ")");
167        }
168        return false;
169    }
170};
171
172template <typename T>
173class proxy_iterator
174{
175  public:
176    using iterator = typename T::iterator;
177    using value_type = typename std::iterator_traits<iterator>::value_type;
178    using reference = typename std::iterator_traits<iterator>::reference;
179    using pointer = typename std::iterator_traits<iterator>::pointer;
180    using difference_type =
181        typename std::iterator_traits<iterator>::difference_type;
182    using iterator_category = std::input_iterator_tag;
183
184    proxy_iterator() = default;
185    explicit proxy_iterator(iterator& it) : m_it(std::addressof(it)) {}
186
187    proxy_iterator& operator++()
188    {
189        ++*m_it;
190        return *this;
191    }
192
193    proxy_iterator& operator--()
194    {
195        --*m_it;
196        return *this;
197    }
198
199    bool operator==(const proxy_iterator& rhs) const
200    {
201        return (m_it && rhs.m_it) ? (*m_it == *rhs.m_it) : (m_it == rhs.m_it);
202    }
203
204    bool operator!=(const proxy_iterator& rhs) const
205    {
206        return !(*this == rhs);
207    }
208
209    reference operator*() const
210    {
211        return **m_it;
212    }
213
214  private:
215    iterator* m_it = nullptr;
216};
217} // namespace
218
219TEST_CASE("deserialization")
220{
221    SECTION("successful deserialization")
222    {
223        SECTION("stream")
224        {
225            std::stringstream ss1;
226            std::stringstream ss2;
227            std::stringstream ss3;
228            ss1 << R"(["foo",1,2,3,false,{"one":1}])";
229            ss2 << R"(["foo",1,2,3,false,{"one":1}])";
230            ss3 << R"(["foo",1,2,3,false,{"one":1}])";
231            json j = json::parse(ss1);
232            CHECK(json::accept(ss2));
233            CHECK(j == json({"foo", 1, 2, 3, false, {{"one", 1}}}));
234
235            SaxEventLogger l;
236            CHECK(json::sax_parse(ss3, &l));
237            CHECK(l.events.size() == 11);
238            CHECK(l.events == std::vector<std::string>(
239            {
240                "start_array()", "string(foo)", "number_unsigned(1)",
241                "number_unsigned(2)", "number_unsigned(3)", "boolean(false)",
242                "start_object()", "key(one)", "number_unsigned(1)",
243                "end_object()", "end_array()"
244            }));
245        }
246
247        SECTION("string literal")
248        {
249            const auto* s = R"(["foo",1,2,3,false,{"one":1}])";
250            json j = json::parse(s);
251            CHECK(json::accept(s));
252            CHECK(j == json({"foo", 1, 2, 3, false, {{"one", 1}}}));
253
254            SaxEventLogger l;
255            CHECK(json::sax_parse(s, &l));
256            CHECK(l.events.size() == 11);
257            CHECK(l.events == std::vector<std::string>(
258            {
259                "start_array()", "string(foo)", "number_unsigned(1)",
260                "number_unsigned(2)", "number_unsigned(3)", "boolean(false)",
261                "start_object()", "key(one)", "number_unsigned(1)",
262                "end_object()", "end_array()"
263            }));
264        }
265
266        SECTION("string_t")
267        {
268            json::string_t s = R"(["foo",1,2,3,false,{"one":1}])";
269            json j = json::parse(s);
270            CHECK(json::accept(s));
271            CHECK(j == json({"foo", 1, 2, 3, false, {{"one", 1}}}));
272
273            SaxEventLogger l;
274            CHECK(json::sax_parse(s, &l));
275            CHECK(l.events.size() == 11);
276            CHECK(l.events == std::vector<std::string>(
277            {
278                "start_array()", "string(foo)", "number_unsigned(1)",
279                "number_unsigned(2)", "number_unsigned(3)", "boolean(false)",
280                "start_object()", "key(one)", "number_unsigned(1)",
281                "end_object()", "end_array()"
282            }));
283        }
284
285        SECTION("operator<<")
286        {
287            std::stringstream ss;
288            ss << R"(["foo",1,2,3,false,{"one":1}])";
289            json j;
290            j << ss;
291            CHECK(j == json({"foo", 1, 2, 3, false, {{"one", 1}}}));
292        }
293
294        SECTION("operator>>")
295        {
296            std::stringstream ss;
297            ss << R"(["foo",1,2,3,false,{"one":1}])";
298            json j;
299            ss >> j;
300            CHECK(j == json({"foo", 1, 2, 3, false, {{"one", 1}}}));
301        }
302
303        SECTION("user-defined string literal")
304        {
305            CHECK("[\"foo\",1,2,3,false,{\"one\":1}]"_json == json({"foo", 1, 2, 3, false, {{"one", 1}}}));
306        }
307    }
308
309    SECTION("unsuccessful deserialization")
310    {
311        SECTION("stream")
312        {
313            std::stringstream ss1;
314            std::stringstream ss3;
315            std::stringstream ss4;
316            std::stringstream ss5;
317            ss1 << R"(["foo",1,2,3,false,{"one":1})";
318            ss3 << R"(["foo",1,2,3,false,{"one":1})";
319            ss4 << R"(["foo",1,2,3,false,{"one":1})";
320            ss5 << R"(["foo",1,2,3,false,{"one":1})";
321
322            json _;
323            CHECK_THROWS_WITH_AS(_ = json::parse(ss1), "[json.exception.parse_error.101] parse error at line 1, column 29: syntax error while parsing array - unexpected end of input; expected ']'", json::parse_error&);
324            CHECK(!json::accept(ss3));
325
326            json j_error;
327            CHECK_NOTHROW(j_error = json::parse(ss4, nullptr, false));
328            CHECK(j_error.is_discarded());
329
330            SaxEventLogger l;
331            CHECK(!json::sax_parse(ss5, &l));
332            CHECK(l.events.size() == 11);
333            CHECK(l.events == std::vector<std::string>(
334            {
335                "start_array()", "string(foo)", "number_unsigned(1)",
336                "number_unsigned(2)", "number_unsigned(3)", "boolean(false)",
337                "start_object()", "key(one)", "number_unsigned(1)",
338                "end_object()", "parse_error(29)"
339            }));
340        }
341
342        SECTION("string")
343        {
344            json::string_t s = R"(["foo",1,2,3,false,{"one":1})";
345            json _;
346            CHECK_THROWS_WITH_AS(_ = json::parse(s), "[json.exception.parse_error.101] parse error at line 1, column 29: syntax error while parsing array - unexpected end of input; expected ']'", json::parse_error&);
347            CHECK(!json::accept(s));
348
349            json j_error;
350            CHECK_NOTHROW(j_error = json::parse(s, nullptr, false));
351            CHECK(j_error.is_discarded());
352
353            SaxEventLogger l;
354            CHECK(!json::sax_parse(s, &l));
355            CHECK(l.events.size() == 11);
356            CHECK(l.events == std::vector<std::string>(
357            {
358                "start_array()", "string(foo)", "number_unsigned(1)",
359                "number_unsigned(2)", "number_unsigned(3)", "boolean(false)",
360                "start_object()", "key(one)", "number_unsigned(1)",
361                "end_object()", "parse_error(29)"
362            }));
363        }
364
365        SECTION("operator<<")
366        {
367            std::stringstream ss;
368            ss << R"(["foo",1,2,3,false,{"one":1})";
369            json j;
370            CHECK_THROWS_WITH_AS(j << ss, "[json.exception.parse_error.101] parse error at line 1, column 29: syntax error while parsing array - unexpected end of input; expected ']'", json::parse_error&);
371        }
372
373        SECTION("operator>>")
374        {
375            std::stringstream ss;
376            ss << R"(["foo",1,2,3,false,{"one":1})";
377            json j;
378            CHECK_THROWS_WITH_AS(ss >> j, "[json.exception.parse_error.101] parse error at line 1, column 29: syntax error while parsing array - unexpected end of input; expected ']'", json::parse_error&);
379        }
380
381        SECTION("user-defined string literal")
382        {
383            CHECK_THROWS_WITH_AS("[\"foo\",1,2,3,false,{\"one\":1}"_json, "[json.exception.parse_error.101] parse error at line 1, column 29: syntax error while parsing array - unexpected end of input; expected ']'", json::parse_error&);
384        }
385    }
386
387    SECTION("contiguous containers")
388    {
389        SECTION("directly")
390        {
391            SECTION("from std::vector")
392            {
393                std::vector<uint8_t> v = {'t', 'r', 'u', 'e'};
394                CHECK(json::parse(v) == json(true));
395                CHECK(json::accept(v));
396
397                SaxEventLogger l;
398                CHECK(json::sax_parse(v, &l));
399                CHECK(l.events.size() == 1);
400                CHECK(l.events == std::vector<std::string>({"boolean(true)"}));
401            }
402
403            SECTION("from std::array")
404            {
405                std::array<uint8_t, 5> v { {'t', 'r', 'u', 'e'} };
406                CHECK(json::parse(v) == json(true));
407                CHECK(json::accept(v));
408
409                SaxEventLogger l;
410                CHECK(json::sax_parse(v, &l));
411                CHECK(l.events.size() == 1);
412                CHECK(l.events == std::vector<std::string>({"boolean(true)"}));
413            }
414
415            SECTION("from array")
416            {
417                uint8_t v[] = {'t', 'r', 'u', 'e'}; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
418                CHECK(json::parse(v) == json(true));
419                CHECK(json::accept(v));
420
421                SaxEventLogger l;
422                CHECK(json::sax_parse(v, &l));
423                CHECK(l.events.size() == 1);
424                CHECK(l.events == std::vector<std::string>({"boolean(true)"}));
425            }
426
427            SECTION("from chars")
428            {
429                auto* v = new uint8_t[5]; // NOLINT(cppcoreguidelines-owning-memory)
430                v[0] = 't';
431                v[1] = 'r';
432                v[2] = 'u';
433                v[3] = 'e';
434                v[4] = '\0';
435                CHECK(json::parse(v) == json(true));
436                CHECK(json::accept(v));
437
438                SaxEventLogger l;
439                CHECK(json::sax_parse(v, &l));
440                CHECK(l.events.size() == 1);
441                CHECK(l.events == std::vector<std::string>({"boolean(true)"}));
442
443                delete[] v; // NOLINT(cppcoreguidelines-owning-memory)
444            }
445
446            SECTION("from std::string")
447            {
448                std::string v = {'t', 'r', 'u', 'e'};
449                CHECK(json::parse(v) == json(true));
450                CHECK(json::accept(v));
451
452                SaxEventLogger l;
453                CHECK(json::sax_parse(v, &l));
454                CHECK(l.events.size() == 1);
455                CHECK(l.events == std::vector<std::string>({"boolean(true)"}));
456            }
457
458            SECTION("from std::initializer_list")
459            {
460                std::initializer_list<uint8_t> v = {'t', 'r', 'u', 'e'};
461                CHECK(json::parse(v) == json(true));
462                CHECK(json::accept(v));
463
464                SaxEventLogger l;
465                CHECK(json::sax_parse(v, &l));
466                CHECK(l.events.size() == 1);
467                CHECK(l.events == std::vector<std::string>({"boolean(true)"}));
468            }
469
470            SECTION("empty container")
471            {
472                std::vector<uint8_t> v;
473                json _;
474                CHECK_THROWS_AS(_ = json::parse(v), json::parse_error&);
475                CHECK(!json::accept(v));
476
477                SaxEventLogger l;
478                CHECK(!json::sax_parse(v, &l));
479                CHECK(l.events.size() == 1);
480                CHECK(l.events == std::vector<std::string>({"parse_error(1)"}));
481            }
482        }
483
484        SECTION("via iterator range")
485        {
486            SECTION("from std::vector")
487            {
488                std::vector<uint8_t> v = {'t', 'r', 'u', 'e'};
489                CHECK(json::parse(std::begin(v), std::end(v)) == json(true));
490                CHECK(json::accept(std::begin(v), std::end(v)));
491
492                SaxEventLogger l;
493                CHECK(json::sax_parse(std::begin(v), std::end(v), &l));
494                CHECK(l.events.size() == 1);
495                CHECK(l.events == std::vector<std::string>({"boolean(true)"}));
496
497            }
498
499            SECTION("from std::array")
500            {
501                std::array<uint8_t, 5> v { {'t', 'r', 'u', 'e'} };
502                CHECK(json::parse(std::begin(v), std::end(v)) == json(true));
503                CHECK(json::accept(std::begin(v), std::end(v)));
504
505                SaxEventLogger l;
506                CHECK(json::sax_parse(std::begin(v), std::end(v), &l));
507                CHECK(l.events.size() == 1);
508                CHECK(l.events == std::vector<std::string>({"boolean(true)"}));
509            }
510
511            SECTION("from array")
512            {
513                uint8_t v[] = {'t', 'r', 'u', 'e'}; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
514                CHECK(json::parse(std::begin(v), std::end(v)) == json(true));
515                CHECK(json::accept(std::begin(v), std::end(v)));
516
517                SaxEventLogger l;
518                CHECK(json::sax_parse(std::begin(v), std::end(v), &l));
519                CHECK(l.events.size() == 1);
520                CHECK(l.events == std::vector<std::string>({"boolean(true)"}));
521            }
522
523            SECTION("from std::string")
524            {
525                std::string v = {'t', 'r', 'u', 'e'};
526                CHECK(json::parse(std::begin(v), std::end(v)) == json(true));
527                CHECK(json::accept(std::begin(v), std::end(v)));
528
529                SaxEventLogger l;
530                CHECK(json::sax_parse(std::begin(v), std::end(v), &l));
531                CHECK(l.events.size() == 1);
532                CHECK(l.events == std::vector<std::string>({"boolean(true)"}));
533            }
534
535            SECTION("from std::initializer_list")
536            {
537                std::initializer_list<uint8_t> v = {'t', 'r', 'u', 'e'};
538                CHECK(json::parse(std::begin(v), std::end(v)) == json(true));
539                CHECK(json::accept(std::begin(v), std::end(v)));
540
541                SaxEventLogger l;
542                CHECK(json::sax_parse(std::begin(v), std::end(v), &l));
543                CHECK(l.events.size() == 1);
544                CHECK(l.events == std::vector<std::string>({"boolean(true)"}));
545            }
546
547            SECTION("from std::valarray")
548            {
549                std::valarray<uint8_t> v = {'t', 'r', 'u', 'e'};
550                CHECK(json::parse(std::begin(v), std::end(v)) == json(true));
551                CHECK(json::accept(std::begin(v), std::end(v)));
552
553                SaxEventLogger l;
554                CHECK(json::sax_parse(std::begin(v), std::end(v), &l));
555                CHECK(l.events.size() == 1);
556                CHECK(l.events == std::vector<std::string>({"boolean(true)"}));
557            }
558
559            SECTION("with empty range")
560            {
561                std::vector<uint8_t> v;
562                json _;
563                CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
564                CHECK(!json::accept(std::begin(v), std::end(v)));
565
566                SaxEventLogger l;
567                CHECK(!json::sax_parse(std::begin(v), std::end(v), &l));
568                CHECK(l.events.size() == 1);
569                CHECK(l.events == std::vector<std::string>({"parse_error(1)"}));
570            }
571
572            SECTION("iterator_input_adapter advances iterators correctly")
573            {
574                using nlohmann::json;
575                using nlohmann::detail::input_format_t;
576                using nlohmann::detail::json_sax_dom_parser;
577                using proxy = proxy_iterator<std::string>;
578
579                std::string str1 = "[1]";
580                std::string str2 = "[2]";
581                std::string str = str1 + str2;
582
583                auto first = str.begin();
584                auto last = str.end();
585                json j;
586                json_sax_dom_parser<json> sax(j, true);
587
588                CHECK(json::sax_parse(proxy(first), proxy(last), &sax,
589                                      input_format_t::json, false));
590                CHECK(j.dump() == str1);
591                CHECK(std::string(first, last) == str2);
592            }
593        }
594
595        // these cases are required for 100% line coverage
596        SECTION("error cases")
597        {
598            SECTION("case 1")
599            {
600                std::array<std::uint8_t, 9> v = {{'\"', 'a', 'a', 'a', 'a', 'a', 'a', '\\', 'u'}};
601                json _;
602                CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
603                CHECK(!json::accept(std::begin(v), std::end(v)));
604
605                json j_error;
606                CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
607                CHECK(j_error.is_discarded());
608
609                SaxEventLogger l;
610                CHECK(!json::sax_parse(std::begin(v), std::end(v), &l));
611                CHECK(l.events.size() == 1);
612                CHECK(l.events == std::vector<std::string>({"parse_error(10)"}));
613            }
614
615            SECTION("case 2")
616            {
617                std::array<std::uint8_t, 10> v = {{'\"', 'a', 'a', 'a', 'a', 'a', 'a', '\\', 'u', '1'}};
618                json _;
619                CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
620                CHECK(!json::accept(std::begin(v), std::end(v)));
621
622                json j_error;
623                CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
624                CHECK(j_error.is_discarded());
625
626                SaxEventLogger l;
627                CHECK(!json::sax_parse(std::begin(v), std::end(v), &l));
628                CHECK(l.events.size() == 1);
629                CHECK(l.events == std::vector<std::string>({"parse_error(11)"}));
630            }
631
632            SECTION("case 3")
633            {
634                std::array<std::uint8_t, 17> v = {{'\"', 'a', 'a', 'a', 'a', 'a', 'a', '\\', 'u', '1', '1', '1', '1', '1', '1', '1', '1'}};
635                json _;
636                CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
637                CHECK(!json::accept(std::begin(v), std::end(v)));
638
639                json j_error;
640                CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
641                CHECK(j_error.is_discarded());
642
643                SaxEventLogger l;
644                CHECK(!json::sax_parse(std::begin(v), std::end(v), &l));
645                CHECK(l.events.size() == 1);
646                CHECK(l.events == std::vector<std::string>({"parse_error(18)"}));
647            }
648
649            SECTION("case 4")
650            {
651                std::array<std::uint8_t, 17> v = {{'\"', 'a', 'a', 'a', 'a', 'a', 'a', 'u', '1', '1', '1', '1', '1', '1', '1', '1', '\\'}};
652                json _;
653                CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
654                CHECK(!json::accept(std::begin(v), std::end(v)));
655
656                json j_error;
657                CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
658                CHECK(j_error.is_discarded());
659
660                SaxEventLogger l;
661                CHECK(!json::sax_parse(std::begin(v), std::end(v), &l));
662                CHECK(l.events.size() == 1);
663                CHECK(l.events == std::vector<std::string>({"parse_error(18)"}));
664            }
665
666            SECTION("case 5")
667            {
668                std::array<std::uint8_t, 3> v = {{'\"', 0x7F, 0xC1}};
669                json _;
670                CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
671                CHECK(!json::accept(std::begin(v), std::end(v)));
672
673                json j_error;
674                CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
675                CHECK(j_error.is_discarded());
676
677                SaxEventLogger l;
678                CHECK(!json::sax_parse(std::begin(v), std::end(v), &l));
679                CHECK(l.events.size() == 1);
680                CHECK(l.events == std::vector<std::string>({"parse_error(3)"}));
681            }
682
683            SECTION("case 6")
684            {
685                std::array<std::uint8_t, 4> v = {{'\"', 0x7F, 0xDF, 0x7F}};
686                json _;
687                CHECK_THROWS_WITH_AS(_ = json::parse(std::begin(v), std::end(v)), "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid string: ill-formed UTF-8 byte; last read: '\"\x7f\xdf\x7f'", json::parse_error&);
688                CHECK(!json::accept(std::begin(v), std::end(v)));
689
690                json j_error;
691                CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
692                CHECK(j_error.is_discarded());
693
694                SaxEventLogger l;
695                CHECK(!json::sax_parse(std::begin(v), std::end(v), &l));
696                CHECK(l.events.size() == 1);
697                CHECK(l.events == std::vector<std::string>({"parse_error(4)"}));
698            }
699
700            SECTION("case 7")
701            {
702                std::array<std::uint8_t, 4> v = {{'\"', 0x7F, 0xDF, 0xC0}};
703                json _;
704                CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
705                CHECK(!json::accept(std::begin(v), std::end(v)));
706
707                json j_error;
708                CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
709                CHECK(j_error.is_discarded());
710
711                SaxEventLogger l;
712                CHECK(!json::sax_parse(std::begin(v), std::end(v), &l));
713                CHECK(l.events.size() == 1);
714                CHECK(l.events == std::vector<std::string>({"parse_error(4)"}));
715            }
716
717            SECTION("case 8")
718            {
719                std::array<std::uint8_t, 4> v = {{'\"', 0x7F, 0xE0, 0x9F}};
720                json _;
721                CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
722                CHECK(!json::accept(std::begin(v), std::end(v)));
723
724                json j_error;
725                CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
726                CHECK(j_error.is_discarded());
727
728                SaxEventLogger l;
729                CHECK(!json::sax_parse(std::begin(v), std::end(v), &l));
730                CHECK(l.events.size() == 1);
731                CHECK(l.events == std::vector<std::string>({"parse_error(4)"}));
732            }
733
734            SECTION("case 9")
735            {
736                std::array<std::uint8_t, 4> v = {{'\"', 0x7F, 0xEF, 0xC0}};
737                json _;
738                CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
739                CHECK(!json::accept(std::begin(v), std::end(v)));
740
741                json j_error;
742                CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
743                CHECK(j_error.is_discarded());
744
745                SaxEventLogger l;
746                CHECK(!json::sax_parse(std::begin(v), std::end(v), &l));
747                CHECK(l.events.size() == 1);
748                CHECK(l.events == std::vector<std::string>({"parse_error(4)"}));
749            }
750
751            SECTION("case 10")
752            {
753                std::array<std::uint8_t, 4> v = {{'\"', 0x7F, 0xED, 0x7F}};
754                json _;
755                CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
756                CHECK(!json::accept(std::begin(v), std::end(v)));
757
758                json j_error;
759                CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
760                CHECK(j_error.is_discarded());
761
762                SaxEventLogger l;
763                CHECK(!json::sax_parse(std::begin(v), std::end(v), &l));
764                CHECK(l.events.size() == 1);
765                CHECK(l.events == std::vector<std::string>({"parse_error(4)"}));
766            }
767
768            SECTION("case 11")
769            {
770                std::array<std::uint8_t, 4> v = {{'\"', 0x7F, 0xF0, 0x8F}};
771                json _;
772                CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
773                CHECK(!json::accept(std::begin(v), std::end(v)));
774
775                json j_error;
776                CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
777                CHECK(j_error.is_discarded());
778
779                SaxEventLogger l;
780                CHECK(!json::sax_parse(std::begin(v), std::end(v), &l));
781                CHECK(l.events.size() == 1);
782                CHECK(l.events == std::vector<std::string>({"parse_error(4)"}));
783            }
784
785            SECTION("case 12")
786            {
787                std::array<std::uint8_t, 4> v = {{'\"', 0x7F, 0xF0, 0xC0}};
788                json _;
789                CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
790                CHECK(!json::accept(std::begin(v), std::end(v)));
791
792                json j_error;
793                CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
794                CHECK(j_error.is_discarded());
795
796                SaxEventLogger l;
797                CHECK(!json::sax_parse(std::begin(v), std::end(v), &l));
798                CHECK(l.events.size() == 1);
799                CHECK(l.events == std::vector<std::string>({"parse_error(4)"}));
800            }
801
802            SECTION("case 13")
803            {
804                std::array<std::uint8_t, 4> v = {{'\"', 0x7F, 0xF3, 0x7F}};
805                json _;
806                CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
807                CHECK(!json::accept(std::begin(v), std::end(v)));
808
809                json j_error;
810                CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
811                CHECK(j_error.is_discarded());
812
813                SaxEventLogger l;
814                CHECK(!json::sax_parse(std::begin(v), std::end(v), &l));
815                CHECK(l.events.size() == 1);
816                CHECK(l.events == std::vector<std::string>({"parse_error(4)"}));
817            }
818
819            SECTION("case 14")
820            {
821                std::array<std::uint8_t, 4> v = {{'\"', 0x7F, 0xF3, 0xC0}};
822                json _;
823                CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
824                CHECK(!json::accept(std::begin(v), std::end(v)));
825
826                json j_error;
827                CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
828                CHECK(j_error.is_discarded());
829
830                SaxEventLogger l;
831                CHECK(!json::sax_parse(std::begin(v), std::end(v), &l));
832                CHECK(l.events.size() == 1);
833                CHECK(l.events == std::vector<std::string>({"parse_error(4)"}));
834            }
835
836            SECTION("case 15")
837            {
838                std::array<std::uint8_t, 4> v = {{'\"', 0x7F, 0xF4, 0x7F}};
839                json _;
840                CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
841                CHECK(!json::accept(std::begin(v), std::end(v)));
842
843                json j_error;
844                CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
845                CHECK(j_error.is_discarded());
846
847                SaxEventLogger l;
848                CHECK(!json::sax_parse(std::begin(v), std::end(v), &l));
849                CHECK(l.events.size() == 1);
850                CHECK(l.events == std::vector<std::string>({"parse_error(4)"}));
851            }
852
853            SECTION("case 16")
854            {
855                std::array<std::uint8_t, 6> v = {{'{', '\"', '\"', ':', '1', '1'}};
856                json _;
857                CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
858                CHECK(!json::accept(std::begin(v), std::end(v)));
859
860                json j_error;
861                CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
862                CHECK(j_error.is_discarded());
863
864                SaxEventLogger l;
865                CHECK(!json::sax_parse(std::begin(v), std::end(v), &l));
866                CHECK(l.events.size() == 4);
867                CHECK(l.events == std::vector<std::string>(
868                {
869                    "start_object()", "key()", "number_unsigned(11)",
870                    "parse_error(7)"
871                }));
872            }
873        }
874    }
875
876    SECTION("ignoring byte-order marks")
877    {
878        std::string bom = "\xEF\xBB\xBF";
879
880        SECTION("BOM only")
881        {
882            json _;
883            CHECK_THROWS_WITH_AS(_ = json::parse(bom), "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal", json::parse_error&);
884
885            CHECK_THROWS_WITH_AS(_ = json::parse(std::istringstream(bom)), "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal", json::parse_error&);
886
887            SaxEventLogger l;
888            CHECK(!json::sax_parse(bom, &l));
889            CHECK(l.events.size() == 1);
890            CHECK(l.events == std::vector<std::string>(
891            {
892                "parse_error(4)"
893            }));
894        }
895
896        SECTION("BOM and content")
897        {
898            CHECK(json::parse(bom + "1") == 1);
899            CHECK(json::parse(std::istringstream(bom + "1")) == 1);
900
901            SaxEventLogger l1;
902            SaxEventLogger l2;
903            CHECK(json::sax_parse(std::istringstream(bom + "1"), &l1));
904            CHECK(json::sax_parse(bom + "1", &l2));
905            CHECK(l1.events.size() == 1);
906            CHECK(l1.events == std::vector<std::string>(
907            {
908                "number_unsigned(1)"
909            }));
910            CHECK(l2.events.size() == 1);
911            CHECK(l2.events == std::vector<std::string>(
912            {
913                "number_unsigned(1)"
914            }));
915        }
916
917        SECTION("2 byte of BOM")
918        {
919            json _;
920            CHECK_THROWS_WITH_AS(_ = json::parse(bom.substr(0, 2)), "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid BOM; must be 0xEF 0xBB 0xBF if given; last read: '\xEF\xBB'", json::parse_error&);
921
922            CHECK_THROWS_WITH_AS(_ = json::parse(std::istringstream(bom.substr(0, 2))), "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid BOM; must be 0xEF 0xBB 0xBF if given; last read: '\xEF\xBB'", json::parse_error&);
923
924            SaxEventLogger l1;
925            SaxEventLogger l2;
926            CHECK(!json::sax_parse(std::istringstream(bom.substr(0, 2)), &l1));
927            CHECK(!json::sax_parse(bom.substr(0, 2), &l2));
928            CHECK(l1.events.size() == 1);
929            CHECK(l1.events == std::vector<std::string>(
930            {
931                "parse_error(3)"
932            }));
933            CHECK(l2.events.size() == 1);
934            CHECK(l2.events == std::vector<std::string>(
935            {
936                "parse_error(3)"
937            }));
938        }
939
940        SECTION("1 byte of BOM")
941        {
942            json _;
943            CHECK_THROWS_WITH_AS(_ = json::parse(bom.substr(0, 1)), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid BOM; must be 0xEF 0xBB 0xBF if given; last read: '\xEF'", json::parse_error&);
944
945            CHECK_THROWS_WITH_AS(_ = json::parse(std::istringstream(bom.substr(0, 1))), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid BOM; must be 0xEF 0xBB 0xBF if given; last read: '\xEF'", json::parse_error&);
946
947            SaxEventLogger l1;
948            SaxEventLogger l2;
949            CHECK(!json::sax_parse(std::istringstream(bom.substr(0, 1)), &l1));
950            CHECK(!json::sax_parse(bom.substr(0, 1), &l2));
951            CHECK(l1.events.size() == 1);
952            CHECK(l1.events == std::vector<std::string>(
953            {
954                "parse_error(2)"
955            }));
956            CHECK(l2.events.size() == 1);
957            CHECK(l2.events == std::vector<std::string>(
958            {
959                "parse_error(2)"
960            }));
961        }
962
963        SECTION("variations")
964        {
965            // calculate variations of each byte of the BOM to make sure
966            // that the BOM and only the BOM is skipped
967            for (int i0 = -1; i0 < 2; ++i0)
968            {
969                for (int i1 = -1; i1 < 2; ++i1)
970                {
971                    for (int i2 = -1; i2 < 2; ++i2)
972                    {
973                        // debug output for the variations
974                        CAPTURE(i0)
975                        CAPTURE(i1)
976                        CAPTURE(i2)
977
978                        std::string s;
979                        s.push_back(static_cast<char>(bom[0] + i0));
980                        s.push_back(static_cast<char>(bom[1] + i1));
981                        s.push_back(static_cast<char>(bom[2] + i2));
982
983                        if (i0 == 0 && i1 == 0 && i2 == 0)
984                        {
985                            // without any variation, we skip the BOM
986                            CHECK(json::parse(s + "null") == json());
987                            CHECK(json::parse(std::istringstream(s + "null")) == json());
988
989                            SaxEventLogger l;
990                            CHECK(json::sax_parse(s + "null", &l));
991                            CHECK(l.events.size() == 1);
992                            CHECK(l.events == std::vector<std::string>(
993                            {
994                                "null()"
995                            }));
996                        }
997                        else
998                        {
999                            // any variation is an error
1000                            json _;
1001                            CHECK_THROWS_AS(_ = json::parse(s + "null"), json::parse_error&);
1002                            CHECK_THROWS_AS(_ = json::parse(std::istringstream(s + "null")), json::parse_error&);
1003
1004                            SaxEventLogger l;
1005                            CHECK(!json::sax_parse(s + "null", &l));
1006                            CHECK(l.events.size() == 1);
1007
1008                            if (i0 != 0)
1009                            {
1010                                CHECK(l.events == std::vector<std::string>(
1011                                {
1012                                    "parse_error(1)"
1013                                }));
1014                            }
1015                            else if (i1 != 0)
1016                            {
1017                                CHECK(l.events == std::vector<std::string>(
1018                                {
1019                                    "parse_error(2)"
1020                                }));
1021                            }
1022                            else
1023                            {
1024                                CHECK(l.events == std::vector<std::string>(
1025                                {
1026                                    "parse_error(3)"
1027                                }));
1028                            }
1029                        }
1030                    }
1031                }
1032            }
1033        }
1034
1035        SECTION("preserve state after parsing")
1036        {
1037            std::istringstream s(bom + "123 456");
1038            json j;
1039            j << s;
1040            CHECK(j == 123);
1041            j << s;
1042            CHECK(j == 456);
1043        }
1044    }
1045
1046    SECTION("SAX and early abort")
1047    {
1048        std::string s = R"([1, ["string", 43.12], null, {"key1": true, "key2": false}])";
1049
1050        SaxEventLogger default_logger;
1051        SaxEventLoggerExitAfterStartObject exit_after_start_object;
1052        SaxEventLoggerExitAfterKey exit_after_key;
1053        SaxEventLoggerExitAfterStartArray exit_after_start_array;
1054
1055        json::sax_parse(s, &default_logger);
1056        CHECK(default_logger.events.size() == 14);
1057        CHECK(default_logger.events == std::vector<std::string>(
1058        {
1059            "start_array()", "number_unsigned(1)", "start_array()",
1060            "string(string)", "number_float(43.12)", "end_array()", "null()",
1061            "start_object()", "key(key1)", "boolean(true)", "key(key2)",
1062            "boolean(false)", "end_object()", "end_array()"
1063        }));
1064
1065        json::sax_parse(s, &exit_after_start_object);
1066        CHECK(exit_after_start_object.events.size() == 8);
1067        CHECK(exit_after_start_object.events == std::vector<std::string>(
1068        {
1069            "start_array()", "number_unsigned(1)", "start_array()",
1070            "string(string)", "number_float(43.12)", "end_array()", "null()",
1071            "start_object()"
1072        }));
1073
1074        json::sax_parse(s, &exit_after_key);
1075        CHECK(exit_after_key.events.size() == 9);
1076        CHECK(exit_after_key.events == std::vector<std::string>(
1077        {
1078            "start_array()", "number_unsigned(1)", "start_array()",
1079            "string(string)", "number_float(43.12)", "end_array()", "null()",
1080            "start_object()", "key(key1)"
1081        }));
1082
1083        json::sax_parse(s, &exit_after_start_array);
1084        CHECK(exit_after_start_array.events.size() == 1);
1085        CHECK(exit_after_start_array.events == std::vector<std::string>(
1086        {
1087            "start_array()"
1088        }));
1089    }
1090
1091    SECTION("JSON Lines")
1092    {
1093        SECTION("Example file")
1094        {
1095            std::stringstream ss;
1096            ss << R"({"name": "Gilbert", "wins": [["straight", "7"], ["one pair", "10"]]}
1097                    {"name": "Alexa", "wins": [["two pair", "4"], ["two pair", "9"]]}
1098                    {"name": "May", "wins": []}
1099                    {"name": "Deloise", "wins": [["three of a kind", "5"]]}
1100)";
1101
1102            std::string line;
1103            int object_count = 0;
1104            while (std::getline(ss, line))
1105            {
1106                ++object_count;
1107                CHECK(json::accept(line));
1108            }
1109
1110            CHECK(object_count == 4);
1111        }
1112
1113        SECTION("Example file without trailing newline")
1114        {
1115            std::stringstream ss;
1116            ss << R"({"name": "Gilbert", "wins": [["straight", "7"], ["one pair", "10"]]}
1117                    {"name": "Alexa", "wins": [["two pair", "4"], ["two pair", "9"]]}
1118                    {"name": "May", "wins": []}
1119                    {"name": "Deloise", "wins": [["three of a kind", "5"]]})";
1120
1121            std::string line;
1122            int object_count = 0;
1123            while (std::getline(ss, line))
1124            {
1125                ++object_count;
1126                CHECK(json::accept(line));
1127            }
1128
1129            CHECK(object_count == 4);
1130        }
1131    }
1132}
1133
1134TEST_CASE_TEMPLATE("deserialization of different character types (ASCII)", T,
1135                   char, unsigned char, signed char,
1136                   wchar_t,
1137                   char16_t, char32_t,
1138                   std::uint8_t, std::int8_t,
1139                   std::int16_t, std::uint16_t,
1140                   std::int32_t, std::uint32_t)
1141{
1142    std::vector<T> v = {'t', 'r', 'u', 'e'};
1143    CHECK(json::parse(v) == json(true));
1144    CHECK(json::accept(v));
1145
1146    SaxEventLogger l;
1147    CHECK(json::sax_parse(v, &l));
1148    CHECK(l.events.size() == 1);
1149    CHECK(l.events == std::vector<std::string>({"boolean(true)"}));
1150}
1151
1152TEST_CASE_TEMPLATE("deserialization of different character types (UTF-8)", T,
1153                   char, unsigned char, std::uint8_t)
1154{
1155    // a star emoji
1156    std::vector<T> v = {'"', static_cast<T>(0xe2u), static_cast<T>(0xadu), static_cast<T>(0x90u), static_cast<T>(0xefu), static_cast<T>(0xb8u), static_cast<T>(0x8fu), '"'};
1157    CHECK(json::parse(v).dump(-1, ' ', true) == "\"\\u2b50\\ufe0f\"");
1158    CHECK(json::accept(v));
1159
1160    SaxEventLogger l;
1161    CHECK(json::sax_parse(v, &l));
1162    CHECK(l.events.size() == 1);
1163}
1164
1165TEST_CASE_TEMPLATE("deserialization of different character types (UTF-16)", T,
1166                   char16_t, std::uint16_t)
1167{
1168    // a star emoji
1169    std::vector<T> v = {static_cast<T>('"'), static_cast<T>(0x2b50), static_cast<T>(0xfe0f), static_cast<T>('"')};
1170    CHECK(json::parse(v).dump(-1, ' ', true) == "\"\\u2b50\\ufe0f\"");
1171    CHECK(json::accept(v));
1172
1173    SaxEventLogger l;
1174    CHECK(json::sax_parse(v, &l));
1175    CHECK(l.events.size() == 1);
1176}
1177
1178TEST_CASE_TEMPLATE("deserialization of different character types (UTF-32)", T,
1179                   char32_t, std::uint32_t)
1180{
1181    // a star emoji
1182    std::vector<T> v = {static_cast<T>('"'), static_cast<T>(0x2b50), static_cast<T>(0xfe0f), static_cast<T>('"')};
1183    CHECK(json::parse(v).dump(-1, ' ', true) == "\"\\u2b50\\ufe0f\"");
1184    CHECK(json::accept(v));
1185
1186    SaxEventLogger l;
1187    CHECK(json::sax_parse(v, &l));
1188    CHECK(l.events.size() == 1);
1189}
1190