1c5f01b2fSopenharmony_ci//     __ _____ _____ _____
2c5f01b2fSopenharmony_ci//  __|  |   __|     |   | |  JSON for Modern C++ (supporting code)
3c5f01b2fSopenharmony_ci// |  |  |__   |  |  | | | |  version 3.11.2
4c5f01b2fSopenharmony_ci// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
5c5f01b2fSopenharmony_ci//
6c5f01b2fSopenharmony_ci// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
7c5f01b2fSopenharmony_ci// SPDX-License-Identifier: MIT
8c5f01b2fSopenharmony_ci
9c5f01b2fSopenharmony_ci#include "doctest_compatibility.h"
10c5f01b2fSopenharmony_ci
11c5f01b2fSopenharmony_ci// for some reason including this after the json header leads to linker errors with VS 2017...
12c5f01b2fSopenharmony_ci#include <locale>
13c5f01b2fSopenharmony_ci
14c5f01b2fSopenharmony_ci#include <nlohmann/json.hpp>
15c5f01b2fSopenharmony_ciusing nlohmann::json;
16c5f01b2fSopenharmony_ci
17c5f01b2fSopenharmony_ci#include <fstream>
18c5f01b2fSopenharmony_ci#include <sstream>
19c5f01b2fSopenharmony_ci#include <iostream>
20c5f01b2fSopenharmony_ci#include <iomanip>
21c5f01b2fSopenharmony_ci#include "make_test_data_available.hpp"
22c5f01b2fSopenharmony_ci
23c5f01b2fSopenharmony_ci// this test suite uses static variables with non-trivial destructors
24c5f01b2fSopenharmony_ciDOCTEST_CLANG_SUPPRESS_WARNING_PUSH
25c5f01b2fSopenharmony_ciDOCTEST_CLANG_SUPPRESS_WARNING("-Wexit-time-destructors")
26c5f01b2fSopenharmony_ci
27c5f01b2fSopenharmony_cinamespace
28c5f01b2fSopenharmony_ci{
29c5f01b2fSopenharmony_ciextern size_t calls;
30c5f01b2fSopenharmony_cisize_t calls = 0;
31c5f01b2fSopenharmony_ci
32c5f01b2fSopenharmony_civoid check_utf8dump(bool success_expected, int byte1, int byte2, int byte3, int byte4);
33c5f01b2fSopenharmony_ci
34c5f01b2fSopenharmony_civoid check_utf8dump(bool success_expected, int byte1, int byte2 = -1, int byte3 = -1, int byte4 = -1)
35c5f01b2fSopenharmony_ci{
36c5f01b2fSopenharmony_ci    static std::string json_string;
37c5f01b2fSopenharmony_ci    json_string.clear();
38c5f01b2fSopenharmony_ci
39c5f01b2fSopenharmony_ci    CAPTURE(byte1)
40c5f01b2fSopenharmony_ci    CAPTURE(byte2)
41c5f01b2fSopenharmony_ci    CAPTURE(byte3)
42c5f01b2fSopenharmony_ci    CAPTURE(byte4)
43c5f01b2fSopenharmony_ci
44c5f01b2fSopenharmony_ci    json_string += std::string(1, static_cast<char>(byte1));
45c5f01b2fSopenharmony_ci
46c5f01b2fSopenharmony_ci    if (byte2 != -1)
47c5f01b2fSopenharmony_ci    {
48c5f01b2fSopenharmony_ci        json_string += std::string(1, static_cast<char>(byte2));
49c5f01b2fSopenharmony_ci    }
50c5f01b2fSopenharmony_ci
51c5f01b2fSopenharmony_ci    if (byte3 != -1)
52c5f01b2fSopenharmony_ci    {
53c5f01b2fSopenharmony_ci        json_string += std::string(1, static_cast<char>(byte3));
54c5f01b2fSopenharmony_ci    }
55c5f01b2fSopenharmony_ci
56c5f01b2fSopenharmony_ci    if (byte4 != -1)
57c5f01b2fSopenharmony_ci    {
58c5f01b2fSopenharmony_ci        json_string += std::string(1, static_cast<char>(byte4));
59c5f01b2fSopenharmony_ci    }
60c5f01b2fSopenharmony_ci
61c5f01b2fSopenharmony_ci    CAPTURE(json_string)
62c5f01b2fSopenharmony_ci
63c5f01b2fSopenharmony_ci    // store the string in a JSON value
64c5f01b2fSopenharmony_ci    static json j;
65c5f01b2fSopenharmony_ci    static json j2;
66c5f01b2fSopenharmony_ci    j = json_string;
67c5f01b2fSopenharmony_ci    j2 = "abc" + json_string + "xyz";
68c5f01b2fSopenharmony_ci
69c5f01b2fSopenharmony_ci    static std::string s_ignored;
70c5f01b2fSopenharmony_ci    static std::string s_ignored2;
71c5f01b2fSopenharmony_ci    static std::string s_ignored_ascii;
72c5f01b2fSopenharmony_ci    static std::string s_ignored2_ascii;
73c5f01b2fSopenharmony_ci    static std::string s_replaced;
74c5f01b2fSopenharmony_ci    static std::string s_replaced2;
75c5f01b2fSopenharmony_ci    static std::string s_replaced_ascii;
76c5f01b2fSopenharmony_ci    static std::string s_replaced2_ascii;
77c5f01b2fSopenharmony_ci
78c5f01b2fSopenharmony_ci    // dumping with ignore/replace must not throw in any case
79c5f01b2fSopenharmony_ci    s_ignored = j.dump(-1, ' ', false, json::error_handler_t::ignore);
80c5f01b2fSopenharmony_ci    s_ignored2 = j2.dump(-1, ' ', false, json::error_handler_t::ignore);
81c5f01b2fSopenharmony_ci    s_ignored_ascii = j.dump(-1, ' ', true, json::error_handler_t::ignore);
82c5f01b2fSopenharmony_ci    s_ignored2_ascii = j2.dump(-1, ' ', true, json::error_handler_t::ignore);
83c5f01b2fSopenharmony_ci    s_replaced = j.dump(-1, ' ', false, json::error_handler_t::replace);
84c5f01b2fSopenharmony_ci    s_replaced2 = j2.dump(-1, ' ', false, json::error_handler_t::replace);
85c5f01b2fSopenharmony_ci    s_replaced_ascii = j.dump(-1, ' ', true, json::error_handler_t::replace);
86c5f01b2fSopenharmony_ci    s_replaced2_ascii = j2.dump(-1, ' ', true, json::error_handler_t::replace);
87c5f01b2fSopenharmony_ci
88c5f01b2fSopenharmony_ci    if (success_expected)
89c5f01b2fSopenharmony_ci    {
90c5f01b2fSopenharmony_ci        static std::string s_strict;
91c5f01b2fSopenharmony_ci        // strict mode must not throw if success is expected
92c5f01b2fSopenharmony_ci        s_strict = j.dump();
93c5f01b2fSopenharmony_ci        // all dumps should agree on the string
94c5f01b2fSopenharmony_ci        CHECK(s_strict == s_ignored);
95c5f01b2fSopenharmony_ci        CHECK(s_strict == s_replaced);
96c5f01b2fSopenharmony_ci    }
97c5f01b2fSopenharmony_ci    else
98c5f01b2fSopenharmony_ci    {
99c5f01b2fSopenharmony_ci        // strict mode must throw if success is not expected
100c5f01b2fSopenharmony_ci        CHECK_THROWS_AS(j.dump(), json::type_error&);
101c5f01b2fSopenharmony_ci        // ignore and replace must create different dumps
102c5f01b2fSopenharmony_ci        CHECK(s_ignored != s_replaced);
103c5f01b2fSopenharmony_ci
104c5f01b2fSopenharmony_ci        // check that replace string contains a replacement character
105c5f01b2fSopenharmony_ci        CHECK(s_replaced.find("\xEF\xBF\xBD") != std::string::npos);
106c5f01b2fSopenharmony_ci    }
107c5f01b2fSopenharmony_ci
108c5f01b2fSopenharmony_ci    // check that prefix and suffix are preserved
109c5f01b2fSopenharmony_ci    CHECK(s_ignored2.substr(1, 3) == "abc");
110c5f01b2fSopenharmony_ci    CHECK(s_ignored2.substr(s_ignored2.size() - 4, 3) == "xyz");
111c5f01b2fSopenharmony_ci    CHECK(s_ignored2_ascii.substr(1, 3) == "abc");
112c5f01b2fSopenharmony_ci    CHECK(s_ignored2_ascii.substr(s_ignored2_ascii.size() - 4, 3) == "xyz");
113c5f01b2fSopenharmony_ci    CHECK(s_replaced2.substr(1, 3) == "abc");
114c5f01b2fSopenharmony_ci    CHECK(s_replaced2.substr(s_replaced2.size() - 4, 3) == "xyz");
115c5f01b2fSopenharmony_ci    CHECK(s_replaced2_ascii.substr(1, 3) == "abc");
116c5f01b2fSopenharmony_ci    CHECK(s_replaced2_ascii.substr(s_replaced2_ascii.size() - 4, 3) == "xyz");
117c5f01b2fSopenharmony_ci}
118c5f01b2fSopenharmony_ci
119c5f01b2fSopenharmony_civoid check_utf8string(bool success_expected, int byte1, int byte2, int byte3, int byte4);
120c5f01b2fSopenharmony_ci
121c5f01b2fSopenharmony_ci// create and check a JSON string with up to four UTF-8 bytes
122c5f01b2fSopenharmony_civoid check_utf8string(bool success_expected, int byte1, int byte2 = -1, int byte3 = -1, int byte4 = -1)
123c5f01b2fSopenharmony_ci{
124c5f01b2fSopenharmony_ci    if (++calls % 100000 == 0)
125c5f01b2fSopenharmony_ci    {
126c5f01b2fSopenharmony_ci        std::cout << calls << " of 455355 UTF-8 strings checked" << std::endl;
127c5f01b2fSopenharmony_ci    }
128c5f01b2fSopenharmony_ci
129c5f01b2fSopenharmony_ci    static std::string json_string;
130c5f01b2fSopenharmony_ci    json_string = "\"";
131c5f01b2fSopenharmony_ci
132c5f01b2fSopenharmony_ci    CAPTURE(byte1)
133c5f01b2fSopenharmony_ci    json_string += std::string(1, static_cast<char>(byte1));
134c5f01b2fSopenharmony_ci
135c5f01b2fSopenharmony_ci    if (byte2 != -1)
136c5f01b2fSopenharmony_ci    {
137c5f01b2fSopenharmony_ci        CAPTURE(byte2)
138c5f01b2fSopenharmony_ci        json_string += std::string(1, static_cast<char>(byte2));
139c5f01b2fSopenharmony_ci    }
140c5f01b2fSopenharmony_ci
141c5f01b2fSopenharmony_ci    if (byte3 != -1)
142c5f01b2fSopenharmony_ci    {
143c5f01b2fSopenharmony_ci        CAPTURE(byte3)
144c5f01b2fSopenharmony_ci        json_string += std::string(1, static_cast<char>(byte3));
145c5f01b2fSopenharmony_ci    }
146c5f01b2fSopenharmony_ci
147c5f01b2fSopenharmony_ci    if (byte4 != -1)
148c5f01b2fSopenharmony_ci    {
149c5f01b2fSopenharmony_ci        CAPTURE(byte4)
150c5f01b2fSopenharmony_ci        json_string += std::string(1, static_cast<char>(byte4));
151c5f01b2fSopenharmony_ci    }
152c5f01b2fSopenharmony_ci
153c5f01b2fSopenharmony_ci    json_string += "\"";
154c5f01b2fSopenharmony_ci
155c5f01b2fSopenharmony_ci    CAPTURE(json_string)
156c5f01b2fSopenharmony_ci
157c5f01b2fSopenharmony_ci    json _;
158c5f01b2fSopenharmony_ci    if (success_expected)
159c5f01b2fSopenharmony_ci    {
160c5f01b2fSopenharmony_ci        CHECK_NOTHROW(_ = json::parse(json_string));
161c5f01b2fSopenharmony_ci    }
162c5f01b2fSopenharmony_ci    else
163c5f01b2fSopenharmony_ci    {
164c5f01b2fSopenharmony_ci        CHECK_THROWS_AS(_ = json::parse(json_string), json::parse_error&);
165c5f01b2fSopenharmony_ci    }
166c5f01b2fSopenharmony_ci}
167c5f01b2fSopenharmony_ci} // namespace
168c5f01b2fSopenharmony_ci
169c5f01b2fSopenharmony_ciTEST_CASE("Unicode (2/5)" * doctest::skip())
170c5f01b2fSopenharmony_ci{
171c5f01b2fSopenharmony_ci    SECTION("RFC 3629")
172c5f01b2fSopenharmony_ci    {
173c5f01b2fSopenharmony_ci        /*
174c5f01b2fSopenharmony_ci        RFC 3629 describes in Sect. 4 the syntax of UTF-8 byte sequences as
175c5f01b2fSopenharmony_ci        follows:
176c5f01b2fSopenharmony_ci
177c5f01b2fSopenharmony_ci            A UTF-8 string is a sequence of octets representing a sequence of UCS
178c5f01b2fSopenharmony_ci            characters.  An octet sequence is valid UTF-8 only if it matches the
179c5f01b2fSopenharmony_ci            following syntax, which is derived from the rules for encoding UTF-8
180c5f01b2fSopenharmony_ci            and is expressed in the ABNF of [RFC2234].
181c5f01b2fSopenharmony_ci
182c5f01b2fSopenharmony_ci            UTF8-octets = *( UTF8-char )
183c5f01b2fSopenharmony_ci            UTF8-char   = UTF8-1 / UTF8-2 / UTF8-3 / UTF8-4
184c5f01b2fSopenharmony_ci            UTF8-1      = %x00-7F
185c5f01b2fSopenharmony_ci            UTF8-2      = %xC2-DF UTF8-tail
186c5f01b2fSopenharmony_ci            UTF8-3      = %xE0 %xA0-BF UTF8-tail / %xE1-EC 2( UTF8-tail ) /
187c5f01b2fSopenharmony_ci                          %xED %x80-9F UTF8-tail / %xEE-EF 2( UTF8-tail )
188c5f01b2fSopenharmony_ci            UTF8-4      = %xF0 %x90-BF 2( UTF8-tail ) / %xF1-F3 3( UTF8-tail ) /
189c5f01b2fSopenharmony_ci                          %xF4 %x80-8F 2( UTF8-tail )
190c5f01b2fSopenharmony_ci            UTF8-tail   = %x80-BF
191c5f01b2fSopenharmony_ci        */
192c5f01b2fSopenharmony_ci
193c5f01b2fSopenharmony_ci        SECTION("ill-formed first byte")
194c5f01b2fSopenharmony_ci        {
195c5f01b2fSopenharmony_ci            for (int byte1 = 0x80; byte1 <= 0xC1; ++byte1)
196c5f01b2fSopenharmony_ci            {
197c5f01b2fSopenharmony_ci                check_utf8string(false, byte1);
198c5f01b2fSopenharmony_ci                check_utf8dump(false, byte1);
199c5f01b2fSopenharmony_ci            }
200c5f01b2fSopenharmony_ci
201c5f01b2fSopenharmony_ci            for (int byte1 = 0xF5; byte1 <= 0xFF; ++byte1)
202c5f01b2fSopenharmony_ci            {
203c5f01b2fSopenharmony_ci                check_utf8string(false, byte1);
204c5f01b2fSopenharmony_ci                check_utf8dump(false, byte1);
205c5f01b2fSopenharmony_ci            }
206c5f01b2fSopenharmony_ci        }
207c5f01b2fSopenharmony_ci
208c5f01b2fSopenharmony_ci        SECTION("UTF8-1 (x00-x7F)")
209c5f01b2fSopenharmony_ci        {
210c5f01b2fSopenharmony_ci            SECTION("well-formed")
211c5f01b2fSopenharmony_ci            {
212c5f01b2fSopenharmony_ci                for (int byte1 = 0x00; byte1 <= 0x7F; ++byte1)
213c5f01b2fSopenharmony_ci                {
214c5f01b2fSopenharmony_ci                    // unescaped control characters are parse errors in JSON
215c5f01b2fSopenharmony_ci                    if (0x00 <= byte1 && byte1 <= 0x1F)
216c5f01b2fSopenharmony_ci                    {
217c5f01b2fSopenharmony_ci                        check_utf8string(false, byte1);
218c5f01b2fSopenharmony_ci                        continue;
219c5f01b2fSopenharmony_ci                    }
220c5f01b2fSopenharmony_ci
221c5f01b2fSopenharmony_ci                    // a single quote is a parse error in JSON
222c5f01b2fSopenharmony_ci                    if (byte1 == 0x22)
223c5f01b2fSopenharmony_ci                    {
224c5f01b2fSopenharmony_ci                        check_utf8string(false, byte1);
225c5f01b2fSopenharmony_ci                        continue;
226c5f01b2fSopenharmony_ci                    }
227c5f01b2fSopenharmony_ci
228c5f01b2fSopenharmony_ci                    // a single backslash is a parse error in JSON
229c5f01b2fSopenharmony_ci                    if (byte1 == 0x5C)
230c5f01b2fSopenharmony_ci                    {
231c5f01b2fSopenharmony_ci                        check_utf8string(false, byte1);
232c5f01b2fSopenharmony_ci                        continue;
233c5f01b2fSopenharmony_ci                    }
234c5f01b2fSopenharmony_ci
235c5f01b2fSopenharmony_ci                    // all other characters are OK
236c5f01b2fSopenharmony_ci                    check_utf8string(true, byte1);
237c5f01b2fSopenharmony_ci                    check_utf8dump(true, byte1);
238c5f01b2fSopenharmony_ci                }
239c5f01b2fSopenharmony_ci            }
240c5f01b2fSopenharmony_ci        }
241c5f01b2fSopenharmony_ci
242c5f01b2fSopenharmony_ci        SECTION("UTF8-2 (xC2-xDF UTF8-tail)")
243c5f01b2fSopenharmony_ci        {
244c5f01b2fSopenharmony_ci            SECTION("well-formed")
245c5f01b2fSopenharmony_ci            {
246c5f01b2fSopenharmony_ci                for (int byte1 = 0xC2; byte1 <= 0xDF; ++byte1)
247c5f01b2fSopenharmony_ci                {
248c5f01b2fSopenharmony_ci                    for (int byte2 = 0x80; byte2 <= 0xBF; ++byte2)
249c5f01b2fSopenharmony_ci                    {
250c5f01b2fSopenharmony_ci                        check_utf8string(true, byte1, byte2);
251c5f01b2fSopenharmony_ci                        check_utf8dump(true, byte1, byte2);
252c5f01b2fSopenharmony_ci                    }
253c5f01b2fSopenharmony_ci                }
254c5f01b2fSopenharmony_ci            }
255c5f01b2fSopenharmony_ci
256c5f01b2fSopenharmony_ci            SECTION("ill-formed: missing second byte")
257c5f01b2fSopenharmony_ci            {
258c5f01b2fSopenharmony_ci                for (int byte1 = 0xC2; byte1 <= 0xDF; ++byte1)
259c5f01b2fSopenharmony_ci                {
260c5f01b2fSopenharmony_ci                    check_utf8string(false, byte1);
261c5f01b2fSopenharmony_ci                    check_utf8dump(false, byte1);
262c5f01b2fSopenharmony_ci                }
263c5f01b2fSopenharmony_ci            }
264c5f01b2fSopenharmony_ci
265c5f01b2fSopenharmony_ci            SECTION("ill-formed: wrong second byte")
266c5f01b2fSopenharmony_ci            {
267c5f01b2fSopenharmony_ci                for (int byte1 = 0xC2; byte1 <= 0xDF; ++byte1)
268c5f01b2fSopenharmony_ci                {
269c5f01b2fSopenharmony_ci                    for (int byte2 = 0x00; byte2 <= 0xFF; ++byte2)
270c5f01b2fSopenharmony_ci                    {
271c5f01b2fSopenharmony_ci                        // skip correct second byte
272c5f01b2fSopenharmony_ci                        if (0x80 <= byte2 && byte2 <= 0xBF)
273c5f01b2fSopenharmony_ci                        {
274c5f01b2fSopenharmony_ci                            continue;
275c5f01b2fSopenharmony_ci                        }
276c5f01b2fSopenharmony_ci
277c5f01b2fSopenharmony_ci                        check_utf8string(false, byte1, byte2);
278c5f01b2fSopenharmony_ci                        check_utf8dump(false, byte1, byte2);
279c5f01b2fSopenharmony_ci                    }
280c5f01b2fSopenharmony_ci                }
281c5f01b2fSopenharmony_ci            }
282c5f01b2fSopenharmony_ci        }
283c5f01b2fSopenharmony_ci
284c5f01b2fSopenharmony_ci        SECTION("UTF8-3 (xE0 xA0-BF UTF8-tail)")
285c5f01b2fSopenharmony_ci        {
286c5f01b2fSopenharmony_ci            SECTION("well-formed")
287c5f01b2fSopenharmony_ci            {
288c5f01b2fSopenharmony_ci                for (int byte1 = 0xE0; byte1 <= 0xE0; ++byte1)
289c5f01b2fSopenharmony_ci                {
290c5f01b2fSopenharmony_ci                    for (int byte2 = 0xA0; byte2 <= 0xBF; ++byte2)
291c5f01b2fSopenharmony_ci                    {
292c5f01b2fSopenharmony_ci                        for (int byte3 = 0x80; byte3 <= 0xBF; ++byte3)
293c5f01b2fSopenharmony_ci                        {
294c5f01b2fSopenharmony_ci                            check_utf8string(true, byte1, byte2, byte3);
295c5f01b2fSopenharmony_ci                            check_utf8dump(true, byte1, byte2, byte3);
296c5f01b2fSopenharmony_ci                        }
297c5f01b2fSopenharmony_ci                    }
298c5f01b2fSopenharmony_ci                }
299c5f01b2fSopenharmony_ci            }
300c5f01b2fSopenharmony_ci
301c5f01b2fSopenharmony_ci            SECTION("ill-formed: missing second byte")
302c5f01b2fSopenharmony_ci            {
303c5f01b2fSopenharmony_ci                for (int byte1 = 0xE0; byte1 <= 0xE0; ++byte1)
304c5f01b2fSopenharmony_ci                {
305c5f01b2fSopenharmony_ci                    check_utf8string(false, byte1);
306c5f01b2fSopenharmony_ci                    check_utf8dump(false, byte1);
307c5f01b2fSopenharmony_ci                }
308c5f01b2fSopenharmony_ci            }
309c5f01b2fSopenharmony_ci
310c5f01b2fSopenharmony_ci            SECTION("ill-formed: missing third byte")
311c5f01b2fSopenharmony_ci            {
312c5f01b2fSopenharmony_ci                for (int byte1 = 0xE0; byte1 <= 0xE0; ++byte1)
313c5f01b2fSopenharmony_ci                {
314c5f01b2fSopenharmony_ci                    for (int byte2 = 0xA0; byte2 <= 0xBF; ++byte2)
315c5f01b2fSopenharmony_ci                    {
316c5f01b2fSopenharmony_ci                        check_utf8string(false, byte1, byte2);
317c5f01b2fSopenharmony_ci                        check_utf8dump(false, byte1, byte2);
318c5f01b2fSopenharmony_ci                    }
319c5f01b2fSopenharmony_ci                }
320c5f01b2fSopenharmony_ci            }
321c5f01b2fSopenharmony_ci
322c5f01b2fSopenharmony_ci            SECTION("ill-formed: wrong second byte")
323c5f01b2fSopenharmony_ci            {
324c5f01b2fSopenharmony_ci                for (int byte1 = 0xE0; byte1 <= 0xE0; ++byte1)
325c5f01b2fSopenharmony_ci                {
326c5f01b2fSopenharmony_ci                    for (int byte2 = 0x00; byte2 <= 0xFF; ++byte2)
327c5f01b2fSopenharmony_ci                    {
328c5f01b2fSopenharmony_ci                        // skip correct second byte
329c5f01b2fSopenharmony_ci                        if (0xA0 <= byte2 && byte2 <= 0xBF)
330c5f01b2fSopenharmony_ci                        {
331c5f01b2fSopenharmony_ci                            continue;
332c5f01b2fSopenharmony_ci                        }
333c5f01b2fSopenharmony_ci
334c5f01b2fSopenharmony_ci                        for (int byte3 = 0x80; byte3 <= 0xBF; ++byte3)
335c5f01b2fSopenharmony_ci                        {
336c5f01b2fSopenharmony_ci                            check_utf8string(false, byte1, byte2, byte3);
337c5f01b2fSopenharmony_ci                            check_utf8dump(false, byte1, byte2, byte3);
338c5f01b2fSopenharmony_ci                        }
339c5f01b2fSopenharmony_ci                    }
340c5f01b2fSopenharmony_ci                }
341c5f01b2fSopenharmony_ci            }
342c5f01b2fSopenharmony_ci
343c5f01b2fSopenharmony_ci            SECTION("ill-formed: wrong third byte")
344c5f01b2fSopenharmony_ci            {
345c5f01b2fSopenharmony_ci                for (int byte1 = 0xE0; byte1 <= 0xE0; ++byte1)
346c5f01b2fSopenharmony_ci                {
347c5f01b2fSopenharmony_ci                    for (int byte2 = 0xA0; byte2 <= 0xBF; ++byte2)
348c5f01b2fSopenharmony_ci                    {
349c5f01b2fSopenharmony_ci                        for (int byte3 = 0x00; byte3 <= 0xFF; ++byte3)
350c5f01b2fSopenharmony_ci                        {
351c5f01b2fSopenharmony_ci                            // skip correct third byte
352c5f01b2fSopenharmony_ci                            if (0x80 <= byte3 && byte3 <= 0xBF)
353c5f01b2fSopenharmony_ci                            {
354c5f01b2fSopenharmony_ci                                continue;
355c5f01b2fSopenharmony_ci                            }
356c5f01b2fSopenharmony_ci
357c5f01b2fSopenharmony_ci                            check_utf8string(false, byte1, byte2, byte3);
358c5f01b2fSopenharmony_ci                            check_utf8dump(false, byte1, byte2, byte3);
359c5f01b2fSopenharmony_ci                        }
360c5f01b2fSopenharmony_ci                    }
361c5f01b2fSopenharmony_ci                }
362c5f01b2fSopenharmony_ci            }
363c5f01b2fSopenharmony_ci        }
364c5f01b2fSopenharmony_ci
365c5f01b2fSopenharmony_ci        SECTION("UTF8-3 (xE1-xEC UTF8-tail UTF8-tail)")
366c5f01b2fSopenharmony_ci        {
367c5f01b2fSopenharmony_ci            SECTION("well-formed")
368c5f01b2fSopenharmony_ci            {
369c5f01b2fSopenharmony_ci                for (int byte1 = 0xE1; byte1 <= 0xEC; ++byte1)
370c5f01b2fSopenharmony_ci                {
371c5f01b2fSopenharmony_ci                    for (int byte2 = 0x80; byte2 <= 0xBF; ++byte2)
372c5f01b2fSopenharmony_ci                    {
373c5f01b2fSopenharmony_ci                        for (int byte3 = 0x80; byte3 <= 0xBF; ++byte3)
374c5f01b2fSopenharmony_ci                        {
375c5f01b2fSopenharmony_ci                            check_utf8string(true, byte1, byte2, byte3);
376c5f01b2fSopenharmony_ci                            check_utf8dump(true, byte1, byte2, byte3);
377c5f01b2fSopenharmony_ci                        }
378c5f01b2fSopenharmony_ci                    }
379c5f01b2fSopenharmony_ci                }
380c5f01b2fSopenharmony_ci            }
381c5f01b2fSopenharmony_ci
382c5f01b2fSopenharmony_ci            SECTION("ill-formed: missing second byte")
383c5f01b2fSopenharmony_ci            {
384c5f01b2fSopenharmony_ci                for (int byte1 = 0xE1; byte1 <= 0xEC; ++byte1)
385c5f01b2fSopenharmony_ci                {
386c5f01b2fSopenharmony_ci                    check_utf8string(false, byte1);
387c5f01b2fSopenharmony_ci                    check_utf8dump(false, byte1);
388c5f01b2fSopenharmony_ci                }
389c5f01b2fSopenharmony_ci            }
390c5f01b2fSopenharmony_ci
391c5f01b2fSopenharmony_ci            SECTION("ill-formed: missing third byte")
392c5f01b2fSopenharmony_ci            {
393c5f01b2fSopenharmony_ci                for (int byte1 = 0xE1; byte1 <= 0xEC; ++byte1)
394c5f01b2fSopenharmony_ci                {
395c5f01b2fSopenharmony_ci                    for (int byte2 = 0x80; byte2 <= 0xBF; ++byte2)
396c5f01b2fSopenharmony_ci                    {
397c5f01b2fSopenharmony_ci                        check_utf8string(false, byte1, byte2);
398c5f01b2fSopenharmony_ci                        check_utf8dump(false, byte1, byte2);
399c5f01b2fSopenharmony_ci                    }
400c5f01b2fSopenharmony_ci                }
401c5f01b2fSopenharmony_ci            }
402c5f01b2fSopenharmony_ci
403c5f01b2fSopenharmony_ci            SECTION("ill-formed: wrong second byte")
404c5f01b2fSopenharmony_ci            {
405c5f01b2fSopenharmony_ci                for (int byte1 = 0xE1; byte1 <= 0xEC; ++byte1)
406c5f01b2fSopenharmony_ci                {
407c5f01b2fSopenharmony_ci                    for (int byte2 = 0x00; byte2 <= 0xFF; ++byte2)
408c5f01b2fSopenharmony_ci                    {
409c5f01b2fSopenharmony_ci                        // skip correct second byte
410c5f01b2fSopenharmony_ci                        if (0x80 <= byte2 && byte2 <= 0xBF)
411c5f01b2fSopenharmony_ci                        {
412c5f01b2fSopenharmony_ci                            continue;
413c5f01b2fSopenharmony_ci                        }
414c5f01b2fSopenharmony_ci
415c5f01b2fSopenharmony_ci                        for (int byte3 = 0x80; byte3 <= 0xBF; ++byte3)
416c5f01b2fSopenharmony_ci                        {
417c5f01b2fSopenharmony_ci                            check_utf8string(false, byte1, byte2, byte3);
418c5f01b2fSopenharmony_ci                            check_utf8dump(false, byte1, byte2, byte3);
419c5f01b2fSopenharmony_ci                        }
420c5f01b2fSopenharmony_ci                    }
421c5f01b2fSopenharmony_ci                }
422c5f01b2fSopenharmony_ci            }
423c5f01b2fSopenharmony_ci
424c5f01b2fSopenharmony_ci            SECTION("ill-formed: wrong third byte")
425c5f01b2fSopenharmony_ci            {
426c5f01b2fSopenharmony_ci                for (int byte1 = 0xE1; byte1 <= 0xEC; ++byte1)
427c5f01b2fSopenharmony_ci                {
428c5f01b2fSopenharmony_ci                    for (int byte2 = 0x80; byte2 <= 0xBF; ++byte2)
429c5f01b2fSopenharmony_ci                    {
430c5f01b2fSopenharmony_ci                        for (int byte3 = 0x00; byte3 <= 0xFF; ++byte3)
431c5f01b2fSopenharmony_ci                        {
432c5f01b2fSopenharmony_ci                            // skip correct third byte
433c5f01b2fSopenharmony_ci                            if (0x80 <= byte3 && byte3 <= 0xBF)
434c5f01b2fSopenharmony_ci                            {
435c5f01b2fSopenharmony_ci                                continue;
436c5f01b2fSopenharmony_ci                            }
437c5f01b2fSopenharmony_ci
438c5f01b2fSopenharmony_ci                            check_utf8string(false, byte1, byte2, byte3);
439c5f01b2fSopenharmony_ci                            check_utf8dump(false, byte1, byte2, byte3);
440c5f01b2fSopenharmony_ci                        }
441c5f01b2fSopenharmony_ci                    }
442c5f01b2fSopenharmony_ci                }
443c5f01b2fSopenharmony_ci            }
444c5f01b2fSopenharmony_ci        }
445c5f01b2fSopenharmony_ci
446c5f01b2fSopenharmony_ci        SECTION("UTF8-3 (xED x80-9F UTF8-tail)")
447c5f01b2fSopenharmony_ci        {
448c5f01b2fSopenharmony_ci            SECTION("well-formed")
449c5f01b2fSopenharmony_ci            {
450c5f01b2fSopenharmony_ci                for (int byte1 = 0xED; byte1 <= 0xED; ++byte1)
451c5f01b2fSopenharmony_ci                {
452c5f01b2fSopenharmony_ci                    for (int byte2 = 0x80; byte2 <= 0x9F; ++byte2)
453c5f01b2fSopenharmony_ci                    {
454c5f01b2fSopenharmony_ci                        for (int byte3 = 0x80; byte3 <= 0xBF; ++byte3)
455c5f01b2fSopenharmony_ci                        {
456c5f01b2fSopenharmony_ci                            check_utf8string(true, byte1, byte2, byte3);
457c5f01b2fSopenharmony_ci                            check_utf8dump(true, byte1, byte2, byte3);
458c5f01b2fSopenharmony_ci                        }
459c5f01b2fSopenharmony_ci                    }
460c5f01b2fSopenharmony_ci                }
461c5f01b2fSopenharmony_ci            }
462c5f01b2fSopenharmony_ci
463c5f01b2fSopenharmony_ci            SECTION("ill-formed: missing second byte")
464c5f01b2fSopenharmony_ci            {
465c5f01b2fSopenharmony_ci                for (int byte1 = 0xED; byte1 <= 0xED; ++byte1)
466c5f01b2fSopenharmony_ci                {
467c5f01b2fSopenharmony_ci                    check_utf8string(false, byte1);
468c5f01b2fSopenharmony_ci                    check_utf8dump(false, byte1);
469c5f01b2fSopenharmony_ci                }
470c5f01b2fSopenharmony_ci            }
471c5f01b2fSopenharmony_ci
472c5f01b2fSopenharmony_ci            SECTION("ill-formed: missing third byte")
473c5f01b2fSopenharmony_ci            {
474c5f01b2fSopenharmony_ci                for (int byte1 = 0xED; byte1 <= 0xED; ++byte1)
475c5f01b2fSopenharmony_ci                {
476c5f01b2fSopenharmony_ci                    for (int byte2 = 0x80; byte2 <= 0x9F; ++byte2)
477c5f01b2fSopenharmony_ci                    {
478c5f01b2fSopenharmony_ci                        check_utf8string(false, byte1, byte2);
479c5f01b2fSopenharmony_ci                        check_utf8dump(false, byte1, byte2);
480c5f01b2fSopenharmony_ci                    }
481c5f01b2fSopenharmony_ci                }
482c5f01b2fSopenharmony_ci            }
483c5f01b2fSopenharmony_ci
484c5f01b2fSopenharmony_ci            SECTION("ill-formed: wrong second byte")
485c5f01b2fSopenharmony_ci            {
486c5f01b2fSopenharmony_ci                for (int byte1 = 0xED; byte1 <= 0xED; ++byte1)
487c5f01b2fSopenharmony_ci                {
488c5f01b2fSopenharmony_ci                    for (int byte2 = 0x00; byte2 <= 0xFF; ++byte2)
489c5f01b2fSopenharmony_ci                    {
490c5f01b2fSopenharmony_ci                        // skip correct second byte
491c5f01b2fSopenharmony_ci                        if (0x80 <= byte2 && byte2 <= 0x9F)
492c5f01b2fSopenharmony_ci                        {
493c5f01b2fSopenharmony_ci                            continue;
494c5f01b2fSopenharmony_ci                        }
495c5f01b2fSopenharmony_ci
496c5f01b2fSopenharmony_ci                        for (int byte3 = 0x80; byte3 <= 0xBF; ++byte3)
497c5f01b2fSopenharmony_ci                        {
498c5f01b2fSopenharmony_ci                            check_utf8string(false, byte1, byte2, byte3);
499c5f01b2fSopenharmony_ci                            check_utf8dump(false, byte1, byte2, byte3);
500c5f01b2fSopenharmony_ci                        }
501c5f01b2fSopenharmony_ci                    }
502c5f01b2fSopenharmony_ci                }
503c5f01b2fSopenharmony_ci            }
504c5f01b2fSopenharmony_ci
505c5f01b2fSopenharmony_ci            SECTION("ill-formed: wrong third byte")
506c5f01b2fSopenharmony_ci            {
507c5f01b2fSopenharmony_ci                for (int byte1 = 0xED; byte1 <= 0xED; ++byte1)
508c5f01b2fSopenharmony_ci                {
509c5f01b2fSopenharmony_ci                    for (int byte2 = 0x80; byte2 <= 0x9F; ++byte2)
510c5f01b2fSopenharmony_ci                    {
511c5f01b2fSopenharmony_ci                        for (int byte3 = 0x00; byte3 <= 0xFF; ++byte3)
512c5f01b2fSopenharmony_ci                        {
513c5f01b2fSopenharmony_ci                            // skip correct third byte
514c5f01b2fSopenharmony_ci                            if (0x80 <= byte3 && byte3 <= 0xBF)
515c5f01b2fSopenharmony_ci                            {
516c5f01b2fSopenharmony_ci                                continue;
517c5f01b2fSopenharmony_ci                            }
518c5f01b2fSopenharmony_ci
519c5f01b2fSopenharmony_ci                            check_utf8string(false, byte1, byte2, byte3);
520c5f01b2fSopenharmony_ci                            check_utf8dump(false, byte1, byte2, byte3);
521c5f01b2fSopenharmony_ci                        }
522c5f01b2fSopenharmony_ci                    }
523c5f01b2fSopenharmony_ci                }
524c5f01b2fSopenharmony_ci            }
525c5f01b2fSopenharmony_ci        }
526c5f01b2fSopenharmony_ci
527c5f01b2fSopenharmony_ci        SECTION("UTF8-3 (xEE-xEF UTF8-tail UTF8-tail)")
528c5f01b2fSopenharmony_ci        {
529c5f01b2fSopenharmony_ci            SECTION("well-formed")
530c5f01b2fSopenharmony_ci            {
531c5f01b2fSopenharmony_ci                for (int byte1 = 0xEE; byte1 <= 0xEF; ++byte1)
532c5f01b2fSopenharmony_ci                {
533c5f01b2fSopenharmony_ci                    for (int byte2 = 0x80; byte2 <= 0xBF; ++byte2)
534c5f01b2fSopenharmony_ci                    {
535c5f01b2fSopenharmony_ci                        for (int byte3 = 0x80; byte3 <= 0xBF; ++byte3)
536c5f01b2fSopenharmony_ci                        {
537c5f01b2fSopenharmony_ci                            check_utf8string(true, byte1, byte2, byte3);
538c5f01b2fSopenharmony_ci                            check_utf8dump(true, byte1, byte2, byte3);
539c5f01b2fSopenharmony_ci                        }
540c5f01b2fSopenharmony_ci                    }
541c5f01b2fSopenharmony_ci                }
542c5f01b2fSopenharmony_ci            }
543c5f01b2fSopenharmony_ci
544c5f01b2fSopenharmony_ci            SECTION("ill-formed: missing second byte")
545c5f01b2fSopenharmony_ci            {
546c5f01b2fSopenharmony_ci                for (int byte1 = 0xEE; byte1 <= 0xEF; ++byte1)
547c5f01b2fSopenharmony_ci                {
548c5f01b2fSopenharmony_ci                    check_utf8string(false, byte1);
549c5f01b2fSopenharmony_ci                    check_utf8dump(false, byte1);
550c5f01b2fSopenharmony_ci                }
551c5f01b2fSopenharmony_ci            }
552c5f01b2fSopenharmony_ci
553c5f01b2fSopenharmony_ci            SECTION("ill-formed: missing third byte")
554c5f01b2fSopenharmony_ci            {
555c5f01b2fSopenharmony_ci                for (int byte1 = 0xEE; byte1 <= 0xEF; ++byte1)
556c5f01b2fSopenharmony_ci                {
557c5f01b2fSopenharmony_ci                    for (int byte2 = 0x80; byte2 <= 0xBF; ++byte2)
558c5f01b2fSopenharmony_ci                    {
559c5f01b2fSopenharmony_ci                        check_utf8string(false, byte1, byte2);
560c5f01b2fSopenharmony_ci                        check_utf8dump(false, byte1, byte2);
561c5f01b2fSopenharmony_ci                    }
562c5f01b2fSopenharmony_ci                }
563c5f01b2fSopenharmony_ci            }
564c5f01b2fSopenharmony_ci
565c5f01b2fSopenharmony_ci            SECTION("ill-formed: wrong second byte")
566c5f01b2fSopenharmony_ci            {
567c5f01b2fSopenharmony_ci                for (int byte1 = 0xEE; byte1 <= 0xEF; ++byte1)
568c5f01b2fSopenharmony_ci                {
569c5f01b2fSopenharmony_ci                    for (int byte2 = 0x00; byte2 <= 0xFF; ++byte2)
570c5f01b2fSopenharmony_ci                    {
571c5f01b2fSopenharmony_ci                        // skip correct second byte
572c5f01b2fSopenharmony_ci                        if (0x80 <= byte2 && byte2 <= 0xBF)
573c5f01b2fSopenharmony_ci                        {
574c5f01b2fSopenharmony_ci                            continue;
575c5f01b2fSopenharmony_ci                        }
576c5f01b2fSopenharmony_ci
577c5f01b2fSopenharmony_ci                        for (int byte3 = 0x80; byte3 <= 0xBF; ++byte3)
578c5f01b2fSopenharmony_ci                        {
579c5f01b2fSopenharmony_ci                            check_utf8string(false, byte1, byte2, byte3);
580c5f01b2fSopenharmony_ci                            check_utf8dump(false, byte1, byte2, byte3);
581c5f01b2fSopenharmony_ci                        }
582c5f01b2fSopenharmony_ci                    }
583c5f01b2fSopenharmony_ci                }
584c5f01b2fSopenharmony_ci            }
585c5f01b2fSopenharmony_ci
586c5f01b2fSopenharmony_ci            SECTION("ill-formed: wrong third byte")
587c5f01b2fSopenharmony_ci            {
588c5f01b2fSopenharmony_ci                for (int byte1 = 0xEE; byte1 <= 0xEF; ++byte1)
589c5f01b2fSopenharmony_ci                {
590c5f01b2fSopenharmony_ci                    for (int byte2 = 0x80; byte2 <= 0xBF; ++byte2)
591c5f01b2fSopenharmony_ci                    {
592c5f01b2fSopenharmony_ci                        for (int byte3 = 0x00; byte3 <= 0xFF; ++byte3)
593c5f01b2fSopenharmony_ci                        {
594c5f01b2fSopenharmony_ci                            // skip correct third byte
595c5f01b2fSopenharmony_ci                            if (0x80 <= byte3 && byte3 <= 0xBF)
596c5f01b2fSopenharmony_ci                            {
597c5f01b2fSopenharmony_ci                                continue;
598c5f01b2fSopenharmony_ci                            }
599c5f01b2fSopenharmony_ci
600c5f01b2fSopenharmony_ci                            check_utf8string(false, byte1, byte2, byte3);
601c5f01b2fSopenharmony_ci                            check_utf8dump(false, byte1, byte2, byte3);
602c5f01b2fSopenharmony_ci                        }
603c5f01b2fSopenharmony_ci                    }
604c5f01b2fSopenharmony_ci                }
605c5f01b2fSopenharmony_ci            }
606c5f01b2fSopenharmony_ci        }
607c5f01b2fSopenharmony_ci    }
608c5f01b2fSopenharmony_ci}
609c5f01b2fSopenharmony_ci
610c5f01b2fSopenharmony_ciDOCTEST_CLANG_SUPPRESS_WARNING_POP
611