NPF-01#

The service ignores the presence of a byte order mark.

Supported Requests:

Supporting Items:

References:

None

Fallacies:

None

Graph:

No Historic Data Found


NPF-01.1#

The service ignores the presence of a single UTF-8 byte order mark at the very beginning of the input.

Supported Requests:

Supporting Items:

None

References:

  • cpp-test: [Unicode (1/5);ignore byte-order-mark] (tests/src/unit-unicode1.cpp)

SECTION("ignore byte-order-mark")
{
    SECTION("in a stream")
    {
        // read a file with a UTF-8 BOM
        std::ifstream f(TEST_DATA_DIRECTORY "/json_nlohmann_tests/bom.json");
        json j;
        CHECK_NOTHROW(f >> j);
    }

    SECTION("with an iterator")
    {
        std::string i = "\xef\xbb\xbf{\n   \"foo\": true\n}";
        json _;
        CHECK_NOTHROW(_ = json::parse(i.begin(), i.end()));
    }
}
  • cpp-test: [deserialization;ignoring byte-order marks;BOM and content] (tests/src/unit-deserialization.cpp)

SECTION("BOM and content")
{
    CHECK(json::parse(bom + "1") == 1);
    CHECK(json::parse(std::istringstream(bom + "1")) == 1);

    SaxEventLogger l1;
    SaxEventLogger l2;
    CHECK(json::sax_parse(std::istringstream(bom + "1"), &l1));
    CHECK(json::sax_parse(bom + "1", &l2));
    CHECK(l1.events.size() == 1);
    CHECK(l1.events == std::vector<std::string>(
    {
        "number_unsigned(1)"
    }));
    CHECK(l2.events.size() == 1);
    CHECK(l2.events == std::vector<std::string>(
    {
        "number_unsigned(1)"
    }));
}

Fallacies:

None

Graph:

No Historic Data Found


NPF-01.2#

The service does not parse multiple UTF-8 byte order marks at the beginning of the input and throws an exception.

Supported Requests:

Supporting Items:

None

References:

  • cpp-test: [parse;UTF-8;multiple BOM] (TSF/tests/unit-byte_order_mark.cpp)

SECTION("multiple BOM")
{
    // Whenever a fourth character of a BOM-candidate is read, an error is thrown. 
    // This error does not depend on any trailing garbage.
    CHECK_THROWS_WITH_AS(parser_helper("\xEF\xBB\xBF\xEF\xBB\xBF"),"[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid literal; last read: '\xEF\xBB\xBF\xEF'", json::parse_error&);
    CHECK_THROWS_WITH_AS(parser_helper("\xEF\xBB\xBF\xEF\xBB\xBF\xEF\xBB\xBF"),"[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid literal; last read: '\xEF\xBB\xBF\xEF'", json::parse_error&);
    CHECK_THROWS_WITH_AS(parser_helper("\xEF\xBB\xBF\xEF\xBB\xBF\xEF\xBB\xBF\xEF\xBB\xBF"),"[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid literal; last read: '\xEF\xBB\xBF\xEF'", json::parse_error&);
    CHECK_THROWS_WITH_AS(parser_helper("\xEF\xBB\xBF\xEF\xBB"),"[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid literal; last read: '\xEF\xBB\xBF\xEF'", json::parse_error&);
    CHECK_THROWS_WITH_AS(parser_helper("\xEF\xBB\xBF\xEF foo"),"[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid literal; last read: '\xEF\xBB\xBF\xEF'", json::parse_error&);
}

Fallacies:

None

Graph:

No Historic Data Found


NPF-01.3#

The service does not parse UTF-8 byte order marks outside of a string and the first three characters of the input, and throws an exception.

Supported Requests:

Supporting Items:

None

References:

  • cpp-test: [parse;UTF-8;unexpected BOM] (TSF/tests/unit-byte_order_mark.cpp)

SECTION("unexpected BOM")
{
    // A byte order mark at any other position than the very first character is illegal and an error is thrown.
    CHECK_THROWS_AS(parser_helper(" \xEF\xBB\xBF"), json::parse_error&);
    CHECK_THROWS_AS(parser_helper("\t\xEF\xBB\xBF"), json::parse_error&);
    CHECK_THROWS_AS(parser_helper("\n\xEF\xBB\xBF"), json::parse_error&);
    CHECK_THROWS_AS(parser_helper("\xEF\xBB\xBF"), json::parse_error&);
    CHECK_THROWS_AS(parser_helper("\u000d\xEF\xBB\xBF"), json::parse_error&);
    CHECK_THROWS_AS(parser_helper("1\xEF\xBB\xBF"), json::parse_error&);
    CHECK_THROWS_AS(parser_helper("\"foo\"\xEF\xBB\xBF"), json::parse_error&);
    CHECK_THROWS_AS(parser_helper("[42]\xEF\xBB\xBF"), json::parse_error&);
    CHECK_THROWS_AS(parser_helper("{\"foo\":\"bar\"}\xEF\xBB\xBF"), json::parse_error&);
}

Fallacies:

None

Graph:

No Historic Data Found


NPF-01.4#

The service does not parse UTF-16 and UTF-32 byte order mark instead of an UTF-8 byte order mark, and throws an exception.

Supported Requests:

Supporting Items:

None

References:

  • cpp-test: [parse;other BOM] (TSF/tests/unit-byte_order_mark.cpp)

SECTION("other BOM")
{
    SECTION("UTF-16")
    {
        CHECK_THROWS_AS(parser_helper("\xFE\xFF\"foo\""),json::parse_error&);
        CHECK_THROWS_AS(parser_helper("\xFF\xFE\"foo\""),json::parse_error&);
    }
    SECTION("UTF-32")
    {
        const std::string utf32bom1("\x00\x00\xFE\xFF\x30", 5);
        const std::string utf32bom2("\xFF\xFE\x00\x00\x30", 5);
        CHECK_THROWS_AS(parser_helper(utf32bom1),json::parse_error&);
        CHECK_THROWS_AS(parser_helper(utf32bom2),json::parse_error&);
    }
}

Fallacies:

None

Graph:

No Historic Data Found


NPF-01.5#

The service does not parse partial and perturbed UTF-8 byte order marks within the first three characters of the input and throws an exception.

Supported Requests:

Supporting Items:

None

References:

  • cpp-test: [deserialization;ignoring byte-order marks;2 byte of BOM] (tests/src/unit-deserialization.cpp)

SECTION("2 byte of BOM")
{
    json _;
    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&);

    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&);

    SaxEventLogger l1;
    SaxEventLogger l2;
    CHECK(!json::sax_parse(std::istringstream(bom.substr(0, 2)), &l1));
    CHECK(!json::sax_parse(bom.substr(0, 2), &l2));
    CHECK(l1.events.size() == 1);
    CHECK(l1.events == std::vector<std::string>(
    {
        "parse_error(3)"
    }));
    CHECK(l2.events.size() == 1);
    CHECK(l2.events == std::vector<std::string>(
    {
        "parse_error(3)"
    }));
}
  • cpp-test: [deserialization;ignoring byte-order marks;1 byte of BOM] (tests/src/unit-deserialization.cpp)

SECTION("1 byte of BOM")
{
    json _;
    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&);

    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&);

    SaxEventLogger l1;
    SaxEventLogger l2;
    CHECK(!json::sax_parse(std::istringstream(bom.substr(0, 1)), &l1));
    CHECK(!json::sax_parse(bom.substr(0, 1), &l2));
    CHECK(l1.events.size() == 1);
    CHECK(l1.events == std::vector<std::string>(
    {
        "parse_error(2)"
    }));
    CHECK(l2.events.size() == 1);
    CHECK(l2.events == std::vector<std::string>(
    {
        "parse_error(2)"
    }));
}
  • cpp-test: [deserialization;ignoring byte-order marks;variations] (tests/src/unit-deserialization.cpp)

SECTION("variations")
{
    // calculate variations of each byte of the BOM to make sure
    // that the BOM and only the BOM is skipped
    for (int i0 = -1; i0 < 2; ++i0)
    {
        for (int i1 = -1; i1 < 2; ++i1)
        {
            for (int i2 = -1; i2 < 2; ++i2)
            {
                // debug output for the variations
                CAPTURE(i0)
                CAPTURE(i1)
                CAPTURE(i2)

                std::string s;
                s.push_back(static_cast<char>(bom[0] + i0));
                s.push_back(static_cast<char>(bom[1] + i1));
                s.push_back(static_cast<char>(bom[2] + i2));

                if (i0 == 0 && i1 == 0 && i2 == 0)
                {
                    // without any variation, we skip the BOM
                    CHECK(json::parse(s + "null") == json());
                    CHECK(json::parse(std::istringstream(s + "null")) == json());

                    SaxEventLogger l;
                    CHECK(json::sax_parse(s + "null", &l));
                    CHECK(l.events.size() == 1);
                    CHECK(l.events == std::vector<std::string>(
                    {
                        "null()"
                    }));
                }
                else
                {
                    // any variation is an error
                    json _;
                    CHECK_THROWS_AS(_ = json::parse(s + "null"), json::parse_error&);
                    CHECK_THROWS_AS(_ = json::parse(std::istringstream(s + "null")), json::parse_error&);

                    SaxEventLogger l;
                    CHECK(!json::sax_parse(s + "null", &l));
                    CHECK(l.events.size() == 1);

                    if (i0 != 0)
                    {
                        CHECK(l.events == std::vector<std::string>(
                        {
                            "parse_error(1)"
                        }));
                    }
                    else if (i1 != 0)
                    {
                        CHECK(l.events == std::vector<std::string>(
                        {
                            "parse_error(2)"
                        }));
                    }
                    else
                    {
                        CHECK(l.events == std::vector<std::string>(
                        {
                            "parse_error(3)"
                        }));
                    }
                }
            }
        }
    }
}
  • cpp-test: [Unicode (1/5);error for incomplete/wrong BOM] (tests/src/unit-unicode1.cpp)

SECTION("error for incomplete/wrong BOM")
{
    json _;
    CHECK_THROWS_AS(_ = json::parse("\xef\xbb"), json::parse_error&);
    CHECK_THROWS_AS(_ = json::parse("\xef\xbb\xbb"), json::parse_error&);
}

Fallacies:

None

Graph:

No Historic Data Found


NPF-02#

The service parses numbers according to RFC8259.

Supported Requests:

Supporting Items:

References:

  • function: [lexer::scan_number] (include/nlohmann/detail/input/lexer.hpp)

    • Description: function, which parses numbers into C++ number-types and verifies en passant that these numbers are in accordance with RFC8259

    token_type scan_number()  // lgtm [cpp/use-of-goto] `goto` is used in this function to implement the number-parsing state machine described above. By design, any finite input will eventually reach the "done" state or return token_type::parse_error. In each intermediate state, 1 byte of the input is appended to the token_buffer vector, and only the already initialized variables token_buffer, number_type, and error_message are manipulated.
    {
        // reset token_buffer to store the number's bytes
        reset();

        // the type of the parsed number; initially set to unsigned; will be
        // changed if minus sign, decimal point or exponent is read
        token_type number_type = token_type::value_unsigned;

        // state (init): we just found out we need to scan a number
        switch (current)
        {
            case '-':
            {
                add(current);
                goto scan_number_minus;
            }

            case '0':
            {
                add(current);
                goto scan_number_zero;
            }

            case '1':
            case '2':
            case '3':
            case '4':
            case '5':
            case '6':
            case '7':
            case '8':
            case '9':
            {
                add(current);
                goto scan_number_any1;
            }

            // all other characters are rejected outside scan_number()
            default:            // LCOV_EXCL_LINE
                JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
        }

scan_number_minus:
        // state: we just parsed a leading minus sign
        number_type = token_type::value_integer;
        switch (get())
        {
            case '0':
            {
                add(current);
                goto scan_number_zero;
            }

            case '1':
            case '2':
            case '3':
            case '4':
            case '5':
            case '6':
            case '7':
            case '8':
            case '9':
            {
                add(current);
                goto scan_number_any1;
            }

            default:
            {
                error_message = "invalid number; expected digit after '-'";
                return token_type::parse_error;
            }
        }

scan_number_zero:
        // state: we just parse a zero (maybe with a leading minus sign)
        switch (get())
        {
            case '.':
            {
                add(decimal_point_char);
                decimal_point_position = token_buffer.size() - 1;
                goto scan_number_decimal1;
            }

            case 'e':
            case 'E':
            {
                add(current);
                goto scan_number_exponent;
            }

            default:
                goto scan_number_done;
        }

scan_number_any1:
        // state: we just parsed a number 0-9 (maybe with a leading minus sign)
        switch (get())
        {
            case '0':
            case '1':
            case '2':
            case '3':
            case '4':
            case '5':
            case '6':
            case '7':
            case '8':
            case '9':
            {
                add(current);
                goto scan_number_any1;
            }

            case '.':
            {
                add(decimal_point_char);
                decimal_point_position = token_buffer.size() - 1;
                goto scan_number_decimal1;
            }

            case 'e':
            case 'E':
            {
                add(current);
                goto scan_number_exponent;
            }

            default:
                goto scan_number_done;
        }

scan_number_decimal1:
        // state: we just parsed a decimal point
        number_type = token_type::value_float;
        switch (get())
        {
            case '0':
            case '1':
            case '2':
            case '3':
            case '4':
            case '5':
            case '6':
            case '7':
            case '8':
            case '9':
            {
                add(current);
                goto scan_number_decimal2;
            }

            default:
            {
                error_message = "invalid number; expected digit after '.'";
                return token_type::parse_error;
            }
        }

scan_number_decimal2:
        // we just parsed at least one number after a decimal point
        switch (get())
        {
            case '0':
            case '1':
            case '2':
            case '3':
            case '4':
            case '5':
            case '6':
            case '7':
            case '8':
            case '9':
            {
                add(current);
                goto scan_number_decimal2;
            }

            case 'e':
            case 'E':
            {
                add(current);
                goto scan_number_exponent;
            }

            default:
                goto scan_number_done;
        }

scan_number_exponent:
        // we just parsed an exponent
        number_type = token_type::value_float;
        switch (get())
        {
            case '+':
            case '-':
            {
                add(current);
                goto scan_number_sign;
            }

            case '0':
            case '1':
            case '2':
            case '3':
            case '4':
            case '5':
            case '6':
            case '7':
            case '8':
            case '9':
            {
                add(current);
                goto scan_number_any2;
            }

            default:
            {
                error_message =
                    "invalid number; expected '+', '-', or digit after exponent";
                return token_type::parse_error;
            }
        }

scan_number_sign:
        // we just parsed an exponent sign
        switch (get())
        {
            case '0':
            case '1':
            case '2':
            case '3':
            case '4':
            case '5':
            case '6':
            case '7':
            case '8':
            case '9':
            {
                add(current);
                goto scan_number_any2;
            }

            default:
            {
                error_message = "invalid number; expected digit after exponent sign";
                return token_type::parse_error;
            }
        }

scan_number_any2:
        // we just parsed a number after the exponent or exponent sign
        switch (get())
        {
            case '0':
            case '1':
            case '2':
            case '3':
            case '4':
            case '5':
            case '6':
            case '7':
            case '8':
            case '9':
            {
                add(current);
                goto scan_number_any2;
            }

            default:
                goto scan_number_done;
        }

scan_number_done:
        // unget the character after the number (we only read it to know that
        // we are done scanning a number)
        unget();

        char* endptr = nullptr; // NOLINT(misc-const-correctness,cppcoreguidelines-pro-type-vararg,hicpp-vararg)
        errno = 0;

        // try to parse integers first and fall back to floats
        if (number_type == token_type::value_unsigned)
        {
            const auto x = std::strtoull(token_buffer.data(), &endptr, 10);

            // we checked the number format before
            JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());

            if (errno != ERANGE)
            {
                value_unsigned = static_cast<number_unsigned_t>(x);
                if (value_unsigned == x)
                {
                    return token_type::value_unsigned;
                }
            }
        }
        else if (number_type == token_type::value_integer)
        {
            const auto x = std::strtoll(token_buffer.data(), &endptr, 10);

            // we checked the number format before
            JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());

            if (errno != ERANGE)
            {
                value_integer = static_cast<number_integer_t>(x);
                if (value_integer == x)
                {
                    return token_type::value_integer;
                }
            }
        }

        // this code is reached if we parse a floating-point number or if an
        // integer conversion above failed
        strtof(value_float, token_buffer.data(), &endptr);

        // we checked the number format before
        JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());

        return token_type::value_float;
    }

Fallacies:

None

Graph:

No Historic Data Found


NPF-02.1#

The service parses integers without exponent within the precision of int64_t.

Supported Requests:

Supporting Items:

None

References:

  • cpp-test: [parser class - core;parse;number;floating-point;without exponent] (TSF/tests/unit-class_parser_core.cpp)

SECTION("without exponent")
{
    CHECK(parser_helper("-128.5") == json(-128.5));
    CHECK(parser_helper("0.999") == json(0.999));
    CHECK(parser_helper("128.5") == json(128.5));
    CHECK(parser_helper("-0.0") == json(-0.0));
}
  • cpp-test: [parser class - core;parse;number;integers;without exponent] (TSF/tests/unit-class_parser_core.cpp)

SECTION("without exponent")
{
    CHECK(parser_helper("-128") == json(-128));
    CHECK(parser_helper("-0") == json(-0));
    CHECK(parser_helper("0") == json(0));
    CHECK(parser_helper("128") == json(128));
}
  • cpp-testsuite: [/nst_json_testsuite2/test_parsing/y_number_simple_int.json, /nst_json_testsuite2/test_parsing/y_number_simple_real.json, /nst_json_testsuite2/test_parsing/y_number_negative_int.json, /nst_json_testsuite2/test_parsing/y_number_negative_one.json, /nst_json_testsuite2/test_parsing/y_number_negative_zero.json]

    • Description: Tests whether several numbers without exponent are parsed without throwing an exception.

    • JSON Testsuite: /nst_json_testsuite2/test_parsing/y_number_simple_int.json

    [123]
    
    • JSON Testsuite: /nst_json_testsuite2/test_parsing/y_number_simple_real.json

    [123.456789]
    
    • JSON Testsuite: /nst_json_testsuite2/test_parsing/y_number_negative_int.json

    [-123]
    
    • JSON Testsuite: /nst_json_testsuite2/test_parsing/y_number_negative_one.json

    [-1]
    
    • JSON Testsuite: /nst_json_testsuite2/test_parsing/y_number_negative_zero.json

    [-0]
    
    • cpp-test: [nst’s JSONTestSuite (2);test_parsing;y] (tests/src/unit-testsuites.cpp)

    SECTION("y")
    {
        for (const auto* filename :
                {
                    TEST_DATA_DIRECTORY "/nst_json_testsuite2/test_parsing/y_number_negative_int.json",
                    TEST_DATA_DIRECTORY "/nst_json_testsuite2/test_parsing/y_number_negative_one.json",
                    TEST_DATA_DIRECTORY "/nst_json_testsuite2/test_parsing/y_number_negative_zero.json",
                    TEST_DATA_DIRECTORY "/nst_json_testsuite2/test_parsing/y_number_simple_int.json",
                    TEST_DATA_DIRECTORY "/nst_json_testsuite2/test_parsing/y_number_simple_real.json",
                }
            )
        {
            CAPTURE(filename)
            std::ifstream f(filename);
            json _;
            CHECK_NOTHROW(_ = json::parse(f));
            std::ifstream f2(filename);
            CHECK(json::accept(f2));
        }
    }
    
    
     // Note: Other test data lines have been filtered out for conciseness.
    

Fallacies:

None

Graph:

No Historic Data Found


NPF-02.10#

The service ignores trailing zeroes after the decimal point.

Supported Requests:

Supporting Items:

None

References:

  • cpp-test: [regression tests 1;issue #379 - locale-independent str-to-num] (tests/src/unit-regression1.cpp)

SECTION("issue #379 - locale-independent str-to-num")
{
    static_cast<void>(setlocale(LC_NUMERIC, "de_DE.UTF-8"));

    // verify that parsed correctly despite using strtod internally
    CHECK(json::parse("3.14").get<double>() == 3.14);

    // check a different code path
    CHECK(json::parse("1.000000000000000000000000000000000000000000000000000000000000000000000000").get<double>() == 1.0);
}
  • cpp-test: [parse;trailing zeroes] (TSF/tests/unit-numbers.cpp)

SECTION("trailing zeroes")
{   
    // Trailing zeroes after the decimal point do not influence the parsing
    CHECK(json::parse("3.1415000000000000000000000")==json::parse("3.1415"));
    CHECK(json::parse("3.1415000000000\u004515")==json::parse("3.1415\u004515"));
    CHECK(json::parse("3.1415926000000000\u006515")==json::parse("3.1415926\u006515"));
    // This also works for numbers that are not parsed correctly anyway
    CHECK(json::parse("2.2250738585072011360574097967091319759348195463516456400000000e-308")==json::parse("2.22507385850720113605740979670913197593481954635164564e-308"));
    CHECK(json::parse("0.999999999999999944488848768742172978818416595458984374")==json::parse("0.999999999999999944488848768742172978818416595458984374000000"));
}

Fallacies:

None

Graph:

No Historic Data Found


NPF-02.11#

The service parses numbers within the 64-bit double range but outside of the double precision without throwing an exception.

Supported Requests:

Supporting Items:

None

References:

  • cpp-test: [regression tests 1;issue #186 miloyip/nativejson-benchmark: floating-point parsing] (tests/src/unit-regression1.cpp)

SECTION("issue #186 miloyip/nativejson-benchmark: floating-point parsing")
{
    json j;

    j = json::parse("-0.0");
    CHECK(j.get<double>() == -0.0);

    j = json::parse("2.22507385850720113605740979670913197593481954635164564e-308");
    CHECK(j.get<double>() == 2.2250738585072009e-308);

    j = json::parse("0.999999999999999944488848768742172978818416595458984374");
    CHECK(j.get<double>() == 0.99999999999999989);

    j = json::parse("1.00000000000000011102230246251565404236316680908203126");
    CHECK(j.get<double>() == 1.00000000000000022);

    j = json::parse("7205759403792793199999e-5");
    CHECK(j.get<double>() == 72057594037927928.0);

    j = json::parse("922337203685477529599999e-5");
    CHECK(j.get<double>() == 9223372036854774784.0);

    j = json::parse("1014120480182583464902367222169599999e-5");
    CHECK(j.get<double>() == 10141204801825834086073718800384.0);

    j = json::parse("5708990770823839207320493820740630171355185151999e-3");
    CHECK(j.get<double>() == 5708990770823838890407843763683279797179383808.0);

    // create JSON class with nonstandard float number type

    // float
    nlohmann::basic_json<std::map, std::vector, std::string, bool, int32_t, uint32_t, float> const j_float =
        1.23e25f;
    CHECK(j_float.get<float>() == 1.23e25f);

    // double
    nlohmann::basic_json<std::map, std::vector, std::string, bool, int64_t, uint64_t, double> const j_double =
        1.23e35;
    CHECK(j_double.get<double>() == 1.23e35);

    // long double
    nlohmann::basic_json<std::map, std::vector, std::string, bool, int64_t, uint64_t, long double>
    const j_long_double = 1.23e45L;
    CHECK(j_long_double.get<long double>() == 1.23e45L);
}

Fallacies:

None

Graph:

No Historic Data Found


NPF-02.12#

The service ignores capitalisation of the exponent.

Supported Requests:

Supporting Items:

None

References:

  • cpp-test: [parse;exponents;Capitalisation] (TSF/tests/unit-numbers.cpp)

SECTION("Capitalisation")
{
    CHECK(json::parse("3.1415\u00454")==json::parse("3.1415\u00654"));
}

Fallacies:

None

Graph:

No Historic Data Found


NPF-02.2#

The service parses integers with exponent within the precision of 64-bit double.

Supported Requests:

Supporting Items:

None

References:

  • cpp-test: [parser class - core;parse;number;floating-point;with exponent] (TSF/tests/unit-class_parser_core.cpp)

SECTION("with exponent")
{
    CHECK(parser_helper("-128.5E3") == json(-128.5E3));
    CHECK(parser_helper("-128.5E-3") == json(-128.5E-3));
    CHECK(parser_helper("-0.0e1") == json(-0.0e1));
    CHECK(parser_helper("-0.0E1") == json(-0.0e1));
}
  • cpp-test: [parser class - core;parse;number;integers;with exponent] (TSF/tests/unit-class_parser_core.cpp)

SECTION("with exponent")
{
    CHECK(parser_helper("0e1") == json(0e1));
    CHECK(parser_helper("0E1") == json(0e1));

    CHECK(parser_helper("10000E-4") == json(10000e-4));
    CHECK(parser_helper("10000E-3") == json(10000e-3));
    CHECK(parser_helper("10000E-2") == json(10000e-2));
    CHECK(parser_helper("10000E-1") == json(10000e-1));
    CHECK(parser_helper("10000E0") == json(10000e0));
    CHECK(parser_helper("10000E1") == json(10000e1));
    CHECK(parser_helper("10000E2") == json(10000e2));
    CHECK(parser_helper("10000E3") == json(10000e3));
    CHECK(parser_helper("10000E4") == json(10000e4));

    CHECK(parser_helper("10000e-4") == json(10000e-4));
    CHECK(parser_helper("10000e-3") == json(10000e-3));
    CHECK(parser_helper("10000e-2") == json(10000e-2));
    CHECK(parser_helper("10000e-1") == json(10000e-1));
    CHECK(parser_helper("10000e0") == json(10000e0));
    CHECK(parser_helper("10000e1") == json(10000e1));
    CHECK(parser_helper("10000e2") == json(10000e2));
    CHECK(parser_helper("10000e3") == json(10000e3));
    CHECK(parser_helper("10000e4") == json(10000e4));

    CHECK(parser_helper("-0e1") == json(-0e1));
    CHECK(parser_helper("-0E1") == json(-0e1));
    CHECK(parser_helper("-0E123") == json(-0e123));

    // numbers after exponent
    CHECK(parser_helper("10E0") == json(10e0));
    CHECK(parser_helper("10E1") == json(10e1));
    CHECK(parser_helper("10E2") == json(10e2));
    CHECK(parser_helper("10E3") == json(10e3));
    CHECK(parser_helper("10E4") == json(10e4));
    CHECK(parser_helper("10E5") == json(10e5));
    CHECK(parser_helper("10E6") == json(10e6));
    CHECK(parser_helper("10E7") == json(10e7));
    CHECK(parser_helper("10E8") == json(10e8));
    CHECK(parser_helper("10E9") == json(10e9));
    CHECK(parser_helper("10E+0") == json(10e0));
    CHECK(parser_helper("10E+1") == json(10e1));
    CHECK(parser_helper("10E+2") == json(10e2));
    CHECK(parser_helper("10E+3") == json(10e3));
    CHECK(parser_helper("10E+4") == json(10e4));
    CHECK(parser_helper("10E+5") == json(10e5));
    CHECK(parser_helper("10E+6") == json(10e6));
    CHECK(parser_helper("10E+7") == json(10e7));
    CHECK(parser_helper("10E+8") == json(10e8));
    CHECK(parser_helper("10E+9") == json(10e9));
    CHECK(parser_helper("10E-1") == json(10e-1));
    CHECK(parser_helper("10E-2") == json(10e-2));
    CHECK(parser_helper("10E-3") == json(10e-3));
    CHECK(parser_helper("10E-4") == json(10e-4));
    CHECK(parser_helper("10E-5") == json(10e-5));
    CHECK(parser_helper("10E-6") == json(10e-6));
    CHECK(parser_helper("10E-7") == json(10e-7));
    CHECK(parser_helper("10E-8") == json(10e-8));
    CHECK(parser_helper("10E-9") == json(10e-9));
}
  • cpp-testsuite: [/nst_json_testsuite2/test_parsing/y_number_real_capital_e.json, /nst_json_testsuite2/test_parsing/y_number_real_capital_e_neg_exp.json, /nst_json_testsuite2/test_parsing/y_number_real_capital_e_pos_exp.json, /nst_json_testsuite2/test_parsing/y_number_real_exponent.json, /nst_json_testsuite2/test_parsing/y_number_real_fraction_exponent.json, /nst_json_testsuite2/test_parsing/y_number_real_neg_exp.json, /nst_json_testsuite2/test_parsing/y_number_real_pos_exponent.json]

    • Description: Tests whether several numbers with exponent are parsed without throwing an exception.

    • JSON Testsuite: /nst_json_testsuite2/test_parsing/y_number_real_capital_e.json

    [1E22]
    
    • JSON Testsuite: /nst_json_testsuite2/test_parsing/y_number_real_capital_e_neg_exp.json

    [1E-2]
    
    • JSON Testsuite: /nst_json_testsuite2/test_parsing/y_number_real_capital_e_pos_exp.json

    [1E+2]
    
    • JSON Testsuite: /nst_json_testsuite2/test_parsing/y_number_real_exponent.json

    [123e45]
    
    • JSON Testsuite: /nst_json_testsuite2/test_parsing/y_number_real_fraction_exponent.json

    [123.456e78]
    
    • JSON Testsuite: /nst_json_testsuite2/test_parsing/y_number_real_neg_exp.json

    [1e-2]
    
    • JSON Testsuite: /nst_json_testsuite2/test_parsing/y_number_real_pos_exponent.json

    [1e+2]
    
    • cpp-test: [nst’s JSONTestSuite (2);test_parsing;y] (tests/src/unit-testsuites.cpp)

    SECTION("y")
    {
        for (const auto* filename :
                {
                    TEST_DATA_DIRECTORY "/nst_json_testsuite2/test_parsing/y_number_real_capital_e.json",
                    TEST_DATA_DIRECTORY "/nst_json_testsuite2/test_parsing/y_number_real_capital_e_neg_exp.json",
                    TEST_DATA_DIRECTORY "/nst_json_testsuite2/test_parsing/y_number_real_capital_e_pos_exp.json",
                    TEST_DATA_DIRECTORY "/nst_json_testsuite2/test_parsing/y_number_real_exponent.json",
                    TEST_DATA_DIRECTORY "/nst_json_testsuite2/test_parsing/y_number_real_fraction_exponent.json",
                    TEST_DATA_DIRECTORY "/nst_json_testsuite2/test_parsing/y_number_real_neg_exp.json",
                    TEST_DATA_DIRECTORY "/nst_json_testsuite2/test_parsing/y_number_real_pos_exponent.json",
                }
            )
        {
            CAPTURE(filename)
            std::ifstream f(filename);
            json _;
            CHECK_NOTHROW(_ = json::parse(f));
            std::ifstream f2(filename);
            CHECK(json::accept(f2));
        }
    }
    
    
     // Note: Other test data lines have been filtered out for conciseness.
    
  • cpp-test: [parse;Precision] (TSF/tests/unit-numbers.cpp)

SECTION("Precision")
{
    CHECK(json::parse("1.7976931348623158e308").dump()=="1.7976931348623157e+308"); // maximum double value 
    CHECK(json::parse("-1.7976931348623158e308").dump()=="-1.7976931348623157e+308"); // minimum double value
}

Fallacies:

None

Graph:

No Historic Data Found


NPF-02.3#

The service parses floating point values without exponent within the precision of 64-bit double.

Supported Requests:

Supporting Items:

None

References:

  • cpp-test: [parser class - core;parse;number;integers] (TSF/tests/unit-class_parser_core.cpp)

SECTION("integers")
{
    SECTION("without exponent")
    {
        CHECK(parser_helper("-128") == json(-128));
        CHECK(parser_helper("-0") == json(-0));
        CHECK(parser_helper("0") == json(0));
        CHECK(parser_helper("128") == json(128));
    }

    SECTION("with exponent")
    {
        CHECK(parser_helper("0e1") == json(0e1));
        CHECK(parser_helper("0E1") == json(0e1));

        CHECK(parser_helper("10000E-4") == json(10000e-4));
        CHECK(parser_helper("10000E-3") == json(10000e-3));
        CHECK(parser_helper("10000E-2") == json(10000e-2));
        CHECK(parser_helper("10000E-1") == json(10000e-1));
        CHECK(parser_helper("10000E0") == json(10000e0));
        CHECK(parser_helper("10000E1") == json(10000e1));
        CHECK(parser_helper("10000E2") == json(10000e2));
        CHECK(parser_helper("10000E3") == json(10000e3));
        CHECK(parser_helper("10000E4") == json(10000e4));

        CHECK(parser_helper("10000e-4") == json(10000e-4));
        CHECK(parser_helper("10000e-3") == json(10000e-3));
        CHECK(parser_helper("10000e-2") == json(10000e-2));
        CHECK(parser_helper("10000e-1") == json(10000e-1));
        CHECK(parser_helper("10000e0") == json(10000e0));
        CHECK(parser_helper("10000e1") == json(10000e1));
        CHECK(parser_helper("10000e2") == json(10000e2));
        CHECK(parser_helper("10000e3") == json(10000e3));
        CHECK(parser_helper("10000e4") == json(10000e4));

        CHECK(parser_helper("-0e1") == json(-0e1));
        CHECK(parser_helper("-0E1") == json(-0e1));
        CHECK(parser_helper("-0E123") == json(-0e123));

        // numbers after exponent
        CHECK(parser_helper("10E0") == json(10e0));
        CHECK(parser_helper("10E1") == json(10e1));
        CHECK(parser_helper("10E2") == json(10e2));
        CHECK(parser_helper("10E3") == json(10e3));
        CHECK(parser_helper("10E4") == json(10e4));
        CHECK(parser_helper("10E5") == json(10e5));
        CHECK(parser_helper("10E6") == json(10e6));
        CHECK(parser_helper("10E7") == json(10e7));
        CHECK(parser_helper("10E8") == json(10e8));
        CHECK(parser_helper("10E9") == json(10e9));
        CHECK(parser_helper("10E+0") == json(10e0));
        CHECK(parser_helper("10E+1") == json(10e1));
        CHECK(parser_helper("10E+2") == json(10e2));
        CHECK(parser_helper("10E+3") == json(10e3));
        CHECK(parser_helper("10E+4") == json(10e4));
        CHECK(parser_helper("10E+5") == json(10e5));
        CHECK(parser_helper("10E+6") == json(10e6));
        CHECK(parser_helper("10E+7") == json(10e7));
        CHECK(parser_helper("10E+8") == json(10e8));
        CHECK(parser_helper("10E+9") == json(10e9));
        CHECK(parser_helper("10E-1") == json(10e-1));
        CHECK(parser_helper("10E-2") == json(10e-2));
        CHECK(parser_helper("10E-3") == json(10e-3));
        CHECK(parser_helper("10E-4") == json(10e-4));
        CHECK(parser_helper("10E-5") == json(10e-5));
        CHECK(parser_helper("10E-6") == json(10e-6));
        CHECK(parser_helper("10E-7") == json(10e-7));
        CHECK(parser_helper("10E-8") == json(10e-8));
        CHECK(parser_helper("10E-9") == json(10e-9));
    }

    SECTION("edge cases")
    {
        // From RFC8259, Section 6:
        // Note that when such software is used, numbers that are
        // integers and are in the range [-(2**53)+1, (2**53)-1]
        // are interoperable in the sense that implementations will
        // agree exactly on their numeric values.

        // -(2**53)+1
        CHECK(parser_helper("-9007199254740991").get<int64_t>() == -9007199254740991);
        // (2**53)-1
        CHECK(parser_helper("9007199254740991").get<int64_t>() == 9007199254740991);
    }

    SECTION("over the edge cases")  // issue #178 - Integer conversion to unsigned (incorrect handling of 64-bit integers)
    {
        // While RFC8259, Section 6 specifies a preference for support
        // for ranges in range of IEEE 754-2008 binary64 (double precision)
        // this does not accommodate 64-bit integers without loss of accuracy.
        // As 64-bit integers are now widely used in software, it is desirable
        // to expand support to the full 64 bit (signed and unsigned) range
        // i.e. -(2**63) -> (2**64)-1.

        // -(2**63)    ** Note: compilers see negative literals as negated positive numbers (hence the -1))
        CHECK(parser_helper("-9223372036854775808").get<int64_t>() == -9223372036854775807 - 1);
        // (2**63)-1
        CHECK(parser_helper("9223372036854775807").get<int64_t>() == 9223372036854775807);
        // (2**64)-1
        CHECK(parser_helper("18446744073709551615").get<uint64_t>() == 18446744073709551615u);
    }
}

Fallacies:

None

Graph:

No Historic Data Found


NPF-02.4#

The service parses floating point values with exponent within the precision of 64-bit double.

Supported Requests:

Supporting Items:

None

References:

  • cpp-test: [parser class - core;parse;number;floating-point] (TSF/tests/unit-class_parser_core.cpp)

SECTION("floating-point")
{
    SECTION("without exponent")
    {
        CHECK(parser_helper("-128.5") == json(-128.5));
        CHECK(parser_helper("0.999") == json(0.999));
        CHECK(parser_helper("128.5") == json(128.5));
        CHECK(parser_helper("-0.0") == json(-0.0));
    }

    SECTION("with exponent")
    {
        CHECK(parser_helper("-128.5E3") == json(-128.5E3));
        CHECK(parser_helper("-128.5E-3") == json(-128.5E-3));
        CHECK(parser_helper("-0.0e1") == json(-0.0e1));
        CHECK(parser_helper("-0.0E1") == json(-0.0e1));
    }
}
  • cpp-test: [regression tests 1;issue #360 - Loss of precision when serializing <double>] (tests/src/unit-regression1.cpp)

SECTION("issue #360 - Loss of precision when serializing <double>")
{
    auto check_roundtrip = [](double number)
    {
        CAPTURE(number)

        json j = number;
        CHECK(j.is_number_float());

        std::stringstream ss;
        ss << j;

        CHECK_NOTHROW(ss >> j);
        CHECK(j.is_number_float());
        CHECK(j.get<json::number_float_t>() == number);
    };

    check_roundtrip(100000000000.1236);
    check_roundtrip((std::numeric_limits<json::number_float_t>::max)());

    // Some more numbers which fail to roundtrip when serialized with digits10 significand digits (instead of max_digits10)
    check_roundtrip(1.541888611948064e-17);
    check_roundtrip(5.418771028591015e-16);
    check_roundtrip(9.398685592608595e-15);
    check_roundtrip(8.826843952762347e-14);
    check_roundtrip(8.143291313475335e-13);
    check_roundtrip(4.851328172762508e-12);
    check_roundtrip(6.677850998084358e-11);
    check_roundtrip(3.995398518174525e-10);
    check_roundtrip(1.960452605645124e-9);
    check_roundtrip(3.551812586302883e-8);
    check_roundtrip(2.947988411689261e-7);
    check_roundtrip(8.210166748056192e-6);
    check_roundtrip(6.104889704266753e-5);
    check_roundtrip(0.0008629954631330876);
    check_roundtrip(0.004936993881051611);
    check_roundtrip(0.08309725102608073);
    check_roundtrip(0.5210494268499783);
    check_roundtrip(6.382927930939767);
    check_roundtrip(59.94947245358671);
    check_roundtrip(361.0838651266122);
    check_roundtrip(4678.354596181877);
    check_roundtrip(61412.17658956043);
    check_roundtrip(725696.0799057782);
    check_roundtrip(2811732.583399828);
    check_roundtrip(30178351.07533605);
    check_roundtrip(689684880.3235844);
    check_roundtrip(5714887673.555147);
    check_roundtrip(84652038821.18808);
    check_roundtrip(156510583431.7721);
    check_roundtrip(5938450569021.732);
    check_roundtrip(83623297654460.33);
    check_roundtrip(701466573254773.6);
    check_roundtrip(1369013370304513);
    check_roundtrip(96963648023094720); // NOLINT(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions)
    check_roundtrip(3.478237409280108e+17);
}

Fallacies:

None

Graph:

No Historic Data Found


NPF-02.5#

The service ignores leading zeroes in the exponent.

Supported Requests:

Supporting Items:

None

References:

  • cpp-test: [parse;exponents;leading zeroes] (TSF/tests/unit-numbers.cpp)

SECTION("leading zeroes")
{
    CHECK(json::parse("1\u00451")==json::parse("1\u004501"));
    CHECK(json::parse("0.1\u00451")==json::parse("0.1\u004501"));
    CHECK(json::parse("1\u004545")==json::parse("1\u004500000000000000000000000045"));
    CHECK(json::parse("12415\u004516")==json::parse("12415\u00450016"));
    CHECK(json::parse("12.415\u004516")==json::parse("12.415\u00450016"));
    CHECK(json::parse("1\u00651")==json::parse("1\u006501"));
    CHECK(json::parse("0.1\u00651")==json::parse("0.1\u006501"));
    CHECK(json::parse("1\u006545")==json::parse("1\u006500000000000000000000000045"));
    CHECK(json::parse("12415\u006516")==json::parse("12415\u00650016"));
    CHECK(json::parse("12.415\u006516")==json::parse("12.415\u00650016"));
}

Fallacies:

None

Graph:

No Historic Data Found


NPF-02.6#

The service parses integers within IEEE 754-2008 binary64.

Supported Requests:

Supporting Items:

None

References:

  • cpp-test: [parser class - core;parse;number;integers;edge cases] (TSF/tests/unit-class_parser_core.cpp)

SECTION("edge cases")
{
    // From RFC8259, Section 6:
    // Note that when such software is used, numbers that are
    // integers and are in the range [-(2**53)+1, (2**53)-1]
    // are interoperable in the sense that implementations will
    // agree exactly on their numeric values.

    // -(2**53)+1
    CHECK(parser_helper("-9007199254740991").get<int64_t>() == -9007199254740991);
    // (2**53)-1
    CHECK(parser_helper("9007199254740991").get<int64_t>() == 9007199254740991);
}
  • cpp-test: [parser class - core;parse;number;integers;over the edge cases] (TSF/tests/unit-class_parser_core.cpp)

SECTION("over the edge cases")  // issue #178 - Integer conversion to unsigned (incorrect handling of 64-bit integers)
{
    // While RFC8259, Section 6 specifies a preference for support
    // for ranges in range of IEEE 754-2008 binary64 (double precision)
    // this does not accommodate 64-bit integers without loss of accuracy.
    // As 64-bit integers are now widely used in software, it is desirable
    // to expand support to the full 64 bit (signed and unsigned) range
    // i.e. -(2**63) -> (2**64)-1.

    // -(2**63)    ** Note: compilers see negative literals as negated positive numbers (hence the -1))
    CHECK(parser_helper("-9223372036854775808").get<int64_t>() == -9223372036854775807 - 1);
    // (2**63)-1
    CHECK(parser_helper("9223372036854775807").get<int64_t>() == 9223372036854775807);
    // (2**64)-1
    CHECK(parser_helper("18446744073709551615").get<uint64_t>() == 18446744073709551615u);
}

Fallacies:

None

Graph:

No Historic Data Found


NPF-02.7#

The service ignores leading and trailing whitespace.

Supported Requests:

Supporting Items:

None

References:

  • cpp-test: [parse;whitespace] (TSF/tests/unit-numbers.cpp)

SECTION("whitespace")
{
    // Leading and trailing whitespace is ignored.
    CHECK(json::parse("\n\n\t 123\n\t\t  \u000d")==json::parse("123"));
    CHECK(json::parse(" 123 ")==json::parse("123"));
    CHECK(json::parse(" 123\t")==json::parse("123"));
    CHECK(json::parse(" 123\n")==json::parse("123"));
    CHECK(json::parse(" 123\u000d")==json::parse("123"));
    CHECK(json::parse("\t123 ")==json::parse("123"));
    CHECK(json::parse("\t123\t")==json::parse("123"));
    CHECK(json::parse("\t123\n")==json::parse("123"));
    CHECK(json::parse("\t123\u000d")==json::parse("123"));
    CHECK(json::parse("\n123 ")==json::parse("123"));
    CHECK(json::parse("\n123\t")==json::parse("123"));
    CHECK(json::parse("\n123\n")==json::parse("123"));
    CHECK(json::parse("\n123\u000d")==json::parse("123"));
    CHECK(json::parse("\u000d123 ")==json::parse("123"));
    CHECK(json::parse("\u000d123\t")==json::parse("123"));
    CHECK(json::parse("\u000d123\n")==json::parse("123"));
    CHECK(json::parse("\u000d123\u000d")==json::parse("123"));
}
  • function: [lexer::skip_whitespace] (include/nlohmann/detail/input/lexer.hpp)

    • Description: function, which skips admissible whitespace during reading

void skip_whitespace()
{
    do
    {
        get();
    }
    while (current == ' ' || current == '\t' || current == '\n' || current == '\r');
}

Fallacies:

None

Graph:

No Historic Data Found


NPF-02.8#

The service ignores one singular leading plus of the exponent.

Supported Requests:

Supporting Items:

None

References:

  • cpp-test: [parse;exponents;leading plus] (TSF/tests/unit-numbers.cpp)

SECTION("leading plus")
{
    CHECK(json::parse("1\u0045+1")==json::parse("1\u00451"));
    CHECK(json::parse("1\u0065+1")==json::parse("1\u00651"));
    CHECK(json::parse("1.0034\u0045+23")==json::parse("1.0034\u004523"));
    CHECK(json::parse("1.0034\u0065+23")==json::parse("1.0034\u006523"));
}

Fallacies:

None

Graph:

No Historic Data Found


NPF-02.9#

The service parses floating point numbers within IEEE 754-2008 binary64 standard.

Supported Requests:

Supporting Items:

None

References:

  • cpp-test: [compliance tests from nativejson-benchmark;doubles] (tests/src/unit-testsuites.cpp)

SECTION("doubles")
{
    auto TEST_DOUBLE = [](const std::string & json_string, const double expected)
    {
        CAPTURE(json_string)
        CAPTURE(expected)
        CHECK(json::parse(json_string)[0].get<double>() == Approx(expected));
    };

    TEST_DOUBLE("[0.0]", 0.0);
    TEST_DOUBLE("[-0.0]", -0.0);
    TEST_DOUBLE("[1.0]", 1.0);
    TEST_DOUBLE("[-1.0]", -1.0);
    TEST_DOUBLE("[1.5]", 1.5);
    TEST_DOUBLE("[-1.5]", -1.5);
    TEST_DOUBLE("[3.1416]", 3.1416);
    TEST_DOUBLE("[1E10]", 1E10);
    TEST_DOUBLE("[1e10]", 1e10);
    TEST_DOUBLE("[1E+10]", 1E+10);
    TEST_DOUBLE("[1E-10]", 1E-10);
    TEST_DOUBLE("[-1E10]", -1E10);
    TEST_DOUBLE("[-1e10]", -1e10);
    TEST_DOUBLE("[-1E+10]", -1E+10);
    TEST_DOUBLE("[-1E-10]", -1E-10);
    TEST_DOUBLE("[1.234E+10]", 1.234E+10);
    TEST_DOUBLE("[1.234E-10]", 1.234E-10);
    TEST_DOUBLE("[1.79769e+308]", 1.79769e+308);
    TEST_DOUBLE("[2.22507e-308]", 2.22507e-308);
    TEST_DOUBLE("[-1.79769e+308]", -1.79769e+308);
    TEST_DOUBLE("[-2.22507e-308]", -2.22507e-308);
    TEST_DOUBLE("[4.9406564584124654e-324]", 4.9406564584124654e-324); // minimum denormal
    TEST_DOUBLE("[2.2250738585072009e-308]", 2.2250738585072009e-308); // Max subnormal double
    TEST_DOUBLE("[2.2250738585072014e-308]", 2.2250738585072014e-308); // Min normal positive double
    TEST_DOUBLE("[1.7976931348623157e+308]", 1.7976931348623157e+308); // Max double
    TEST_DOUBLE("[1e-10000]", 0.0);                                   // must underflow
    TEST_DOUBLE("[18446744073709551616]",
                18446744073709551616.0);    // 2^64 (max of uint64_t + 1, force to use double)
    TEST_DOUBLE("[-9223372036854775809]",
                -9223372036854775809.0);    // -2^63 - 1(min of int64_t + 1, force to use double)
    TEST_DOUBLE("[0.9868011474609375]",
                0.9868011474609375);          // https://github.com/miloyip/rapidjson/issues/120
    TEST_DOUBLE("[123e34]", 123e34);                                  // Fast Path Cases In Disguise
    TEST_DOUBLE("[45913141877270640000.0]", 45913141877270640000.0);
    TEST_DOUBLE("[2.2250738585072011e-308]",
                2.2250738585072011e-308);
    //TEST_DOUBLE("[1e-00011111111111]", 0.0);
    //TEST_DOUBLE("[-1e-00011111111111]", -0.0);
    TEST_DOUBLE("[1e-214748363]", 0.0);
    TEST_DOUBLE("[1e-214748364]", 0.0);
    //TEST_DOUBLE("[1e-21474836311]", 0.0);
    TEST_DOUBLE("[0.017976931348623157e+310]", 1.7976931348623157e+308); // Max double in another form

    // Since
    // abs((2^-1022 - 2^-1074) - 2.2250738585072012e-308) = 3.109754131239141401123495768877590405345064751974375599... ¡Á 10^-324
    // abs((2^-1022) - 2.2250738585072012e-308) = 1.830902327173324040642192159804623318305533274168872044... ¡Á 10 ^ -324
    // So 2.2250738585072012e-308 should round to 2^-1022 = 2.2250738585072014e-308
    TEST_DOUBLE("[2.2250738585072012e-308]",
                2.2250738585072014e-308);

    // Closer to normal/subnormal boundary
    // boundary = 2^-1022 - 2^-1075 = 2.225073858507201136057409796709131975934819546351645648... ¡Á 10^-308
    TEST_DOUBLE("[2.22507385850720113605740979670913197593481954635164564e-308]",
                2.2250738585072009e-308);
    TEST_DOUBLE("[2.22507385850720113605740979670913197593481954635164565e-308]",
                2.2250738585072014e-308);

    // 1.0 is in (1.0 - 2^-54, 1.0 + 2^-53)
    // 1.0 - 2^-54 = 0.999999999999999944488848768742172978818416595458984375
    TEST_DOUBLE("[0.999999999999999944488848768742172978818416595458984375]", 1.0); // round to even
    TEST_DOUBLE("[0.999999999999999944488848768742172978818416595458984374]",
                0.99999999999999989); // previous double
    TEST_DOUBLE("[0.999999999999999944488848768742172978818416595458984376]", 1.0); // next double
    // 1.0 + 2^-53 = 1.00000000000000011102230246251565404236316680908203125
    TEST_DOUBLE("[1.00000000000000011102230246251565404236316680908203125]", 1.0); // round to even
    TEST_DOUBLE("[1.00000000000000011102230246251565404236316680908203124]", 1.0); // previous double
    TEST_DOUBLE("[1.00000000000000011102230246251565404236316680908203126]",
                1.00000000000000022); // next double

    // Numbers from https://github.com/floitsch/double-conversion/blob/master/test/cctest/test-strtod.cc

    TEST_DOUBLE("[72057594037927928.0]", 72057594037927928.0);
    TEST_DOUBLE("[72057594037927936.0]", 72057594037927936.0);
    TEST_DOUBLE("[72057594037927932.0]", 72057594037927936.0);
    TEST_DOUBLE("[7205759403792793199999e-5]", 72057594037927928.0);
    TEST_DOUBLE("[7205759403792793200001e-5]", 72057594037927936.0);

    TEST_DOUBLE("[9223372036854774784.0]", 9223372036854774784.0);
    TEST_DOUBLE("[9223372036854775808.0]", 9223372036854775808.0);
    TEST_DOUBLE("[9223372036854775296.0]", 9223372036854775808.0);
    TEST_DOUBLE("[922337203685477529599999e-5]", 9223372036854774784.0);
    TEST_DOUBLE("[922337203685477529600001e-5]", 9223372036854775808.0);

    TEST_DOUBLE("[10141204801825834086073718800384]", 10141204801825834086073718800384.0);
    TEST_DOUBLE("[10141204801825835211973625643008]", 10141204801825835211973625643008.0);
    TEST_DOUBLE("[10141204801825834649023672221696]", 10141204801825835211973625643008.0);
    TEST_DOUBLE("[1014120480182583464902367222169599999e-5]", 10141204801825834086073718800384.0);
    TEST_DOUBLE("[1014120480182583464902367222169600001e-5]", 10141204801825835211973625643008.0);

    TEST_DOUBLE("[5708990770823838890407843763683279797179383808]",
                5708990770823838890407843763683279797179383808.0);
    TEST_DOUBLE("[5708990770823839524233143877797980545530986496]",
                5708990770823839524233143877797980545530986496.0);
    TEST_DOUBLE("[5708990770823839207320493820740630171355185152]",
                5708990770823839524233143877797980545530986496.0);
    TEST_DOUBLE("[5708990770823839207320493820740630171355185151999e-3]",
                5708990770823838890407843763683279797179383808.0);
    TEST_DOUBLE("[5708990770823839207320493820740630171355185152001e-3]",
                5708990770823839524233143877797980545530986496.0);

    {
        std::string n1e308(312, '0');   // '1' followed by 308 '0'
        n1e308[0] = '[';
        n1e308[1] = '1';
        n1e308[310] = ']';
        n1e308[311] = '\0';
        TEST_DOUBLE(n1e308, 1E308);
    }

    // Cover trimming
    TEST_DOUBLE(
        "[2.22507385850720113605740979670913197593481954635164564802342610972482222202107694551652952390813508"
        "7914149158913039621106870086438694594645527657207407820621743379988141063267329253552286881372149012"
        "9811224514518898490572223072852551331557550159143974763979834118019993239625482890171070818506906306"
        "6665599493827577257201576306269066333264756530000924588831643303777979186961204949739037782970490505"
        "1080609940730262937128958950003583799967207254304360284078895771796150945516748243471030702609144621"
        "5722898802581825451803257070188608721131280795122334262883686223215037756666225039825343359745688844"
        "2390026549819838548794829220689472168983109969836584681402285424333066033985088644580400103493397042"
        "7567186443383770486037861622771738545623065874679014086723327636718751234567890123456789012345678901"
        "e-308]",
        2.2250738585072014e-308);
}
  • cpp-test: [regression tests 1;issue #360 - Loss of precision when serializing <double>] (tests/src/unit-regression1.cpp)

SECTION("issue #360 - Loss of precision when serializing <double>")
{
    auto check_roundtrip = [](double number)
    {
        CAPTURE(number)

        json j = number;
        CHECK(j.is_number_float());

        std::stringstream ss;
        ss << j;

        CHECK_NOTHROW(ss >> j);
        CHECK(j.is_number_float());
        CHECK(j.get<json::number_float_t>() == number);
    };

    check_roundtrip(100000000000.1236);
    check_roundtrip((std::numeric_limits<json::number_float_t>::max)());

    // Some more numbers which fail to roundtrip when serialized with digits10 significand digits (instead of max_digits10)
    check_roundtrip(1.541888611948064e-17);
    check_roundtrip(5.418771028591015e-16);
    check_roundtrip(9.398685592608595e-15);
    check_roundtrip(8.826843952762347e-14);
    check_roundtrip(8.143291313475335e-13);
    check_roundtrip(4.851328172762508e-12);
    check_roundtrip(6.677850998084358e-11);
    check_roundtrip(3.995398518174525e-10);
    check_roundtrip(1.960452605645124e-9);
    check_roundtrip(3.551812586302883e-8);
    check_roundtrip(2.947988411689261e-7);
    check_roundtrip(8.210166748056192e-6);
    check_roundtrip(6.104889704266753e-5);
    check_roundtrip(0.0008629954631330876);
    check_roundtrip(0.004936993881051611);
    check_roundtrip(0.08309725102608073);
    check_roundtrip(0.5210494268499783);
    check_roundtrip(6.382927930939767);
    check_roundtrip(59.94947245358671);
    check_roundtrip(361.0838651266122);
    check_roundtrip(4678.354596181877);
    check_roundtrip(61412.17658956043);
    check_roundtrip(725696.0799057782);
    check_roundtrip(2811732.583399828);
    check_roundtrip(30178351.07533605);
    check_roundtrip(689684880.3235844);
    check_roundtrip(5714887673.555147);
    check_roundtrip(84652038821.18808);
    check_roundtrip(156510583431.7721);
    check_roundtrip(5938450569021.732);
    check_roundtrip(83623297654460.33);
    check_roundtrip(701466573254773.6);
    check_roundtrip(1369013370304513);
    check_roundtrip(96963648023094720); // NOLINT(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions)
    check_roundtrip(3.478237409280108e+17);
}

Fallacies:

None

Graph:

No Historic Data Found


NPF-03#

The service parses strings according to RFC8259.

Supported Requests:

Supporting Items:

References:

  • function: [lexer::scan_string] (include/nlohmann/detail/input/lexer.hpp)

    • Description: function, which parses strings into C++ std::string and verifies en passant that these strings are in accordance with RFC8259

token_type scan_string()
{
    // reset token_buffer (ignore opening quote)
    reset();

    // we entered the function by reading an open quote
    JSON_ASSERT(current == '\"');

    while (true)
    {
        // get next character
        switch (get())
        {
            // end of file while parsing string
            case char_traits<char_type>::eof():
            {
                error_message = "invalid string: missing closing quote";
                return token_type::parse_error;
            }

            // closing quote
            case '\"':
            {
                return token_type::value_string;
            }

            // escapes
            case '\\':
            {
                switch (get())
                {
                    // quotation mark
                    case '\"':
                        add('\"');
                        break;
                    // reverse solidus
                    case '\\':
                        add('\\');
                        break;
                    // solidus
                    case '/':
                        add('/');
                        break;
                    // backspace
                    case 'b':
                        add('\b');
                        break;
                    // form feed
                    case 'f':
                        add('\f');
                        break;
                    // line feed
                    case 'n':
                        add('\n');
                        break;
                    // carriage return
                    case 'r':
                        add('\r');
                        break;
                    // tab
                    case 't':
                        add('\t');
                        break;

                    // unicode escapes
                    case 'u':
                    {
                        const int codepoint1 = get_codepoint();
                        int codepoint = codepoint1; // start with codepoint1

                        if (JSON_HEDLEY_UNLIKELY(codepoint1 == -1))
                        {
                            error_message = "invalid string: '\\u' must be followed by 4 hex digits";
                            return token_type::parse_error;
                        }

                        // check if code point is a high surrogate
                        if (0xD800 <= codepoint1 && codepoint1 <= 0xDBFF)
                        {
                            // expect next \uxxxx entry
                            if (JSON_HEDLEY_LIKELY(get() == '\\' && get() == 'u'))
                            {
                                const int codepoint2 = get_codepoint();

                                if (JSON_HEDLEY_UNLIKELY(codepoint2 == -1))
                                {
                                    error_message = "invalid string: '\\u' must be followed by 4 hex digits";
                                    return token_type::parse_error;
                                }

                                // check if codepoint2 is a low surrogate
                                if (JSON_HEDLEY_LIKELY(0xDC00 <= codepoint2 && codepoint2 <= 0xDFFF))
                                {
                                    // overwrite codepoint
                                    codepoint = static_cast<int>(
                                                    // high surrogate occupies the most significant 22 bits
                                                    (static_cast<unsigned int>(codepoint1) << 10u)
                                                    // low surrogate occupies the least significant 15 bits
                                                    + static_cast<unsigned int>(codepoint2)
                                                    // there is still the 0xD800, 0xDC00 and 0x10000 noise
                                                    // in the result, so we have to subtract with:
                                                    // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
                                                    - 0x35FDC00u);
                                }
                                else
                                {
                                    error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF";
                                    return token_type::parse_error;
                                }
                            }
                            else
                            {
                                error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF";
                                return token_type::parse_error;
                            }
                        }
                        else
                        {
                            if (JSON_HEDLEY_UNLIKELY(0xDC00 <= codepoint1 && codepoint1 <= 0xDFFF))
                            {
                                error_message = "invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF";
                                return token_type::parse_error;
                            }
                        }

                        // result of the above calculation yields a proper codepoint
                        JSON_ASSERT(0x00 <= codepoint && codepoint <= 0x10FFFF);

                        // translate codepoint into bytes
                        if (codepoint < 0x80)
                        {
                            // 1-byte characters: 0xxxxxxx (ASCII)
                            add(static_cast<char_int_type>(codepoint));
                        }
                        else if (codepoint <= 0x7FF)
                        {
                            // 2-byte characters: 110xxxxx 10xxxxxx
                            add(static_cast<char_int_type>(0xC0u | (static_cast<unsigned int>(codepoint) >> 6u)));
                            add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
                        }
                        else if (codepoint <= 0xFFFF)
                        {
                            // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
                            add(static_cast<char_int_type>(0xE0u | (static_cast<unsigned int>(codepoint) >> 12u)));
                            add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
                            add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
                        }
                        else
                        {
                            // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
                            add(static_cast<char_int_type>(0xF0u | (static_cast<unsigned int>(codepoint) >> 18u)));
                            add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 12u) & 0x3Fu)));
                            add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
                            add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
                        }

                        break;
                    }

                    // other characters after escape
                    default:
                        error_message = "invalid string: forbidden character after backslash";
                        return token_type::parse_error;
                }

                break;
            }

            // invalid control characters
            case 0x00:
            {
                error_message = "invalid string: control character U+0000 (NUL) must be escaped to \\u0000";
                return token_type::parse_error;
            }

            case 0x01:
            {
                error_message = "invalid string: control character U+0001 (SOH) must be escaped to \\u0001";
                return token_type::parse_error;
            }

            case 0x02:
            {
                error_message = "invalid string: control character U+0002 (STX) must be escaped to \\u0002";
                return token_type::parse_error;
            }

            case 0x03:
            {
                error_message = "invalid string: control character U+0003 (ETX) must be escaped to \\u0003";
                return token_type::parse_error;
            }

            case 0x04:
            {
                error_message = "invalid string: control character U+0004 (EOT) must be escaped to \\u0004";
                return token_type::parse_error;
            }

            case 0x05:
            {
                error_message = "invalid string: control character U+0005 (ENQ) must be escaped to \\u0005";
                return token_type::parse_error;
            }

            case 0x06:
            {
                error_message = "invalid string: control character U+0006 (ACK) must be escaped to \\u0006";
                return token_type::parse_error;
            }

            case 0x07:
            {
                error_message = "invalid string: control character U+0007 (BEL) must be escaped to \\u0007";
                return token_type::parse_error;
            }

            case 0x08:
            {
                error_message = "invalid string: control character U+0008 (BS) must be escaped to \\u0008 or \\b";
                return token_type::parse_error;
            }

            case 0x09:
            {
                error_message = "invalid string: control character U+0009 (HT) must be escaped to \\u0009 or \\t";
                return token_type::parse_error;
            }

            case 0x0A:
            {
                error_message = "invalid string: control character U+000A (LF) must be escaped to \\u000A or \\n";
                return token_type::parse_error;
            }

            case 0x0B:
            {
                error_message = "invalid string: control character U+000B (VT) must be escaped to \\u000B";
                return token_type::parse_error;
            }

            case 0x0C:
            {
                error_message = "invalid string: control character U+000C (FF) must be escaped to \\u000C or \\f";
                return token_type::parse_error;
            }

            case 0x0D:
            {
                error_message = "invalid string: control character U+000D (CR) must be escaped to \\u000D or \\r";
                return token_type::parse_error;
            }

            case 0x0E:
            {
                error_message = "invalid string: control character U+000E (SO) must be escaped to \\u000E";
                return token_type::parse_error;
            }

            case 0x0F:
            {
                error_message = "invalid string: control character U+000F (SI) must be escaped to \\u000F";
                return token_type::parse_error;
            }

            case 0x10:
            {
                error_message = "invalid string: control character U+0010 (DLE) must be escaped to \\u0010";
                return token_type::parse_error;
            }

            case 0x11:
            {
                error_message = "invalid string: control character U+0011 (DC1) must be escaped to \\u0011";
                return token_type::parse_error;
            }

            case 0x12:
            {
                error_message = "invalid string: control character U+0012 (DC2) must be escaped to \\u0012";
                return token_type::parse_error;
            }

            case 0x13:
            {
                error_message = "invalid string: control character U+0013 (DC3) must be escaped to \\u0013";
                return token_type::parse_error;
            }

            case 0x14:
            {
                error_message = "invalid string: control character U+0014 (DC4) must be escaped to \\u0014";
                return token_type::parse_error;
            }

            case 0x15:
            {
                error_message = "invalid string: control character U+0015 (NAK) must be escaped to \\u0015";
                return token_type::parse_error;
            }

            case 0x16:
            {
                error_message = "invalid string: control character U+0016 (SYN) must be escaped to \\u0016";
                return token_type::parse_error;
            }

            case 0x17:
            {
                error_message = "invalid string: control character U+0017 (ETB) must be escaped to \\u0017";
                return token_type::parse_error;
            }

            case 0x18:
            {
                error_message = "invalid string: control character U+0018 (CAN) must be escaped to \\u0018";
                return token_type::parse_error;
            }

            case 0x19:
            {
                error_message = "invalid string: control character U+0019 (EM) must be escaped to \\u0019";
                return token_type::parse_error;
            }

            case 0x1A:
            {
                error_message = "invalid string: control character U+001A (SUB) must be escaped to \\u001A";
                return token_type::parse_error;
            }

            case 0x1B:
            {
                error_message = "invalid string: control character U+001B (ESC) must be escaped to \\u001B";
                return token_type::parse_error;
            }

            case 0x1C:
            {
                error_message = "invalid string: control character U+001C (FS) must be escaped to \\u001C";
                return token_type::parse_error;
            }

            case 0x1D:
            {
                error_message = "invalid string: control character U+001D (GS) must be escaped to \\u001D";
                return token_type::parse_error;
            }

            case 0x1E:
            {
                error_message = "invalid string: control character U+001E (RS) must be escaped to \\u001E";
                return token_type::parse_error;
            }

            case 0x1F:
            {
                error_message = "invalid string: control character U+001F (US) must be escaped to \\u001F";
                return token_type::parse_error;
            }

            // U+0020..U+007F (except U+0022 (quote) and U+005C (backspace))
            case 0x20:
            case 0x21:
            case 0x23:
            case 0x24:
            case 0x25:
            case 0x26:
            case 0x27:
            case 0x28:
            case 0x29:
            case 0x2A:
            case 0x2B:
            case 0x2C:
            case 0x2D:
            case 0x2E:
            case 0x2F:
            case 0x30:
            case 0x31:
            case 0x32:
            case 0x33:
            case 0x34:
            case 0x35:
            case 0x36:
            case 0x37:
            case 0x38:
            case 0x39:
            case 0x3A:
            case 0x3B:
            case 0x3C:
            case 0x3D:
            case 0x3E:
            case 0x3F:
            case 0x40:
            case 0x41:
            case 0x42:
            case 0x43:
            case 0x44:
            case 0x45:
            case 0x46:
            case 0x47:
            case 0x48:
            case 0x49:
            case 0x4A:
            case 0x4B:
            case 0x4C:
            case 0x4D:
            case 0x4E:
            case 0x4F:
            case 0x50:
            case 0x51:
            case 0x52:
            case 0x53:
            case 0x54:
            case 0x55:
            case 0x56:
            case 0x57:
            case 0x58:
            case 0x59:
            case 0x5A:
            case 0x5B:
            case 0x5D:
            case 0x5E:
            case 0x5F:
            case 0x60:
            case 0x61:
            case 0x62:
            case 0x63:
            case 0x64:
            case 0x65:
            case 0x66:
            case 0x67:
            case 0x68:
            case 0x69:
            case 0x6A:
            case 0x6B:
            case 0x6C:
            case 0x6D:
            case 0x6E:
            case 0x6F:
            case 0x70:
            case 0x71:
            case 0x72:
            case 0x73:
            case 0x74:
            case 0x75:
            case 0x76:
            case 0x77:
            case 0x78:
            case 0x79:
            case 0x7A:
            case 0x7B:
            case 0x7C:
            case 0x7D:
            case 0x7E:
            case 0x7F:
            {
                add(current);
                break;
            }

            // U+0080..U+07FF: bytes C2..DF 80..BF
            case 0xC2:
            case 0xC3:
            case 0xC4:
            case 0xC5:
            case 0xC6:
            case 0xC7:
            case 0xC8:
            case 0xC9:
            case 0xCA:
            case 0xCB:
            case 0xCC:
            case 0xCD:
            case 0xCE:
            case 0xCF:
            case 0xD0:
            case 0xD1:
            case 0xD2:
            case 0xD3:
            case 0xD4:
            case 0xD5:
            case 0xD6:
            case 0xD7:
            case 0xD8:
            case 0xD9:
            case 0xDA:
            case 0xDB:
            case 0xDC:
            case 0xDD:
            case 0xDE:
            case 0xDF:
            {
                if (JSON_HEDLEY_UNLIKELY(!next_byte_in_range({0x80, 0xBF})))
                {
                    return token_type::parse_error;
                }
                break;
            }

            // U+0800..U+0FFF: bytes E0 A0..BF 80..BF
            case 0xE0:
            {
                if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF}))))
                {
                    return token_type::parse_error;
                }
                break;
            }

            // U+1000..U+CFFF: bytes E1..EC 80..BF 80..BF
            // U+E000..U+FFFF: bytes EE..EF 80..BF 80..BF
            case 0xE1:
            case 0xE2:
            case 0xE3:
            case 0xE4:
            case 0xE5:
            case 0xE6:
            case 0xE7:
            case 0xE8:
            case 0xE9:
            case 0xEA:
            case 0xEB:
            case 0xEC:
            case 0xEE:
            case 0xEF:
            {
                if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF}))))
                {
                    return token_type::parse_error;
                }
                break;
            }

            // U+D000..U+D7FF: bytes ED 80..9F 80..BF
            case 0xED:
            {
                if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x9F, 0x80, 0xBF}))))
                {
                    return token_type::parse_error;
                }
                break;
            }

            // U+10000..U+3FFFF F0 90..BF 80..BF 80..BF
            case 0xF0:
            {
                if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
                {
                    return token_type::parse_error;
                }
                break;
            }

            // U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF
            case 0xF1:
            case 0xF2:
            case 0xF3:
            {
                if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
                {
                    return token_type::parse_error;
                }
                break;
            }

            // U+100000..U+10FFFF F4 80..8F 80..BF 80..BF
            case 0xF4:
            {
                if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF}))))
                {
                    return token_type::parse_error;
                }
                break;
            }

            // remaining bytes (80..C1 and F5..FF) are ill-formed
            default:
            {
                error_message = "invalid string: ill-formed UTF-8 byte";
                return token_type::parse_error;
            }
        }
    }
}

Fallacies:

None

Graph:

No Historic Data Found


NPF-03.1#

The service ignores leading and trailing whitespace.

Supported Requests:

Supporting Items:

None

References:

  • cpp-test: [parse;whitespace] (TSF/tests/unit-strings.cpp)

SECTION("whitespace")
{
    // leading and trailing whitespace is ignored.
    CHECK(json::parse(" \"foo\" ")==json::parse("\"foo\""));
    CHECK(json::parse(" \"foo\"\t")==json::parse("\"foo\""));
    CHECK(json::parse(" \"foo\"\n")==json::parse("\"foo\""));
    CHECK(json::parse(" \"foo\"\u000d")==json::parse("\"foo\""));
    CHECK(json::parse("\t\"foo\" ")==json::parse("\"foo\""));
    CHECK(json::parse("\t\"foo\"\t")==json::parse("\"foo\""));
    CHECK(json::parse("\t\"foo\"\n")==json::parse("\"foo\""));
    CHECK(json::parse("\t\"foo\"\u000d")==json::parse("\"foo\""));
    CHECK(json::parse("\n\"foo\" ")==json::parse("\"foo\""));
    CHECK(json::parse("\n\"foo\"\t")==json::parse("\"foo\""));
    CHECK(json::parse("\n\"foo\"\n")==json::parse("\"foo\""));
    CHECK(json::parse("\n\"foo\"\u000d")==json::parse("\"foo\""));
    CHECK(json::parse("\u000d\"foo\" ")==json::parse("\"foo\""));
    CHECK(json::parse("\u000d\"foo\"\t")==json::parse("\"foo\""));
    CHECK(json::parse("\u000d\"foo\"\n")==json::parse("\"foo\""));
    CHECK(json::parse("\u000d\"foo\"\u000d")==json::parse("\"foo\""));
}
  • function: [lexer::skip_whitespace] (include/nlohmann/detail/input/lexer.hpp)

    • Description: function, which skips admissible whitespace during reading

void skip_whitespace()
{
    do
    {
        get();
    }
    while (current == ' ' || current == '\t' || current == '\n' || current == '\r');
}

Fallacies:

None

Graph:

No Historic Data Found


NPF-03.2#

The service parses escaped characters in the basic multilingual plane.

Supported Requests:

Supporting Items:

None

References:

  • cpp-test: [parser class - core;parse;string;escaped] (TSF/tests/unit-class_parser_core.cpp)

SECTION("escaped")
{
    // quotation mark "\""
    auto r1 = R"("\"")"_json;
    CHECK(parser_helper("\"\\\"\"") == r1);
    // reverse solidus "\\"
    auto r2 = R"("\\")"_json;
    CHECK(parser_helper("\"\\\\\"") == r2);
    // solidus
    CHECK(parser_helper("\"\\/\"") == R"("/")"_json);
    // backspace
    CHECK(parser_helper("\"\\b\"") == json("\b"));
    // formfeed
    CHECK(parser_helper("\"\\f\"") == json("\f"));
    // newline
    CHECK(parser_helper("\"\\n\"") == json("\n"));
    // carriage return
    CHECK(parser_helper("\"\\r\"") == json("\r"));
    // horizontal tab
    CHECK(parser_helper("\"\\t\"") == json("\t"));

    CHECK(parser_helper("\"\\u0001\"").get<json::string_t>() == "\x01");
    CHECK(parser_helper("\"\\u000a\"").get<json::string_t>() == "\n");
    CHECK(parser_helper("\"\\u00b0\"").get<json::string_t>() == "°");
    CHECK(parser_helper("\"\\u0c00\"").get<json::string_t>() == "ఀ");
    CHECK(parser_helper("\"\\ud000\"").get<json::string_t>() == "퀀");
    CHECK(parser_helper("\"\\u000E\"").get<json::string_t>() == "\x0E");
    CHECK(parser_helper("\"\\u00F0\"").get<json::string_t>() == "ð");
    CHECK(parser_helper("\"\\u0100\"").get<json::string_t>() == "Ā");
    CHECK(parser_helper("\"\\u2000\"").get<json::string_t>() == " ");
    CHECK(parser_helper("\"\\uFFFF\"").get<json::string_t>() == "￿");
    CHECK(parser_helper("\"\\u20AC\"").get<json::string_t>() == "€");
    CHECK(parser_helper("\"\"").get<json::string_t>() == "€");
    CHECK(parser_helper("\"🎈\"").get<json::string_t>() == "🎈");

    CHECK(parser_helper("\"\\ud80c\\udc60\"").get<json::string_t>() == "\xf0\x93\x81\xa0");
    CHECK(parser_helper("\"\\ud83c\\udf1e\"").get<json::string_t>() == "🌞");
}
  • cpp-test: [compliance tests from nativejson-benchmark;strings] (tests/src/unit-testsuites.cpp)

SECTION("strings")
{
    auto TEST_STRING = [](const std::string & json_string, const std::string & expected)
    {
        CAPTURE(json_string)
        CAPTURE(expected)
        CHECK(json::parse(json_string)[0].get<std::string>() == expected);
    };

    TEST_STRING("[\"\"]", "");
    TEST_STRING("[\"Hello\"]", "Hello");
    TEST_STRING(R"(["Hello\nWorld"])", "Hello\nWorld");
    //TEST_STRING("[\"Hello\\u0000World\"]", "Hello\0World");
    TEST_STRING(R"(["\"\\/\b\f\n\r\t"])", "\"\\/\b\f\n\r\t");
    TEST_STRING(R"(["\u0024"])", "$");         // Dollar sign U+0024
    TEST_STRING(R"(["\u00A2"])", "\xC2\xA2");     // Cents sign U+00A2
    TEST_STRING(R"(["\u20AC"])", "\xE2\x82\xAC"); // Euro sign U+20AC
    TEST_STRING(R"(["\uD834\uDD1E"])", "\xF0\x9D\x84\x9E");  // G clef sign U+1D11E
}
  • cpp-test: [Unicode (1/5);\\uxxxx sequences;correct sequences] (tests/src/unit-unicode1.cpp)

SECTION("correct sequences")
{
    // generate all UTF-8 code points; in total, 1112064 code points are
    // generated: 0x1FFFFF code points - 2048 invalid values between
    // 0xD800 and 0xDFFF.
    for (std::size_t cp = 0; cp <= 0x10FFFFu; ++cp)
    {
        // string to store the code point as in \uxxxx format
        std::string json_text = "\"";

        // decide whether to use one or two \uxxxx sequences
        if (cp < 0x10000u)
        {
            // The Unicode standard permanently reserves these code point
            // values for UTF-16 encoding of the high and low surrogates, and
            // they will never be assigned a character, so there should be no
            // reason to encode them. The official Unicode standard says that
            // no UTF forms, including UTF-16, can encode these code points.
            if (cp >= 0xD800u && cp <= 0xDFFFu)
            {
                // if we would not skip these code points, we would get a
                // "missing low surrogate" exception
                continue;
            }

            // code points in the Basic Multilingual Plane can be
            // represented with one \uxxxx sequence
            json_text += codepoint_to_unicode(cp);
        }
        else
        {
            // To escape an extended character that is not in the Basic
            // Multilingual Plane, the character is represented as a
            // 12-character sequence, encoding the UTF-16 surrogate pair
            const auto codepoint1 = 0xd800u + (((cp - 0x10000u) >> 10) & 0x3ffu);
            const auto codepoint2 = 0xdc00u + ((cp - 0x10000u) & 0x3ffu);
            json_text += codepoint_to_unicode(codepoint1) + codepoint_to_unicode(codepoint2);
        }

        json_text += "\"";
        CAPTURE(json_text)
        json _;
        CHECK_NOTHROW(_ = json::parse(json_text));
    }
}

Fallacies:

None

Graph:

No Historic Data Found


NPF-03.3#

The service ignores capitalisation in escaped hexadecimal unicode.

Supported Requests:

Supporting Items:

None

References:

  • cpp-test: [Unicode;escaped unicode] (TSF/tests/unit-strings.cpp)

SECTION("escaped unicode")
{
    for (uint32_t i = 0x0000; i<=0xFFFF; i++)
    {
        std::ostringstream temp;
        std::ostringstream temp2;
        temp << "\"\\u" << std::hex << std::uppercase << std::setfill('0') << std::setw(4) << i << "\"";
        temp2 << "\"\\u" << std::hex << std::nouppercase << std::setfill('0') << std::setw(4) << i << "\"";
        if (i>=0xD800 && i<=0xDFFF)
        {
            // Unpaired utf-16 surrogates are illegal.
            // Observe that this verbatim not what RFC8259 §7 prescribes; 
            // it appears, however, to be in the spirit of RFC8259, cf. §8.2 
            // Illegal characters are not parsed anyway.
            CHECK(!json::accept(temp.str()));
            CHECK(!json::accept(temp2.str()));
            CHECK_THROWS_AS(parser_helper(temp.str()),json::parse_error&);
            CHECK_THROWS_AS(parser_helper(temp2.str()),json::parse_error&);
        } else { 
            // all other characters of the basic multilingual plane are accepted.
            CHECK(json::accept(temp.str()));
            CHECK(json::accept(temp2.str()));
            CHECK(json::parse(temp.str())==json::parse(temp2.str()));
        }
    }
}

Fallacies:

None

Graph:

No Historic Data Found


NPF-03.4#

The service parses all unescaped utf-8 characters except quotation mark, reverse solidus and the control characters.

Supported Requests:

Supporting Items:

None

References:

  • cpp-test: [RFC 8259 examples;7. Strings] (tests/src/unit-testsuites.cpp)

SECTION("7. Strings")
{
    CHECK(json::parse("\"\\u005C\"") == json("\\"));
    CHECK(json::parse("\"\\uD834\\uDD1E\"") == json("𝄞"));
    CHECK(json::parse("\"𝄞\"") == json("𝄞"));
}
  • cpp-testsuite: [/json_nlohmann_tests/all_unicode.json]

    • JSON Testsuite: /json_nlohmann_tests/all_unicode.json

    Link to file [Content too large - 1112068 lines]

    • cpp-test: [Unicode (1/5);read all unicode characters] (tests/src/unit-unicode1.cpp)

    SECTION("read all unicode characters")
    {
        // read a file with all Unicode characters stored as single-character
        // strings in a JSON array
        std::ifstream f(TEST_DATA_DIRECTORY "/json_nlohmann_tests/all_unicode.json");
        json j;
        CHECK_NOTHROW(f >> j);
    
        // the array has 1112064 + 1 elements (a terminating "null" value)
        // Note: 1112064 = 0x1FFFFF code points - 2048 invalid values between
        // 0xD800 and 0xDFFF.
        CHECK(j.size() == 1112065);
    
        SECTION("check JSON Pointers")
        {
            for (const auto& s : j)
            {
                // skip non-string JSON values
                if (!s.is_string())
                {
                    continue;
                }
    
                auto ptr = s.get<std::string>();
    
                // tilde must be followed by 0 or 1
                if (ptr == "~")
                {
                    ptr += "0";
                }
    
                // JSON Pointers must begin with "/"
                ptr.insert(0, "/");
    
                CHECK_NOTHROW(json::json_pointer("/" + ptr));
    
                // check escape/unescape roundtrip
                auto escaped = nlohmann::detail::escape(ptr);
                nlohmann::detail::unescape(escaped);
                CHECK(escaped == ptr);
            }
        }
    }
    
  • cpp-test: [Unicode;unescaped unicode] (TSF/tests/unit-strings.cpp)

SECTION("unescaped unicode")
{
    for (uint32_t i = 0x0000; i<=0x10FFFF; i++)
    {
        std::string temp = uint_to_utf8(i);
        if ((i>=0xD800 && i<=0xDFFF)) { 
            // Unpaired utf-16 surrogates are illegal.
            // Observe that this verbatim not what RFC8259 §7 prescribes; 
            // it appears, however, to be in the spirit of RFC8259, cf. §8.2 
            // The other characters are illegal if unescaped.
            CHECK(!json::accept(temp));
            CHECK_THROWS_AS(parser_helper(temp),json::parse_error&);
            if (i<=0xDBFF){
                for (uint32_t j = 0xDC00; j<=0xDFFF; j++){
                    temp += uint_to_utf8(j);
                    CHECK(!json::accept(temp));
                    CHECK_THROWS_AS(parser_helper(temp),json::parse_error&);
                }
            } 
        } else if (i<0x0020||i==0x0022||i==0x005c){
            CHECK(!json::accept(temp));
            CHECK_THROWS_AS(parser_helper(temp),json::parse_error&);
        } else {
            // All other characters are valid according to RFC8259
            CHECK_NOTHROW(parser_helper(temp));
        }
    }
}

Fallacies:

None

Graph:

No Historic Data Found


NPF-03.5#

The service parses \, \/, \b,\f, \n, \r, \t and escaped quotation marks.

Supported Requests:

Supporting Items:

None

References:

  • cpp-test: [compliance tests from nativejson-benchmark;strings] (tests/src/unit-testsuites.cpp)

SECTION("strings")
{
    auto TEST_STRING = [](const std::string & json_string, const std::string & expected)
    {
        CAPTURE(json_string)
        CAPTURE(expected)
        CHECK(json::parse(json_string)[0].get<std::string>() == expected);
    };

    TEST_STRING("[\"\"]", "");
    TEST_STRING("[\"Hello\"]", "Hello");
    TEST_STRING(R"(["Hello\nWorld"])", "Hello\nWorld");
    //TEST_STRING("[\"Hello\\u0000World\"]", "Hello\0World");
    TEST_STRING(R"(["\"\\/\b\f\n\r\t"])", "\"\\/\b\f\n\r\t");
    TEST_STRING(R"(["\u0024"])", "$");         // Dollar sign U+0024
    TEST_STRING(R"(["\u00A2"])", "\xC2\xA2");     // Cents sign U+00A2
    TEST_STRING(R"(["\u20AC"])", "\xE2\x82\xAC"); // Euro sign U+20AC
    TEST_STRING(R"(["\uD834\uDD1E"])", "\xF0\x9D\x84\x9E");  // G clef sign U+1D11E
}
  • cpp-test: [parser class - core;parse;string;escaped] (TSF/tests/unit-class_parser_core.cpp)

SECTION("escaped")
{
    // quotation mark "\""
    auto r1 = R"("\"")"_json;
    CHECK(parser_helper("\"\\\"\"") == r1);
    // reverse solidus "\\"
    auto r2 = R"("\\")"_json;
    CHECK(parser_helper("\"\\\\\"") == r2);
    // solidus
    CHECK(parser_helper("\"\\/\"") == R"("/")"_json);
    // backspace
    CHECK(parser_helper("\"\\b\"") == json("\b"));
    // formfeed
    CHECK(parser_helper("\"\\f\"") == json("\f"));
    // newline
    CHECK(parser_helper("\"\\n\"") == json("\n"));
    // carriage return
    CHECK(parser_helper("\"\\r\"") == json("\r"));
    // horizontal tab
    CHECK(parser_helper("\"\\t\"") == json("\t"));

    CHECK(parser_helper("\"\\u0001\"").get<json::string_t>() == "\x01");
    CHECK(parser_helper("\"\\u000a\"").get<json::string_t>() == "\n");
    CHECK(parser_helper("\"\\u00b0\"").get<json::string_t>() == "°");
    CHECK(parser_helper("\"\\u0c00\"").get<json::string_t>() == "ఀ");
    CHECK(parser_helper("\"\\ud000\"").get<json::string_t>() == "퀀");
    CHECK(parser_helper("\"\\u000E\"").get<json::string_t>() == "\x0E");
    CHECK(parser_helper("\"\\u00F0\"").get<json::string_t>() == "ð");
    CHECK(parser_helper("\"\\u0100\"").get<json::string_t>() == "Ā");
    CHECK(parser_helper("\"\\u2000\"").get<json::string_t>() == " ");
    CHECK(parser_helper("\"\\uFFFF\"").get<json::string_t>() == "￿");
    CHECK(parser_helper("\"\\u20AC\"").get<json::string_t>() == "€");
    CHECK(parser_helper("\"\"").get<json::string_t>() == "€");
    CHECK(parser_helper("\"🎈\"").get<json::string_t>() == "🎈");

    CHECK(parser_helper("\"\\ud80c\\udc60\"").get<json::string_t>() == "\xf0\x93\x81\xa0");
    CHECK(parser_helper("\"\\ud83c\\udf1e\"").get<json::string_t>() == "🌞");
}

Fallacies:

None

Graph:

No Historic Data Found


NPF-03.6#

The service parses the empty string.

Supported Requests:

Supporting Items:

None

References:

  • cpp-test: [parser class - core;parse;string] (TSF/tests/unit-class_parser_core.cpp)

SECTION("string")
{
    // empty string
    CHECK(parser_helper("\"\"") == json(json::value_t::string));

    SECTION("errors")
    {
        // error: tab in string
        CHECK_THROWS_WITH_AS(parser_helper("\"\t\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0009 (HT) must be escaped to \\u0009 or \\t; last read: '\"<U+0009>'", json::parse_error&);
        // error: newline in string
        CHECK_THROWS_WITH_AS(parser_helper("\"\n\""), "[json.exception.parse_error.101] parse error at line 2, column 0: syntax error while parsing value - invalid string: control character U+000A (LF) must be escaped to \\u000A or \\n; last read: '\"<U+000A>'", json::parse_error&);
        CHECK_THROWS_WITH_AS(parser_helper("\"\r\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+000D (CR) must be escaped to \\u000D or \\r; last read: '\"<U+000D>'", json::parse_error&);
        // error: backspace in string
        CHECK_THROWS_WITH_AS(parser_helper("\"\b\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0008 (BS) must be escaped to \\u0008 or \\b; last read: '\"<U+0008>'", json::parse_error&);
        // improve code coverage
        CHECK_THROWS_AS(parser_helper("\uFF01"), json::parse_error&);
        CHECK_THROWS_AS(parser_helper("[-4:1,]"), json::parse_error&);
        // unescaped control characters
        CHECK_THROWS_WITH_AS(parser_helper("\"\x00\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: missing closing quote; last read: '\"'", json::parse_error&); // NOLINT(bugprone-string-literal-with-embedded-nul)
        CHECK_THROWS_WITH_AS(parser_helper("\"\x01\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0001 (SOH) must be escaped to \\u0001; last read: '\"<U+0001>'", json::parse_error&);
        CHECK_THROWS_WITH_AS(parser_helper("\"\x02\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0002 (STX) must be escaped to \\u0002; last read: '\"<U+0002>'", json::parse_error&);
        CHECK_THROWS_WITH_AS(parser_helper("\"\x03\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0003 (ETX) must be escaped to \\u0003; last read: '\"<U+0003>'", json::parse_error&);
        CHECK_THROWS_WITH_AS(parser_helper("\"\x04\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0004 (EOT) must be escaped to \\u0004; last read: '\"<U+0004>'", json::parse_error&);
        CHECK_THROWS_WITH_AS(parser_helper("\"\x05\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0005 (ENQ) must be escaped to \\u0005; last read: '\"<U+0005>'", json::parse_error&);
        CHECK_THROWS_WITH_AS(parser_helper("\"\x06\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0006 (ACK) must be escaped to \\u0006; last read: '\"<U+0006>'", json::parse_error&);
        CHECK_THROWS_WITH_AS(parser_helper("\"\x07\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0007 (BEL) must be escaped to \\u0007; last read: '\"<U+0007>'", json::parse_error&);
        CHECK_THROWS_WITH_AS(parser_helper("\"\x08\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0008 (BS) must be escaped to \\u0008 or \\b; last read: '\"<U+0008>'", json::parse_error&);
        CHECK_THROWS_WITH_AS(parser_helper("\"\x09\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0009 (HT) must be escaped to \\u0009 or \\t; last read: '\"<U+0009>'", json::parse_error&);
        CHECK_THROWS_WITH_AS(parser_helper("\"\x0a\""), "[json.exception.parse_error.101] parse error at line 2, column 0: syntax error while parsing value - invalid string: control character U+000A (LF) must be escaped to \\u000A or \\n; last read: '\"<U+000A>'", json::parse_error&);
        CHECK_THROWS_WITH_AS(parser_helper("\"\x0b\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+000B (VT) must be escaped to \\u000B; last read: '\"<U+000B>'", json::parse_error&);
        CHECK_THROWS_WITH_AS(parser_helper("\"\x0c\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+000C (FF) must be escaped to \\u000C or \\f; last read: '\"<U+000C>'", json::parse_error&);
        CHECK_THROWS_WITH_AS(parser_helper("\"\x0d\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+000D (CR) must be escaped to \\u000D or \\r; last read: '\"<U+000D>'", json::parse_error&);
        CHECK_THROWS_WITH_AS(parser_helper("\"\x0e\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+000E (SO) must be escaped to \\u000E; last read: '\"<U+000E>'", json::parse_error&);
        CHECK_THROWS_WITH_AS(parser_helper("\"\x0f\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+000F (SI) must be escaped to \\u000F; last read: '\"<U+000F>'", json::parse_error&);
        CHECK_THROWS_WITH_AS(parser_helper("\"\x10\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0010 (DLE) must be escaped to \\u0010; last read: '\"<U+0010>'", json::parse_error&);
        CHECK_THROWS_WITH_AS(parser_helper("\"\x11\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0011 (DC1) must be escaped to \\u0011; last read: '\"<U+0011>'", json::parse_error&);
        CHECK_THROWS_WITH_AS(parser_helper("\"\x12\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0012 (DC2) must be escaped to \\u0012; last read: '\"<U+0012>'", json::parse_error&);
        CHECK_THROWS_WITH_AS(parser_helper("\"\x13\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0013 (DC3) must be escaped to \\u0013; last read: '\"<U+0013>'", json::parse_error&);
        CHECK_THROWS_WITH_AS(parser_helper("\"\x14\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0014 (DC4) must be escaped to \\u0014; last read: '\"<U+0014>'", json::parse_error&);
        CHECK_THROWS_WITH_AS(parser_helper("\"\x15\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0015 (NAK) must be escaped to \\u0015; last read: '\"<U+0015>'", json::parse_error&);
        CHECK_THROWS_WITH_AS(parser_helper("\"\x16\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0016 (SYN) must be escaped to \\u0016; last read: '\"<U+0016>'", json::parse_error&);
        CHECK_THROWS_WITH_AS(parser_helper("\"\x17\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0017 (ETB) must be escaped to \\u0017; last read: '\"<U+0017>'", json::parse_error&);
        CHECK_THROWS_WITH_AS(parser_helper("\"\x18\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0018 (CAN) must be escaped to \\u0018; last read: '\"<U+0018>'", json::parse_error&);
        CHECK_THROWS_WITH_AS(parser_helper("\"\x19\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0019 (EM) must be escaped to \\u0019; last read: '\"<U+0019>'", json::parse_error&);
        CHECK_THROWS_WITH_AS(parser_helper("\"\x1a\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+001A (SUB) must be escaped to \\u001A; last read: '\"<U+001A>'", json::parse_error&);
        CHECK_THROWS_WITH_AS(parser_helper("\"\x1b\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+001B (ESC) must be escaped to \\u001B; last read: '\"<U+001B>'", json::parse_error&);
        CHECK_THROWS_WITH_AS(parser_helper("\"\x1c\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+001C (FS) must be escaped to \\u001C; last read: '\"<U+001C>'", json::parse_error&);
        CHECK_THROWS_WITH_AS(parser_helper("\"\x1d\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+001D (GS) must be escaped to \\u001D; last read: '\"<U+001D>'", json::parse_error&);
        CHECK_THROWS_WITH_AS(parser_helper("\"\x1e\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+001E (RS) must be escaped to \\u001E; last read: '\"<U+001E>'", json::parse_error&);
        CHECK_THROWS_WITH_AS(parser_helper("\"\x1f\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+001F (US) must be escaped to \\u001F; last read: '\"<U+001F>'", json::parse_error&);

        SECTION("additional test for null byte")
        {
            // The test above for the null byte is wrong, because passing
            // a string to the parser only reads int until it encounters
            // a null byte. This test inserts the null byte later on and
            // uses an iterator range.
            std::string s = "\"1\"";
            s[1] = '\0';
            json _;
            CHECK_THROWS_WITH_AS(_ = json::parse(s.begin(), s.end()), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0000 (NUL) must be escaped to \\u0000; last read: '\"<U+0000>'", json::parse_error&);
        }
    }

    SECTION("escaped")
    {
        // quotation mark "\""
        auto r1 = R"("\"")"_json;
        CHECK(parser_helper("\"\\\"\"") == r1);
        // reverse solidus "\\"
        auto r2 = R"("\\")"_json;
        CHECK(parser_helper("\"\\\\\"") == r2);
        // solidus
        CHECK(parser_helper("\"\\/\"") == R"("/")"_json);
        // backspace
        CHECK(parser_helper("\"\\b\"") == json("\b"));
        // formfeed
        CHECK(parser_helper("\"\\f\"") == json("\f"));
        // newline
        CHECK(parser_helper("\"\\n\"") == json("\n"));
        // carriage return
        CHECK(parser_helper("\"\\r\"") == json("\r"));
        // horizontal tab
        CHECK(parser_helper("\"\\t\"") == json("\t"));

        CHECK(parser_helper("\"\\u0001\"").get<json::string_t>() == "\x01");
        CHECK(parser_helper("\"\\u000a\"").get<json::string_t>() == "\n");
        CHECK(parser_helper("\"\\u00b0\"").get<json::string_t>() == "°");
        CHECK(parser_helper("\"\\u0c00\"").get<json::string_t>() == "ఀ");
        CHECK(parser_helper("\"\\ud000\"").get<json::string_t>() == "퀀");
        CHECK(parser_helper("\"\\u000E\"").get<json::string_t>() == "\x0E");
        CHECK(parser_helper("\"\\u00F0\"").get<json::string_t>() == "ð");
        CHECK(parser_helper("\"\\u0100\"").get<json::string_t>() == "Ā");
        CHECK(parser_helper("\"\\u2000\"").get<json::string_t>() == " ");
        CHECK(parser_helper("\"\\uFFFF\"").get<json::string_t>() == "￿");
        CHECK(parser_helper("\"\\u20AC\"").get<json::string_t>() == "€");
        CHECK(parser_helper("\"\"").get<json::string_t>() == "€");
        CHECK(parser_helper("\"🎈\"").get<json::string_t>() == "🎈");

        CHECK(parser_helper("\"\\ud80c\\udc60\"").get<json::string_t>() == "\xf0\x93\x81\xa0");
        CHECK(parser_helper("\"\\ud83c\\udf1e\"").get<json::string_t>() == "🌞");
    }
}

Fallacies:

None

Graph:

No Historic Data Found


NPF-03.7#

The service parses non-empty strings.

Supported Requests:

Supporting Items:

None

References:

  • cpp-test: [parser class - core;parse;string;escaped] (TSF/tests/unit-class_parser_core.cpp)

SECTION("escaped")
{
    // quotation mark "\""
    auto r1 = R"("\"")"_json;
    CHECK(parser_helper("\"\\\"\"") == r1);
    // reverse solidus "\\"
    auto r2 = R"("\\")"_json;
    CHECK(parser_helper("\"\\\\\"") == r2);
    // solidus
    CHECK(parser_helper("\"\\/\"") == R"("/")"_json);
    // backspace
    CHECK(parser_helper("\"\\b\"") == json("\b"));
    // formfeed
    CHECK(parser_helper("\"\\f\"") == json("\f"));
    // newline
    CHECK(parser_helper("\"\\n\"") == json("\n"));
    // carriage return
    CHECK(parser_helper("\"\\r\"") == json("\r"));
    // horizontal tab
    CHECK(parser_helper("\"\\t\"") == json("\t"));

    CHECK(parser_helper("\"\\u0001\"").get<json::string_t>() == "\x01");
    CHECK(parser_helper("\"\\u000a\"").get<json::string_t>() == "\n");
    CHECK(parser_helper("\"\\u00b0\"").get<json::string_t>() == "°");
    CHECK(parser_helper("\"\\u0c00\"").get<json::string_t>() == "ఀ");
    CHECK(parser_helper("\"\\ud000\"").get<json::string_t>() == "퀀");
    CHECK(parser_helper("\"\\u000E\"").get<json::string_t>() == "\x0E");
    CHECK(parser_helper("\"\\u00F0\"").get<json::string_t>() == "ð");
    CHECK(parser_helper("\"\\u0100\"").get<json::string_t>() == "Ā");
    CHECK(parser_helper("\"\\u2000\"").get<json::string_t>() == " ");
    CHECK(parser_helper("\"\\uFFFF\"").get<json::string_t>() == "￿");
    CHECK(parser_helper("\"\\u20AC\"").get<json::string_t>() == "€");
    CHECK(parser_helper("\"\"").get<json::string_t>() == "€");
    CHECK(parser_helper("\"🎈\"").get<json::string_t>() == "🎈");

    CHECK(parser_helper("\"\\ud80c\\udc60\"").get<json::string_t>() == "\xf0\x93\x81\xa0");
    CHECK(parser_helper("\"\\ud83c\\udf1e\"").get<json::string_t>() == "🌞");
}
  • cpp-test: [compliance tests from nativejson-benchmark;strings] (tests/src/unit-testsuites.cpp)

SECTION("strings")
{
    auto TEST_STRING = [](const std::string & json_string, const std::string & expected)
    {
        CAPTURE(json_string)
        CAPTURE(expected)
        CHECK(json::parse(json_string)[0].get<std::string>() == expected);
    };

    TEST_STRING("[\"\"]", "");
    TEST_STRING("[\"Hello\"]", "Hello");
    TEST_STRING(R"(["Hello\nWorld"])", "Hello\nWorld");
    //TEST_STRING("[\"Hello\\u0000World\"]", "Hello\0World");
    TEST_STRING(R"(["\"\\/\b\f\n\r\t"])", "\"\\/\b\f\n\r\t");
    TEST_STRING(R"(["\u0024"])", "$");         // Dollar sign U+0024
    TEST_STRING(R"(["\u00A2"])", "\xC2\xA2");     // Cents sign U+00A2
    TEST_STRING(R"(["\u20AC"])", "\xE2\x82\xAC"); // Euro sign U+20AC
    TEST_STRING(R"(["\uD834\uDD1E"])", "\xF0\x9D\x84\x9E");  // G clef sign U+1D11E
}
  • cpp-test: [RFC 8259 examples;7. Strings] (tests/src/unit-testsuites.cpp)

SECTION("7. Strings")
{
    CHECK(json::parse("\"\\u005C\"") == json("\\"));
    CHECK(json::parse("\"\\uD834\\uDD1E\"") == json("𝄞"));
    CHECK(json::parse("\"𝄞\"") == json("𝄞"));
}
  • cpp-testsuite: [/nst_json_testsuite2/test_parsing/y_string_1_2_3_bytes_UTF-8_sequences.json, /nst_json_testsuite2/test_parsing/y_string_accepted_surrogate_pair.json, /nst_json_testsuite2/test_parsing/y_string_accepted_surrogate_pairs.json, /nst_json_testsuite2/test_parsing/y_string_allowed_escapes.json, /nst_json_testsuite2/test_parsing/y_string_backslash_and_u_escaped_zero.json, /nst_json_testsuite2/test_parsing/y_string_backslash_doublequotes.json, /nst_json_testsuite2/test_parsing/y_string_comments.json, /nst_json_testsuite2/test_parsing/y_string_double_escape_a.json, /nst_json_testsuite2/test_parsing/y_string_double_escape_n.json, /nst_json_testsuite2/test_parsing/y_string_escaped_control_character.json, /nst_json_testsuite2/test_parsing/y_string_escaped_noncharacter.json, /nst_json_testsuite2/test_parsing/y_string_in_array.json, /nst_json_testsuite2/test_parsing/y_string_in_array_with_leading_space.json, /nst_json_testsuite2/test_parsing/y_string_last_surrogates_1_and_2.json, /nst_json_testsuite2/test_parsing/y_string_nbsp_uescaped.json, /nst_json_testsuite2/test_parsing/y_string_nonCharacterInUTF-8_U+10FFFF.json, /nst_json_testsuite2/test_parsing/y_string_nonCharacterInUTF-8_U+FFFF.json, /nst_json_testsuite2/test_parsing/y_string_null_escape.json, /nst_json_testsuite2/test_parsing/y_string_one-byte-utf-8.json, /nst_json_testsuite2/test_parsing/y_string_pi.json, /nst_json_testsuite2/test_parsing/y_string_reservedCharacterInUTF-8_U+1BFFF.json, /nst_json_testsuite2/test_parsing/y_string_simple_ascii.json, /nst_json_testsuite2/test_parsing/y_string_space.json, /nst_json_testsuite2/test_parsing/y_string_surrogates_U+1D11E_MUSICAL_SYMBOL_G_CLEF.json, /nst_json_testsuite2/test_parsing/y_string_three-byte-utf-8.json, /nst_json_testsuite2/test_parsing/y_string_two-byte-utf-8.json, /nst_json_testsuite2/test_parsing/y_string_u+2028_line_sep.json, /nst_json_testsuite2/test_parsing/y_string_u+2029_par_sep.json, /nst_json_testsuite2/test_parsing/y_string_uEscape.json, /nst_json_testsuite2/test_parsing/y_string_uescaped_newline.json, /nst_json_testsuite2/test_parsing/y_string_unescaped_char_delete.json, /nst_json_testsuite2/test_parsing/y_string_unicode.json, /nst_json_testsuite2/test_parsing/y_string_unicodeEscapedBackslash.json, /nst_json_testsuite2/test_parsing/y_string_unicode_2.json, /nst_json_testsuite2/test_parsing/y_string_unicode_U+10FFFE_nonchar.json, /nst_json_testsuite2/test_parsing/y_string_unicode_U+1FFFE_nonchar.json, /nst_json_testsuite2/test_parsing/y_string_unicode_U+200B_ZERO_WIDTH_SPACE.json, /nst_json_testsuite2/test_parsing/y_string_unicode_U+2064_invisible_plus.json, /nst_json_testsuite2/test_parsing/y_string_unicode_U+FDD0_nonchar.json, /nst_json_testsuite2/test_parsing/y_string_unicode_U+FFFE_nonchar.json, /nst_json_testsuite2/test_parsing/y_string_unicode_escaped_double_quote.json, /nst_json_testsuite2/test_parsing/y_string_utf8.json, /nst_json_testsuite2/test_parsing/y_string_with_del_character.json]

    • Description: Tests whether several non-empty strings are parsed without throwing an exception.

    • JSON Testsuite: /nst_json_testsuite2/test_parsing/y_string_1_2_3_bytes_UTF-8_sequences.json

    ["\u0060\u012a\u12AB"]
    
    • JSON Testsuite: /nst_json_testsuite2/test_parsing/y_string_accepted_surrogate_pair.json

    ["\uD801\udc37"]
    
    • JSON Testsuite: /nst_json_testsuite2/test_parsing/y_string_accepted_surrogate_pairs.json

    ["\ud83d\ude39\ud83d\udc8d"]
    
    • JSON Testsuite: /nst_json_testsuite2/test_parsing/y_string_allowed_escapes.json

    ["\"\\\/\b\f\n\r\t"]
    
    • JSON Testsuite: /nst_json_testsuite2/test_parsing/y_string_backslash_and_u_escaped_zero.json

    ["\\u0000"]
    
    • JSON Testsuite: /nst_json_testsuite2/test_parsing/y_string_backslash_doublequotes.json

    ["\""]
    
    • JSON Testsuite: /nst_json_testsuite2/test_parsing/y_string_comments.json

    ["a/*b*/c/*d//e"]
    
    • JSON Testsuite: /nst_json_testsuite2/test_parsing/y_string_double_escape_a.json

    ["\\a"]
    
    • JSON Testsuite: /nst_json_testsuite2/test_parsing/y_string_double_escape_n.json

    ["\\n"]
    
    • JSON Testsuite: /nst_json_testsuite2/test_parsing/y_string_escaped_control_character.json

    ["\u0012"]
    
    • JSON Testsuite: /nst_json_testsuite2/test_parsing/y_string_escaped_noncharacter.json

    ["\uFFFF"]
    
    • JSON Testsuite: /nst_json_testsuite2/test_parsing/y_string_in_array.json

    ["asd"]
    
    • JSON Testsuite: /nst_json_testsuite2/test_parsing/y_string_in_array_with_leading_space.json

    [ "asd"]
    
    • JSON Testsuite: /nst_json_testsuite2/test_parsing/y_string_last_surrogates_1_and_2.json

    ["\uDBFF\uDFFF"]
    
    • JSON Testsuite: /nst_json_testsuite2/test_parsing/y_string_nbsp_uescaped.json

    ["new\u00A0line"]
    
    • JSON Testsuite: /nst_json_testsuite2/test_parsing/y_string_nonCharacterInUTF-8_U+10FFFF.json

    ["􏿿"]
    
    • JSON Testsuite: /nst_json_testsuite2/test_parsing/y_string_nonCharacterInUTF-8_U+FFFF.json

    ["￿"]
    
    • JSON Testsuite: /nst_json_testsuite2/test_parsing/y_string_null_escape.json

    ["\u0000"]
    
    • JSON Testsuite: /nst_json_testsuite2/test_parsing/y_string_one-byte-utf-8.json

    ["\u002c"]
    
    • JSON Testsuite: /nst_json_testsuite2/test_parsing/y_string_pi.json

    ["π"]
    
    • JSON Testsuite: /nst_json_testsuite2/test_parsing/y_string_reservedCharacterInUTF-8_U+1BFFF.json

    ["𛿿"]
    
    • JSON Testsuite: /nst_json_testsuite2/test_parsing/y_string_simple_ascii.json

    ["asd "]
    
    • JSON Testsuite: /nst_json_testsuite2/test_parsing/y_string_space.json

    " "
    
    • JSON Testsuite: /nst_json_testsuite2/test_parsing/y_string_surrogates_U+1D11E_MUSICAL_SYMBOL_G_CLEF.json

    ["\uD834\uDd1e"]
    
    • JSON Testsuite: /nst_json_testsuite2/test_parsing/y_string_three-byte-utf-8.json

    ["\u0821"]
    
    • JSON Testsuite: /nst_json_testsuite2/test_parsing/y_string_two-byte-utf-8.json

    ["\u0123"]
    
    • JSON Testsuite: /nst_json_testsuite2/test_parsing/y_string_u+2028_line_sep.json

    ["
		"]
    
    • JSON Testsuite: /nst_json_testsuite2/test_parsing/y_string_u+2029_par_sep.json

    ["
		"]
    
    • JSON Testsuite: /nst_json_testsuite2/test_parsing/y_string_uEscape.json

    ["\u0061\u30af\u30EA\u30b9"]
    
    • JSON Testsuite: /nst_json_testsuite2/test_parsing/y_string_uescaped_newline.json

    ["new\u000Aline"]
    
    • JSON Testsuite: /nst_json_testsuite2/test_parsing/y_string_unescaped_char_delete.json

    [""]
    
    • JSON Testsuite: /nst_json_testsuite2/test_parsing/y_string_unicode.json

    ["\uA66D"]
    
    • JSON Testsuite: /nst_json_testsuite2/test_parsing/y_string_unicodeEscapedBackslash.json

    ["\u005C"]
    
    • JSON Testsuite: /nst_json_testsuite2/test_parsing/y_string_unicode_2.json

    ["⍂㈴⍂"]
    
    • JSON Testsuite: /nst_json_testsuite2/test_parsing/y_string_unicode_U+10FFFE_nonchar.json

    ["\uDBFF\uDFFE"]
    
    • JSON Testsuite: /nst_json_testsuite2/test_parsing/y_string_unicode_U+1FFFE_nonchar.json

    ["\uD83F\uDFFE"]
    
    • JSON Testsuite: /nst_json_testsuite2/test_parsing/y_string_unicode_U+200B_ZERO_WIDTH_SPACE.json

    ["\u200B"]
    
    • JSON Testsuite: /nst_json_testsuite2/test_parsing/y_string_unicode_U+2064_invisible_plus.json

    ["\u2064"]
    
    • JSON Testsuite: /nst_json_testsuite2/test_parsing/y_string_unicode_U+FDD0_nonchar.json

    ["\uFDD0"]
    
    • JSON Testsuite: /nst_json_testsuite2/test_parsing/y_string_unicode_U+FFFE_nonchar.json

    ["\uFFFE"]
    
    • JSON Testsuite: /nst_json_testsuite2/test_parsing/y_string_unicode_escaped_double_quote.json

    ["\u0022"]
    
    • JSON Testsuite: /nst_json_testsuite2/test_parsing/y_string_utf8.json

    ["€𝄞"]
    
    • JSON Testsuite: /nst_json_testsuite2/test_parsing/y_string_with_del_character.json

    ["aa"]
    
    • cpp-test: [nst’s JSONTestSuite (2);test_parsing;y] (tests/src/unit-testsuites.cpp)

    SECTION("y")
    {
        for (const auto* filename :
                {
                    TEST_DATA_DIRECTORY "/nst_json_testsuite2/test_parsing/y_string_1_2_3_bytes_UTF-8_sequences.json",
                    TEST_DATA_DIRECTORY "/nst_json_testsuite2/test_parsing/y_string_accepted_surrogate_pair.json",
                    TEST_DATA_DIRECTORY "/nst_json_testsuite2/test_parsing/y_string_accepted_surrogate_pairs.json",
                    TEST_DATA_DIRECTORY "/nst_json_testsuite2/test_parsing/y_string_allowed_escapes.json",
                    TEST_DATA_DIRECTORY "/nst_json_testsuite2/test_parsing/y_string_backslash_and_u_escaped_zero.json",
                    TEST_DATA_DIRECTORY "/nst_json_testsuite2/test_parsing/y_string_backslash_doublequotes.json",
                    TEST_DATA_DIRECTORY "/nst_json_testsuite2/test_parsing/y_string_comments.json",
                    TEST_DATA_DIRECTORY "/nst_json_testsuite2/test_parsing/y_string_double_escape_a.json",
                    TEST_DATA_DIRECTORY "/nst_json_testsuite2/test_parsing/y_string_double_escape_n.json",
                    TEST_DATA_DIRECTORY "/nst_json_testsuite2/test_parsing/y_string_escaped_control_character.json",
                    TEST_DATA_DIRECTORY "/nst_json_testsuite2/test_parsing/y_string_escaped_noncharacter.json",
                    TEST_DATA_DIRECTORY "/nst_json_testsuite2/test_parsing/y_string_in_array.json",
                    TEST_DATA_DIRECTORY "/nst_json_testsuite2/test_parsing/y_string_in_array_with_leading_space.json",
                    TEST_DATA_DIRECTORY "/nst_json_testsuite2/test_parsing/y_string_last_surrogates_1_and_2.json",
                    TEST_DATA_DIRECTORY "/nst_json_testsuite2/test_parsing/y_string_nbsp_uescaped.json",
                    TEST_DATA_DIRECTORY "/nst_json_testsuite2/test_parsing/y_string_nonCharacterInUTF-8_U+10FFFF.json",
                    TEST_DATA_DIRECTORY "/nst_json_testsuite2/test_parsing/y_string_nonCharacterInUTF-8_U+FFFF.json",
                    TEST_DATA_DIRECTORY "/nst_json_testsuite2/test_parsing/y_string_null_escape.json",
                    TEST_DATA_DIRECTORY "/nst_json_testsuite2/test_parsing/y_string_one-byte-utf-8.json",
                    TEST_DATA_DIRECTORY "/nst_json_testsuite2/test_parsing/y_string_pi.json",
                    TEST_DATA_DIRECTORY "/nst_json_testsuite2/test_parsing/y_string_reservedCharacterInUTF-8_U+1BFFF.json",
                    TEST_DATA_DIRECTORY "/nst_json_testsuite2/test_parsing/y_string_simple_ascii.json",
                    TEST_DATA_DIRECTORY "/nst_json_testsuite2/test_parsing/y_string_space.json",
                    TEST_DATA_DIRECTORY "/nst_json_testsuite2/test_parsing/y_string_surrogates_U+1D11E_MUSICAL_SYMBOL_G_CLEF.json",
                    TEST_DATA_DIRECTORY "/nst_json_testsuite2/test_parsing/y_string_three-byte-utf-8.json",
                    TEST_DATA_DIRECTORY "/nst_json_testsuite2/test_parsing/y_string_two-byte-utf-8.json",
                    TEST_DATA_DIRECTORY "/nst_json_testsuite2/test_parsing/y_string_u+2028_line_sep.json",
                    TEST_DATA_DIRECTORY "/nst_json_testsuite2/test_parsing/y_string_u+2029_par_sep.json",
                    TEST_DATA_DIRECTORY "/nst_json_testsuite2/test_parsing/y_string_uEscape.json",
                    TEST_DATA_DIRECTORY "/nst_json_testsuite2/test_parsing/y_string_uescaped_newline.json",
                    TEST_DATA_DIRECTORY "/nst_json_testsuite2/test_parsing/y_string_unescaped_char_delete.json",
                    TEST_DATA_DIRECTORY "/nst_json_testsuite2/test_parsing/y_string_unicode.json",
                    TEST_DATA_DIRECTORY "/nst_json_testsuite2/test_parsing/y_string_unicodeEscapedBackslash.json",
                    TEST_DATA_DIRECTORY "/nst_json_testsuite2/test_parsing/y_string_unicode_2.json",
                    TEST_DATA_DIRECTORY "/nst_json_testsuite2/test_parsing/y_string_unicode_U+10FFFE_nonchar.json",
                    TEST_DATA_DIRECTORY "/nst_json_testsuite2/test_parsing/y_string_unicode_U+1FFFE_nonchar.json",
                    TEST_DATA_DIRECTORY "/nst_json_testsuite2/test_parsing/y_string_unicode_U+200B_ZERO_WIDTH_SPACE.json",
                    TEST_DATA_DIRECTORY "/nst_json_testsuite2/test_parsing/y_string_unicode_U+2064_invisible_plus.json",
                    TEST_DATA_DIRECTORY "/nst_json_testsuite2/test_parsing/y_string_unicode_U+FDD0_nonchar.json",
                    TEST_DATA_DIRECTORY "/nst_json_testsuite2/test_parsing/y_string_unicode_U+FFFE_nonchar.json",
                    TEST_DATA_DIRECTORY "/nst_json_testsuite2/test_parsing/y_string_unicode_escaped_double_quote.json",
                    TEST_DATA_DIRECTORY "/nst_json_testsuite2/test_parsing/y_string_utf8.json",
                    TEST_DATA_DIRECTORY "/nst_json_testsuite2/test_parsing/y_string_with_del_character.json",
                }
            )
        {
            CAPTURE(filename)
            std::ifstream f(filename);
            json _;
            CHECK_NOTHROW(_ = json::parse(f));
            std::ifstream f2(filename);
            CHECK(json::accept(f2));
        }
    }
    
    
     // Note: Other test data lines have been filtered out for conciseness.
    

Fallacies:

None

Graph:

No Historic Data Found


NPF-04#

The service parses literal names “true”, “false” and “null” according to RFC8259.

Supported Requests:

Supporting Items:

References:

  • function: [lexer::scan_literal] (include/nlohmann/detail/input/lexer.hpp)

    • Description: function to scan a literal candidate, compare it to its expected value and return the corresponding C++ literal

token_type scan_literal(const char_type* literal_text, const std::size_t length,
                        token_type return_type)
{
    JSON_ASSERT(char_traits<char_type>::to_char_type(current) == literal_text[0]);
    for (std::size_t i = 1; i < length; ++i)
    {
        if (JSON_HEDLEY_UNLIKELY(char_traits<char_type>::to_char_type(get()) != literal_text[i]))
        {
            error_message = "invalid literal";
            return token_type::parse_error;
        }
    }
    return return_type;
}

Fallacies:

None

Graph:

No Historic Data Found


NPF-04.1#

The service ignores leading and trailing whitespace.

Supported Requests:

Supporting Items:

None

References:

  • cpp-test: [parse;whitespace] (TSF/tests/unit-literals.cpp)

SECTION("whitespace")
{
    CHECK(json::parse(" false ")==json::parse("false"));
    CHECK(json::parse(" false\t")==json::parse("false"));
    CHECK(json::parse(" false\n")==json::parse("false"));
    CHECK(json::parse(" false\u000d")==json::parse("false"));
    CHECK(json::parse("\tfalse ")==json::parse("false"));
    CHECK(json::parse("\tfalse\t")==json::parse("false"));
    CHECK(json::parse("\tfalse\n")==json::parse("false"));
    CHECK(json::parse("\tfalse\u000d")==json::parse("false"));
    CHECK(json::parse("\nfalse ")==json::parse("false"));
    CHECK(json::parse("\nfalse\t")==json::parse("false"));
    CHECK(json::parse("\nfalse\n")==json::parse("false"));
    CHECK(json::parse("\nfalse\u000d")==json::parse("false"));
    CHECK(json::parse("\u000dfalse ")==json::parse("false"));
    CHECK(json::parse("\u000dfalse\t")==json::parse("false"));
    CHECK(json::parse("\u000dfalse\n")==json::parse("false"));
    CHECK(json::parse("\u000dfalse\u000d")==json::parse("false"));
    CHECK(json::parse(" null ")==json::parse("null"));
    CHECK(json::parse(" null\t")==json::parse("null"));
    CHECK(json::parse(" null\n")==json::parse("null"));
    CHECK(json::parse(" null\u000d")==json::parse("null"));
    CHECK(json::parse("\tnull ")==json::parse("null"));
    CHECK(json::parse("\tnull\t")==json::parse("null"));
    CHECK(json::parse("\tnull\n")==json::parse("null"));
    CHECK(json::parse("\tnull\u000d")==json::parse("null"));
    CHECK(json::parse("\nnull ")==json::parse("null"));
    CHECK(json::parse("\nnull\t")==json::parse("null"));
    CHECK(json::parse("\nnull\n")==json::parse("null"));
    CHECK(json::parse("\nnull\u000d")==json::parse("null"));
    CHECK(json::parse("\u000dnull ")==json::parse("null"));
    CHECK(json::parse("\u000dnull\t")==json::parse("null"));
    CHECK(json::parse("\u000dnull\n")==json::parse("null"));
    CHECK(json::parse("\u000dnull\u000d")==json::parse("null"));
    CHECK(json::parse(" true ")==json::parse("true"));
    CHECK(json::parse(" true\t")==json::parse("true"));
    CHECK(json::parse(" true\n")==json::parse("true"));
    CHECK(json::parse(" true\u000d")==json::parse("true"));
    CHECK(json::parse("\ttrue ")==json::parse("true"));
    CHECK(json::parse("\ttrue\t")==json::parse("true"));
    CHECK(json::parse("\ttrue\n")==json::parse("true"));
    CHECK(json::parse("\ttrue\u000d")==json::parse("true"));
    CHECK(json::parse("\ntrue ")==json::parse("true"));
    CHECK(json::parse("\ntrue\t")==json::parse("true"));
    CHECK(json::parse("\ntrue\n")==json::parse("true"));
    CHECK(json::parse("\ntrue\u000d")==json::parse("true"));
    CHECK(json::parse("\u000dtrue ")==json::parse("true"));
    CHECK(json::parse("\u000dtrue\t")==json::parse("true"));
    CHECK(json::parse("\u000dtrue\n")==json::parse("true"));
    CHECK(json::parse("\u000dtrue\u000d")==json::parse("true"));    
}
  • function: [lexer::skip_whitespace] (include/nlohmann/detail/input/lexer.hpp)

    • Description: function, which skips admissible whitespace during reading

void skip_whitespace()
{
    do
    {
        get();
    }
    while (current == ' ' || current == '\t' || current == '\n' || current == '\r');
}

Fallacies:

None

Graph:

No Historic Data Found


NPF-04.2#

The service parses the literal name true.

Supported Requests:

Supporting Items:

None

References:

  • cpp-test: [parser class - core;parse;true] (TSF/tests/unit-class_parser_core.cpp)

SECTION("true")
{
    CHECK(parser_helper("true") == json(true));
}

Fallacies:

None

Graph:

No Historic Data Found


NPF-04.3#

The service parses the literal name false.

Supported Requests:

Supporting Items:

None

References:

  • cpp-test: [parser class - core;parse;false] (TSF/tests/unit-class_parser_core.cpp)

SECTION("false")
{
    CHECK(parser_helper("false") == json(false));
}

Fallacies:

None

Graph:

No Historic Data Found


NPF-04.4#

The service parses the literal name null.

Supported Requests:

Supporting Items:

None

References:

  • cpp-test: [parser class - core;parse;null] (TSF/tests/unit-class_parser_core.cpp)

SECTION("null")
{
    CHECK(parser_helper("null") == json(nullptr));
}

Fallacies:

None

Graph:

No Historic Data Found


NPF-05#

The service parses arrays according to RFC8259.

Supported Requests:

Supporting Items:

References:

None

Fallacies:

None

Graph:

No Historic Data Found


NPF-05.1#

The service ignores leading and trailing whitespace for each value.

Supported Requests:

Supporting Items:

None

References:

  • cpp-test: [parser class - core;parse;array;empty array] (TSF/tests/unit-class_parser_core.cpp)

SECTION("empty array")
{
    CHECK(parser_helper("[]") == json(json::value_t::array));
    CHECK(parser_helper("[ ]") == json(json::value_t::array));
}
  • cpp-test: [parse;whitespace] (TSF/tests/unit-arrays.cpp)

SECTION("whitespace")
{
    json j = json::parse(R"(["1","2","test","foo","bar"])");
    CHECK(parser_helper("[ \"1\" , \"2\" , \"test\" , \"foo\" , \"bar\" ]")==j);
    CHECK(parser_helper("[ \"1\"\t, \"2\"\t, \"test\"\t, \"foo\"\t, \"bar\"\t]")==j);
    CHECK(parser_helper("[ \"1\"\n, \"2\"\n, \"test\"\n, \"foo\"\n, \"bar\"\n]")==j);
    CHECK(parser_helper("[ \"1\"\u000d, \"2\"\u000d, \"test\"\u000d, \"foo\"\u000d, \"bar\"\u000d]")==j);
    CHECK(parser_helper("[\t\"1\" ,\t\"2\" ,\t\"test\" ,\t\"foo\" ,\t\"bar\" ]")==j);
    CHECK(parser_helper("[\t\"1\"\t,\t\"2\"\t,\t\"test\"\t,\t\"foo\"\t,\t\"bar\"\t]")==j);
    CHECK(parser_helper("[\t\"1\"\n,\t\"2\"\n,\t\"test\"\n,\t\"foo\"\n,\t\"bar\"\n]")==j);
    CHECK(parser_helper("[\t\"1\"\u000d,\t\"2\"\u000d,\t\"test\"\u000d,\t\"foo\"\u000d,\t\"bar\"\u000d]")==j);
    CHECK(parser_helper("[\n\"1\" ,\n\"2\" ,\n\"test\" ,\n\"foo\" ,\n\"bar\" ]")==j);
    CHECK(parser_helper("[\n\"1\"\t,\n\"2\"\t,\n\"test\"\t,\n\"foo\"\t,\n\"bar\"\t]")==j);
    CHECK(parser_helper("[\n\"1\"\n,\n\"2\"\n,\n\"test\"\n,\n\"foo\"\n,\n\"bar\"\n]")==j);
    CHECK(parser_helper("[\n\"1\"\u000d,\n\"2\"\u000d,\n\"test\"\u000d,\n\"foo\"\u000d,\n\"bar\"\u000d]")==j);
    CHECK(parser_helper("[\u000d\"1\" ,\u000d\"2\" ,\u000d\"test\" ,\u000d\"foo\" ,\u000d\"bar\" ]")==j);
    CHECK(parser_helper("[\u000d\"1\"\t,\u000d\"2\"\t,\u000d\"test\"\t,\u000d\"foo\"\t,\u000d\"bar\"\t]")==j);
    CHECK(parser_helper("[\u000d\"1\"\n,\u000d\"2\"\n,\u000d\"test\"\n,\u000d\"foo\"\n,\u000d\"bar\"\n]")==j);
    CHECK(parser_helper("[\u000d\"1\"\u000d,\u000d\"2\"\u000d,\u000d\"test\"\u000d,\u000d\"foo\"\u000d,\u000d\"bar\"\u000d]")==j);
}
  • function: [lexer::skip_whitespace] (include/nlohmann/detail/input/lexer.hpp)

    • Description: function, which skips admissible whitespace during reading

void skip_whitespace()
{
    do
    {
        get();
    }
    while (current == ' ' || current == '\t' || current == '\n' || current == '\r');
}

Fallacies:

None

Graph:

No Historic Data Found


NPF-05.2#

The service parses empty arrays.

Supported Requests:

Supporting Items:

None

References:

  • cpp-testsuite: [/nst_json_testsuite2/test_parsing/y_array_empty.json]

    • Description: Tests whether the empty array is parsed without exception.

    • JSON Testsuite: /nst_json_testsuite2/test_parsing/y_array_empty.json

    []
    
    • cpp-test: [nst’s JSONTestSuite (2);test_parsing;y] (tests/src/unit-testsuites.cpp)

    SECTION("y")
    {
        for (const auto* filename :
                {
                    TEST_DATA_DIRECTORY "/nst_json_testsuite2/test_parsing/y_array_empty.json",
                }
            )
        {
            CAPTURE(filename)
            std::ifstream f(filename);
            json _;
            CHECK_NOTHROW(_ = json::parse(f));
            std::ifstream f2(filename);
            CHECK(json::accept(f2));
        }
    }
    
    
     // Note: Other test data lines have been filtered out for conciseness.
    
  • cpp-test: [parser class - core;parse;array;empty array] (TSF/tests/unit-class_parser_core.cpp)

SECTION("empty array")
{
    CHECK(parser_helper("[]") == json(json::value_t::array));
    CHECK(parser_helper("[ ]") == json(json::value_t::array));
}

Fallacies:

None

Graph:

No Historic Data Found


NPF-05.3#

The service parses non-empty arrays.

Supported Requests:

Supporting Items:

None

References:

  • cpp-test: [parser class - core;parse;array;nonempty array] (TSF/tests/unit-class_parser_core.cpp)

SECTION("nonempty array")
{
    CHECK(parser_helper("[true, false, null]") == json({true, false, nullptr}));
}
  • cpp-testsuite: [/nst_json_testsuite2/test_parsing/y_array_arraysWithSpaces.json, /nst_json_testsuite2/test_parsing/y_array_empty-string.json, /nst_json_testsuite2/test_parsing/y_array_ending_with_newline.json, /nst_json_testsuite2/test_parsing/y_array_false.json, /nst_json_testsuite2/test_parsing/y_array_heterogeneous.json, /nst_json_testsuite2/test_parsing/y_array_null.json, /nst_json_testsuite2/test_parsing/y_array_with_1_and_newline.json, /nst_json_testsuite2/test_parsing/y_array_with_leading_space.json, /nst_json_testsuite2/test_parsing/y_array_with_several_null.json, /nst_json_testsuite2/test_parsing/y_array_with_trailing_space.json]

    • Description: Tests whether several non-empty arrays are parsed without exception

    • JSON Testsuite: /nst_json_testsuite2/test_parsing/y_array_arraysWithSpaces.json

    [[]   ]
    
    • JSON Testsuite: /nst_json_testsuite2/test_parsing/y_array_empty-string.json

    [""]
    
    • JSON Testsuite: /nst_json_testsuite2/test_parsing/y_array_ending_with_newline.json

    ["a"]
    
    • JSON Testsuite: /nst_json_testsuite2/test_parsing/y_array_false.json

    [false]
    
    • JSON Testsuite: /nst_json_testsuite2/test_parsing/y_array_heterogeneous.json

    [null, 1, "1", {}]
    
    • JSON Testsuite: /nst_json_testsuite2/test_parsing/y_array_null.json

    [null]
    
    • JSON Testsuite: /nst_json_testsuite2/test_parsing/y_array_with_1_and_newline.json

    [1
    ]
    
    • JSON Testsuite: /nst_json_testsuite2/test_parsing/y_array_with_leading_space.json

    [1]
    
    • JSON Testsuite: /nst_json_testsuite2/test_parsing/y_array_with_several_null.json

    [1,null,null,null,2]
    
    • JSON Testsuite: /nst_json_testsuite2/test_parsing/y_array_with_trailing_space.json

    [2] 
    
    • cpp-test: [nst’s JSONTestSuite (2);test_parsing;y] (tests/src/unit-testsuites.cpp)

    SECTION("y")
    {
        for (const auto* filename :
                {
                    TEST_DATA_DIRECTORY "/nst_json_testsuite2/test_parsing/y_array_arraysWithSpaces.json",
                    TEST_DATA_DIRECTORY "/nst_json_testsuite2/test_parsing/y_array_empty-string.json",
                    TEST_DATA_DIRECTORY "/nst_json_testsuite2/test_parsing/y_array_ending_with_newline.json",
                    TEST_DATA_DIRECTORY "/nst_json_testsuite2/test_parsing/y_array_false.json",
                    TEST_DATA_DIRECTORY "/nst_json_testsuite2/test_parsing/y_array_heterogeneous.json",
                    TEST_DATA_DIRECTORY "/nst_json_testsuite2/test_parsing/y_array_null.json",
                    TEST_DATA_DIRECTORY "/nst_json_testsuite2/test_parsing/y_array_with_1_and_newline.json",
                    TEST_DATA_DIRECTORY "/nst_json_testsuite2/test_parsing/y_array_with_leading_space.json",
                    TEST_DATA_DIRECTORY "/nst_json_testsuite2/test_parsing/y_array_with_several_null.json",
                    TEST_DATA_DIRECTORY "/nst_json_testsuite2/test_parsing/y_array_with_trailing_space.json",
                }
            )
        {
            CAPTURE(filename)
            std::ifstream f(filename);
            json _;
            CHECK_NOTHROW(_ = json::parse(f));
            std::ifstream f2(filename);
            CHECK(json::accept(f2));
        }
    }
    
    
     // Note: Other test data lines have been filtered out for conciseness.
    

Fallacies:

None

Graph:

No Historic Data Found


NPF-06#

The service parses objects according to RFC8259.

Supported Requests:

Supporting Items:

References:

None

Fallacies:

None

Graph:

No Historic Data Found


NPF-06.1#

The service ignores leading and trailing whitespace for name and value of each member.

Supported Requests:

Supporting Items:

None

References:

  • cpp-test: [parser class - core;parse;object;empty object] (TSF/tests/unit-class_parser_core.cpp)

SECTION("empty object")
{
    CHECK(parser_helper("{}") == json(json::value_t::object));
    CHECK(parser_helper("{ }") == json(json::value_t::object));
}
  • cpp-test: [regression tests 1;example from #529] (tests/src/unit-regression1.cpp)

SECTION("example from #529")
{
    std::stringstream ss;
    ss << "{\n    \"one\"   : 1,\n    \"two\"   : 2\n}\n{\n    \"three\" : 3\n}";
    json j;
    CHECK_NOTHROW(ss >> j);
    CHECK(j == json({{"one", 1}, {"two", 2}}));
    CHECK_NOTHROW(ss >> j);
    CHECK(j == json({{"three", 3}}));

    CHECK_THROWS_WITH_AS(ss >> j, "[json.exception.parse_error.101] parse error at line 1, column 1: attempting to parse an empty input; check that your input string or stream contains the expected JSON", json::parse_error&);
}
  • function: [lexer::skip_whitespace] (include/nlohmann/detail/input/lexer.hpp)

    • Description: function, which skips admissible whitespace during reading

void skip_whitespace()
{
    do
    {
        get();
    }
    while (current == ' ' || current == '\t' || current == '\n' || current == '\r');
}

Fallacies:

None

Graph:

No Historic Data Found


NPF-06.2#

The service parses duplicate names without error and reports the last member with that name only.

Supported Requests:

Supporting Items:

None

References:

  • cpp-testsuite: [/nst_json_testsuite2/test_parsing/y_object_duplicated_key.json, /nst_json_testsuite2/test_parsing/y_object_duplicated_key_and_value.json]

    • JSON Testsuite: /nst_json_testsuite2/test_parsing/y_object_duplicated_key.json

    {"a":"b","a":"c"}
    
    • JSON Testsuite: /nst_json_testsuite2/test_parsing/y_object_duplicated_key_and_value.json

    {"a":"b","a":"b"}
    
    • cpp-test: [nst’s JSONTestSuite (2);test_parsing;y] (tests/src/unit-testsuites.cpp)

    SECTION("y")
    {
        for (const auto* filename :
                {
                    TEST_DATA_DIRECTORY "/nst_json_testsuite2/test_parsing/y_object_duplicated_key.json",
                    TEST_DATA_DIRECTORY "/nst_json_testsuite2/test_parsing/y_object_duplicated_key_and_value.json",
                }
            )
        {
            CAPTURE(filename)
            std::ifstream f(filename);
            json _;
            CHECK_NOTHROW(_ = json::parse(f));
            std::ifstream f2(filename);
            CHECK(json::accept(f2));
        }
    }
    
    
     // Note: Other test data lines have been filtered out for conciseness.
    

Fallacies:

None

Graph:

No Historic Data Found


NPF-06.3#

The service parses empty objects.

Supported Requests:

Supporting Items:

None

References:

  • cpp-test: [parser class - core;parse;object;empty object] (TSF/tests/unit-class_parser_core.cpp)

SECTION("empty object")
{
    CHECK(parser_helper("{}") == json(json::value_t::object));
    CHECK(parser_helper("{ }") == json(json::value_t::object));
}

Fallacies:

None

Graph:

No Historic Data Found


NPF-06.4#

The service parses non-empty objects.

Supported Requests:

Supporting Items:

None

References:

  • cpp-test: [parser class - core;parse;object;nonempty object] (TSF/tests/unit-class_parser_core.cpp)

SECTION("nonempty object")
{
    CHECK(parser_helper("{\"\": true, \"one\": 1, \"two\": null}") == json({{"", true}, {"one", 1}, {"two", nullptr}}));
}

Fallacies:

None

Graph:

No Historic Data Found


NPF-07#

The service parses well-formed UTF-8 encoded data only.

Supported Requests:

Supporting Items:

References:

None

Fallacies:

None

Graph:

No Historic Data Found


NPF-07.1#

The service parses UTF-8 encoded data.

Supported Requests:

Supporting Items:

None

References:

  • cpp-test: [Unicode (2/5);RFC 3629;UTF8-1 (x00-x7F);well-formed] (tests/src/unit-unicode2.cpp)

SECTION("well-formed")
{
    for (int byte1 = 0x00; byte1 <= 0x7F; ++byte1)
    {
        // unescaped control characters are parse errors in JSON
        if (0x00 <= byte1 && byte1 <= 0x1F)
        {
            check_utf8string(false, byte1);
            continue;
        }

        // a single quote is a parse error in JSON
        if (byte1 == 0x22)
        {
            check_utf8string(false, byte1);
            continue;
        }

        // a single backslash is a parse error in JSON
        if (byte1 == 0x5C)
        {
            check_utf8string(false, byte1);
            continue;
        }

        // all other characters are OK
        check_utf8string(true, byte1);
        check_utf8dump(true, byte1);
    }
}
  • cpp-test: [Unicode (2/5);RFC 3629;UTF8-2 (xC2-xDF UTF8-tail);well-formed] (tests/src/unit-unicode2.cpp)

SECTION("well-formed")
{
    for (int byte1 = 0xC2; byte1 <= 0xDF; ++byte1)
    {
        for (int byte2 = 0x80; byte2 <= 0xBF; ++byte2)
        {
            check_utf8string(true, byte1, byte2);
            check_utf8dump(true, byte1, byte2);
        }
    }
}
  • cpp-test: [Unicode (2/5);RFC 3629;UTF8-3 (xE0 xA0-BF UTF8-tail);well-formed] (tests/src/unit-unicode2.cpp)

SECTION("well-formed")
{
    for (int byte1 = 0xE0; byte1 <= 0xE0; ++byte1)
    {
        for (int byte2 = 0xA0; byte2 <= 0xBF; ++byte2)
        {
            for (int byte3 = 0x80; byte3 <= 0xBF; ++byte3)
            {
                check_utf8string(true, byte1, byte2, byte3);
                check_utf8dump(true, byte1, byte2, byte3);
            }
        }
    }
}
  • cpp-test: [Unicode (2/5);RFC 3629;UTF8-3 (xE1-xEC UTF8-tail UTF8-tail);well-formed] (tests/src/unit-unicode2.cpp)

SECTION("well-formed")
{
    for (int byte1 = 0xE1; byte1 <= 0xEC; ++byte1)
    {
        for (int byte2 = 0x80; byte2 <= 0xBF; ++byte2)
        {
            for (int byte3 = 0x80; byte3 <= 0xBF; ++byte3)
            {
                check_utf8string(true, byte1, byte2, byte3);
                check_utf8dump(true, byte1, byte2, byte3);
            }
        }
    }
}
  • cpp-test: [Unicode (2/5);RFC 3629;UTF8-3 (xED x80-9F UTF8-tail);well-formed] (tests/src/unit-unicode2.cpp)

SECTION("well-formed")
{
    for (int byte1 = 0xED; byte1 <= 0xED; ++byte1)
    {
        for (int byte2 = 0x80; byte2 <= 0x9F; ++byte2)
        {
            for (int byte3 = 0x80; byte3 <= 0xBF; ++byte3)
            {
                check_utf8string(true, byte1, byte2, byte3);
                check_utf8dump(true, byte1, byte2, byte3);
            }
        }
    }
}
  • cpp-test: [Unicode (2/5);RFC 3629;UTF8-3 (xEE-xEF UTF8-tail UTF8-tail);well-formed] (tests/src/unit-unicode2.cpp)

SECTION("well-formed")
{
    for (int byte1 = 0xEE; byte1 <= 0xEF; ++byte1)
    {
        for (int byte2 = 0x80; byte2 <= 0xBF; ++byte2)
        {
            for (int byte3 = 0x80; byte3 <= 0xBF; ++byte3)
            {
                check_utf8string(true, byte1, byte2, byte3);
                check_utf8dump(true, byte1, byte2, byte3);
            }
        }
    }
}
  • cpp-test: [Unicode (3/5);RFC 3629;UTF8-4 (xF0 x90-BF UTF8-tail UTF8-tail);well-formed] (tests/src/unit-unicode3.cpp)

SECTION("well-formed")
{
    for (int byte1 = 0xF0; byte1 <= 0xF0; ++byte1)
    {
        for (int byte2 = 0x90; byte2 <= 0xBF; ++byte2)
        {
            for (int byte3 = 0x80; byte3 <= 0xBF; ++byte3)
            {
                for (int byte4 = 0x80; byte4 <= 0xBF; ++byte4)
                {
                    check_utf8string(true, byte1, byte2, byte3, byte4);
                    check_utf8dump(true, byte1, byte2, byte3, byte4);
                }
            }
        }
    }
}
  • cpp-test: [Unicode (4/5);RFC 3629;UTF8-4 (xF1-F3 UTF8-tail UTF8-tail UTF8-tail);well-formed] (tests/src/unit-unicode4.cpp)

SECTION("well-formed")
{
    for (int byte1 = 0xF1; byte1 <= 0xF3; ++byte1)
    {
        for (int byte2 = 0x80; byte2 <= 0xBF; ++byte2)
        {
            for (int byte3 = 0x80; byte3 <= 0xBF; ++byte3)
            {
                for (int byte4 = 0x80; byte4 <= 0xBF; ++byte4)
                {
                    check_utf8string(true, byte1, byte2, byte3, byte4);
                    check_utf8dump(true, byte1, byte2, byte3, byte4);
                }
            }
        }
    }
}
  • cpp-test: [Unicode (5/5);RFC 3629;UTF8-4 (xF4 x80-8F UTF8-tail UTF8-tail);well-formed] (tests/src/unit-unicode5.cpp)

SECTION("well-formed")
{
    for (int byte1 = 0xF4; byte1 <= 0xF4; ++byte1)
    {
        for (int byte2 = 0x80; byte2 <= 0x8F; ++byte2)
        {
            for (int byte3 = 0x80; byte3 <= 0xBF; ++byte3)
            {
                for (int byte4 = 0x80; byte4 <= 0xBF; ++byte4)
                {
                    check_utf8string(true, byte1, byte2, byte3, byte4);
                    check_utf8dump(true, byte1, byte2, byte3, byte4);
                }
            }
        }
    }
}

Fallacies:

None

Graph:

No Historic Data Found


NPF-07.2#

The service throws an exception on ill-formed UTF-8 data.

Supported Requests:

Supporting Items:

None

References:

  • cpp-test: [Unicode (2/5);RFC 3629;ill-formed first byte] (tests/src/unit-unicode2.cpp)

SECTION("ill-formed first byte")
{
    for (int byte1 = 0x80; byte1 <= 0xC1; ++byte1)
    {
        check_utf8string(false, byte1);
        check_utf8dump(false, byte1);
    }

    for (int byte1 = 0xF5; byte1 <= 0xFF; ++byte1)
    {
        check_utf8string(false, byte1);
        check_utf8dump(false, byte1);
    }
}
  • cpp-test: [Unicode (2/5);RFC 3629;UTF8-2 (xC2-xDF UTF8-tail);ill-formed: missing second byte] (tests/src/unit-unicode2.cpp)

SECTION("ill-formed: missing second byte")
{
    for (int byte1 = 0xC2; byte1 <= 0xDF; ++byte1)
    {
        check_utf8string(false, byte1);
        check_utf8dump(false, byte1);
    }
}
  • cpp-test: [Unicode (2/5);RFC 3629;UTF8-2 (xC2-xDF UTF8-tail);ill-formed: wrong second byte] (tests/src/unit-unicode2.cpp)

SECTION("ill-formed: wrong second byte")
{
    for (int byte1 = 0xC2; byte1 <= 0xDF; ++byte1)
    {
        for (int byte2 = 0x00; byte2 <= 0xFF; ++byte2)
        {
            // skip correct second byte
            if (0x80 <= byte2 && byte2 <= 0xBF)
            {
                continue;
            }

            check_utf8string(false, byte1, byte2);
            check_utf8dump(false, byte1, byte2);
        }
    }
}
  • cpp-test: [Unicode (2/5);RFC 3629;UTF8-3 (xE0 xA0-BF UTF8-tail);ill-formed: missing second byte] (tests/src/unit-unicode2.cpp)

SECTION("ill-formed: missing second byte")
{
    for (int byte1 = 0xE0; byte1 <= 0xE0; ++byte1)
    {
        check_utf8string(false, byte1);
        check_utf8dump(false, byte1);
    }
}
  • cpp-test: [Unicode (2/5);RFC 3629;UTF8-3 (xE0 xA0-BF UTF8-tail);ill-formed: missing third byte] (tests/src/unit-unicode2.cpp)

SECTION("ill-formed: missing third byte")
{
    for (int byte1 = 0xE0; byte1 <= 0xE0; ++byte1)
    {
        for (int byte2 = 0xA0; byte2 <= 0xBF; ++byte2)
        {
            check_utf8string(false, byte1, byte2);
            check_utf8dump(false, byte1, byte2);
        }
    }
}
  • cpp-test: [Unicode (2/5);RFC 3629;UTF8-3 (xE0 xA0-BF UTF8-tail);ill-formed: wrong second byte] (tests/src/unit-unicode2.cpp)

SECTION("ill-formed: wrong second byte")
{
    for (int byte1 = 0xE0; byte1 <= 0xE0; ++byte1)
    {
        for (int byte2 = 0x00; byte2 <= 0xFF; ++byte2)
        {
            // skip correct second byte
            if (0xA0 <= byte2 && byte2 <= 0xBF)
            {
                continue;
            }

            for (int byte3 = 0x80; byte3 <= 0xBF; ++byte3)
            {
                check_utf8string(false, byte1, byte2, byte3);
                check_utf8dump(false, byte1, byte2, byte3);
            }
        }
    }
}
  • cpp-test: [Unicode (2/5);RFC 3629;UTF8-3 (xE0 xA0-BF UTF8-tail);ill-formed: wrong third byte] (tests/src/unit-unicode2.cpp)

SECTION("ill-formed: wrong third byte")
{
    for (int byte1 = 0xE0; byte1 <= 0xE0; ++byte1)
    {
        for (int byte2 = 0xA0; byte2 <= 0xBF; ++byte2)
        {
            for (int byte3 = 0x00; byte3 <= 0xFF; ++byte3)
            {
                // skip correct third byte
                if (0x80 <= byte3 && byte3 <= 0xBF)
                {
                    continue;
                }

                check_utf8string(false, byte1, byte2, byte3);
                check_utf8dump(false, byte1, byte2, byte3);
            }
        }
    }
}
  • cpp-test: [Unicode (2/5);RFC 3629;UTF8-3 (xE1-xEC UTF8-tail UTF8-tail);ill-formed: missing second byte] (tests/src/unit-unicode2.cpp)

SECTION("ill-formed: missing second byte")
{
    for (int byte1 = 0xE1; byte1 <= 0xEC; ++byte1)
    {
        check_utf8string(false, byte1);
        check_utf8dump(false, byte1);
    }
}
  • cpp-test: [Unicode (2/5);RFC 3629;UTF8-3 (xE1-xEC UTF8-tail UTF8-tail);ill-formed: missing third byte] (tests/src/unit-unicode2.cpp)

SECTION("ill-formed: missing third byte")
{
    for (int byte1 = 0xE1; byte1 <= 0xEC; ++byte1)
    {
        for (int byte2 = 0x80; byte2 <= 0xBF; ++byte2)
        {
            check_utf8string(false, byte1, byte2);
            check_utf8dump(false, byte1, byte2);
        }
    }
}
  • cpp-test: [Unicode (2/5);RFC 3629;UTF8-3 (xE1-xEC UTF8-tail UTF8-tail);ill-formed: wrong second byte] (tests/src/unit-unicode2.cpp)

SECTION("ill-formed: wrong second byte")
{
    for (int byte1 = 0xE1; byte1 <= 0xEC; ++byte1)
    {
        for (int byte2 = 0x00; byte2 <= 0xFF; ++byte2)
        {
            // skip correct second byte
            if (0x80 <= byte2 && byte2 <= 0xBF)
            {
                continue;
            }

            for (int byte3 = 0x80; byte3 <= 0xBF; ++byte3)
            {
                check_utf8string(false, byte1, byte2, byte3);
                check_utf8dump(false, byte1, byte2, byte3);
            }
        }
    }
}
  • cpp-test: [Unicode (2/5);RFC 3629;UTF8-3 (xE1-xEC UTF8-tail UTF8-tail);ill-formed: wrong third byte] (tests/src/unit-unicode2.cpp)

SECTION("ill-formed: wrong third byte")
{
    for (int byte1 = 0xE1; byte1 <= 0xEC; ++byte1)
    {
        for (int byte2 = 0x80; byte2 <= 0xBF; ++byte2)
        {
            for (int byte3 = 0x00; byte3 <= 0xFF; ++byte3)
            {
                // skip correct third byte
                if (0x80 <= byte3 && byte3 <= 0xBF)
                {
                    continue;
                }

                check_utf8string(false, byte1, byte2, byte3);
                check_utf8dump(false, byte1, byte2, byte3);
            }
        }
    }
}
  • cpp-test: [Unicode (2/5);RFC 3629;UTF8-3 (xED x80-9F UTF8-tail);ill-formed: missing second byte] (tests/src/unit-unicode2.cpp)

SECTION("ill-formed: missing second byte")
{
    for (int byte1 = 0xED; byte1 <= 0xED; ++byte1)
    {
        check_utf8string(false, byte1);
        check_utf8dump(false, byte1);
    }
}
  • cpp-test: [Unicode (2/5);RFC 3629;UTF8-3 (xED x80-9F UTF8-tail);ill-formed: missing third byte] (tests/src/unit-unicode2.cpp)

SECTION("ill-formed: missing third byte")
{
    for (int byte1 = 0xED; byte1 <= 0xED; ++byte1)
    {
        for (int byte2 = 0x80; byte2 <= 0x9F; ++byte2)
        {
            check_utf8string(false, byte1, byte2);
            check_utf8dump(false, byte1, byte2);
        }
    }
}
  • cpp-test: [Unicode (2/5);RFC 3629;UTF8-3 (xED x80-9F UTF8-tail);ill-formed: wrong second byte] (tests/src/unit-unicode2.cpp)

SECTION("ill-formed: wrong second byte")
{
    for (int byte1 = 0xED; byte1 <= 0xED; ++byte1)
    {
        for (int byte2 = 0x00; byte2 <= 0xFF; ++byte2)
        {
            // skip correct second byte
            if (0x80 <= byte2 && byte2 <= 0x9F)
            {
                continue;
            }

            for (int byte3 = 0x80; byte3 <= 0xBF; ++byte3)
            {
                check_utf8string(false, byte1, byte2, byte3);
                check_utf8dump(false, byte1, byte2, byte3);
            }
        }
    }
}
  • cpp-test: [Unicode (2/5);RFC 3629;UTF8-3 (xED x80-9F UTF8-tail);ill-formed: wrong third byte] (tests/src/unit-unicode2.cpp)

SECTION("ill-formed: wrong third byte")
{
    for (int byte1 = 0xED; byte1 <= 0xED; ++byte1)
    {
        for (int byte2 = 0x80; byte2 <= 0x9F; ++byte2)
        {
            for (int byte3 = 0x00; byte3 <= 0xFF; ++byte3)
            {
                // skip correct third byte
                if (0x80 <= byte3 && byte3 <= 0xBF)
                {
                    continue;
                }

                check_utf8string(false, byte1, byte2, byte3);
                check_utf8dump(false, byte1, byte2, byte3);
            }
        }
    }
}
  • cpp-test: [Unicode (2/5);RFC 3629;UTF8-3 (xEE-xEF UTF8-tail UTF8-tail);ill-formed: missing second byte] (tests/src/unit-unicode2.cpp)

SECTION("ill-formed: missing second byte")
{
    for (int byte1 = 0xEE; byte1 <= 0xEF; ++byte1)
    {
        check_utf8string(false, byte1);
        check_utf8dump(false, byte1);
    }
}
  • cpp-test: [Unicode (2/5);RFC 3629;UTF8-3 (xEE-xEF UTF8-tail UTF8-tail);ill-formed: missing third byte] (tests/src/unit-unicode2.cpp)

SECTION("ill-formed: missing third byte")
{
    for (int byte1 = 0xEE; byte1 <= 0xEF; ++byte1)
    {
        for (int byte2 = 0x80; byte2 <= 0xBF; ++byte2)
        {
            check_utf8string(false, byte1, byte2);
            check_utf8dump(false, byte1, byte2);
        }
    }
}
  • cpp-test: [Unicode (2/5);RFC 3629;UTF8-3 (xEE-xEF UTF8-tail UTF8-tail);ill-formed: wrong second byte] (tests/src/unit-unicode2.cpp)

SECTION("ill-formed: wrong second byte")
{
    for (int byte1 = 0xEE; byte1 <= 0xEF; ++byte1)
    {
        for (int byte2 = 0x00; byte2 <= 0xFF; ++byte2)
        {
            // skip correct second byte
            if (0x80 <= byte2 && byte2 <= 0xBF)
            {
                continue;
            }

            for (int byte3 = 0x80; byte3 <= 0xBF; ++byte3)
            {
                check_utf8string(false, byte1, byte2, byte3);
                check_utf8dump(false, byte1, byte2, byte3);
            }
        }
    }
}
  • cpp-test: [Unicode (2/5);RFC 3629;UTF8-3 (xEE-xEF UTF8-tail UTF8-tail);ill-formed: wrong third byte] (tests/src/unit-unicode2.cpp)

SECTION("ill-formed: wrong third byte")
{
    for (int byte1 = 0xEE; byte1 <= 0xEF; ++byte1)
    {
        for (int byte2 = 0x80; byte2 <= 0xBF; ++byte2)
        {
            for (int byte3 = 0x00; byte3 <= 0xFF; ++byte3)
            {
                // skip correct third byte
                if (0x80 <= byte3 && byte3 <= 0xBF)
                {
                    continue;
                }

                check_utf8string(false, byte1, byte2, byte3);
                check_utf8dump(false, byte1, byte2, byte3);
            }
        }
    }
}
  • cpp-test: [Unicode (3/5);RFC 3629;UTF8-4 (xF0 x90-BF UTF8-tail UTF8-tail);ill-formed: missing second byte] (tests/src/unit-unicode3.cpp)

SECTION("ill-formed: missing second byte")
{
    for (int byte1 = 0xF0; byte1 <= 0xF0; ++byte1)
    {
        check_utf8string(false, byte1);
        check_utf8dump(false, byte1);
    }
}
  • cpp-test: [Unicode (3/5);RFC 3629;UTF8-4 (xF0 x90-BF UTF8-tail UTF8-tail);ill-formed: missing third byte] (tests/src/unit-unicode3.cpp)

SECTION("ill-formed: missing third byte")
{
    for (int byte1 = 0xF0; byte1 <= 0xF0; ++byte1)
    {
        for (int byte2 = 0x90; byte2 <= 0xBF; ++byte2)
        {
            check_utf8string(false, byte1, byte2);
            check_utf8dump(false, byte1, byte2);
        }
    }
}
  • cpp-test: [Unicode (3/5);RFC 3629;UTF8-4 (xF0 x90-BF UTF8-tail UTF8-tail);ill-formed: missing fourth byte] (tests/src/unit-unicode3.cpp)

SECTION("ill-formed: missing fourth byte")
{
    for (int byte1 = 0xF0; byte1 <= 0xF0; ++byte1)
    {
        for (int byte2 = 0x90; byte2 <= 0xBF; ++byte2)
        {
            for (int byte3 = 0x80; byte3 <= 0xBF; ++byte3)
            {
                check_utf8string(false, byte1, byte2, byte3);
                check_utf8dump(false, byte1, byte2, byte3);
            }
        }
    }
}
  • cpp-test: [Unicode (3/5);RFC 3629;UTF8-4 (xF0 x90-BF UTF8-tail UTF8-tail);ill-formed: wrong second byte] (tests/src/unit-unicode3.cpp)

SECTION("ill-formed: wrong second byte")
{
    for (int byte1 = 0xF0; byte1 <= 0xF0; ++byte1)
    {
        for (int byte2 = 0x00; byte2 <= 0xFF; ++byte2)
        {
            // skip correct second byte
            if (0x90 <= byte2 && byte2 <= 0xBF)
            {
                continue;
            }

            for (int byte3 = 0x80; byte3 <= 0xBF; ++byte3)
            {
                for (int byte4 = 0x80; byte4 <= 0xBF; ++byte4)
                {
                    check_utf8string(false, byte1, byte2, byte3, byte4);
                    check_utf8dump(false, byte1, byte2, byte3, byte4);
                }
            }
        }
    }
}
  • cpp-test: [Unicode (3/5);RFC 3629;UTF8-4 (xF0 x90-BF UTF8-tail UTF8-tail);ill-formed: wrong third byte] (tests/src/unit-unicode3.cpp)

SECTION("ill-formed: wrong third byte")
{
    for (int byte1 = 0xF0; byte1 <= 0xF0; ++byte1)
    {
        for (int byte2 = 0x90; byte2 <= 0xBF; ++byte2)
        {
            for (int byte3 = 0x00; byte3 <= 0xFF; ++byte3)
            {
                // skip correct third byte
                if (0x80 <= byte3 && byte3 <= 0xBF)
                {
                    continue;
                }

                for (int byte4 = 0x80; byte4 <= 0xBF; ++byte4)
                {
                    check_utf8string(false, byte1, byte2, byte3, byte4);
                    check_utf8dump(false, byte1, byte2, byte3, byte4);
                }
            }
        }
    }
}
  • cpp-test: [Unicode (3/5);RFC 3629;UTF8-4 (xF0 x90-BF UTF8-tail UTF8-tail);ill-formed: wrong fourth byte] (tests/src/unit-unicode3.cpp)

SECTION("ill-formed: wrong fourth byte")
{
    for (int byte1 = 0xF0; byte1 <= 0xF0; ++byte1)
    {
        for (int byte2 = 0x90; byte2 <= 0xBF; ++byte2)
        {
            for (int byte3 = 0x80; byte3 <= 0xBF; ++byte3)
            {
                for (int byte4 = 0x00; byte4 <= 0xFF; ++byte4)
                {
                    // skip fourth second byte
                    if (0x80 <= byte3 && byte3 <= 0xBF)
                    {
                        continue;
                    }

                    check_utf8string(false, byte1, byte2, byte3, byte4);
                    check_utf8dump(false, byte1, byte2, byte3, byte4);
                }
            }
        }
    }
}
  • cpp-test: [Unicode (4/5);RFC 3629;UTF8-4 (xF1-F3 UTF8-tail UTF8-tail UTF8-tail);ill-formed: missing second byte] (tests/src/unit-unicode4.cpp)

SECTION("ill-formed: missing second byte")
{
    for (int byte1 = 0xF1; byte1 <= 0xF3; ++byte1)
    {
        check_utf8string(false, byte1);
        check_utf8dump(false, byte1);
    }
}
  • cpp-test: [Unicode (4/5);RFC 3629;UTF8-4 (xF1-F3 UTF8-tail UTF8-tail UTF8-tail);ill-formed: missing third byte] (tests/src/unit-unicode4.cpp)

SECTION("ill-formed: missing third byte")
{
    for (int byte1 = 0xF1; byte1 <= 0xF3; ++byte1)
    {
        for (int byte2 = 0x80; byte2 <= 0xBF; ++byte2)
        {
            check_utf8string(false, byte1, byte2);
            check_utf8dump(false, byte1, byte2);
        }
    }
}
  • cpp-test: [Unicode (4/5);RFC 3629;UTF8-4 (xF1-F3 UTF8-tail UTF8-tail UTF8-tail);ill-formed: missing fourth byte] (tests/src/unit-unicode4.cpp)

SECTION("ill-formed: missing fourth byte")
{
    for (int byte1 = 0xF1; byte1 <= 0xF3; ++byte1)
    {
        for (int byte2 = 0x80; byte2 <= 0xBF; ++byte2)
        {
            for (int byte3 = 0x80; byte3 <= 0xBF; ++byte3)
            {
                check_utf8string(false, byte1, byte2, byte3);
                check_utf8dump(false, byte1, byte2, byte3);
            }
        }
    }
}
  • cpp-test: [Unicode (4/5);RFC 3629;UTF8-4 (xF1-F3 UTF8-tail UTF8-tail UTF8-tail);ill-formed: wrong second byte] (tests/src/unit-unicode4.cpp)

SECTION("ill-formed: wrong second byte")
{
    for (int byte1 = 0xF1; byte1 <= 0xF3; ++byte1)
    {
        for (int byte2 = 0x00; byte2 <= 0xFF; ++byte2)
        {
            // skip correct second byte
            if (0x80 <= byte2 && byte2 <= 0xBF)
            {
                continue;
            }

            for (int byte3 = 0x80; byte3 <= 0xBF; ++byte3)
            {
                for (int byte4 = 0x80; byte4 <= 0xBF; ++byte4)
                {
                    check_utf8string(false, byte1, byte2, byte3, byte4);
                    check_utf8dump(false, byte1, byte2, byte3, byte4);
                }
            }
        }
    }
}
  • cpp-test: [Unicode (4/5);RFC 3629;UTF8-4 (xF1-F3 UTF8-tail UTF8-tail UTF8-tail);ill-formed: wrong third byte] (tests/src/unit-unicode4.cpp)

SECTION("ill-formed: wrong third byte")
{
    for (int byte1 = 0xF1; byte1 <= 0xF3; ++byte1)
    {
        for (int byte2 = 0x80; byte2 <= 0xBF; ++byte2)
        {
            for (int byte3 = 0x00; byte3 <= 0xFF; ++byte3)
            {
                // skip correct third byte
                if (0x80 <= byte3 && byte3 <= 0xBF)
                {
                    continue;
                }

                for (int byte4 = 0x80; byte4 <= 0xBF; ++byte4)
                {
                    check_utf8string(false, byte1, byte2, byte3, byte4);
                    check_utf8dump(false, byte1, byte2, byte3, byte4);
                }
            }
        }
    }
}
  • cpp-test: [Unicode (4/5);RFC 3629;UTF8-4 (xF1-F3 UTF8-tail UTF8-tail UTF8-tail);ill-formed: wrong fourth byte] (tests/src/unit-unicode4.cpp)

SECTION("ill-formed: wrong fourth byte")
{
    for (int byte1 = 0xF1; byte1 <= 0xF3; ++byte1)
    {
        for (int byte2 = 0x80; byte2 <= 0xBF; ++byte2)
        {
            for (int byte3 = 0x80; byte3 <= 0xBF; ++byte3)
            {
                for (int byte4 = 0x00; byte4 <= 0xFF; ++byte4)
                {
                    // skip correct fourth byte
                    if (0x80 <= byte3 && byte3 <= 0xBF)
                    {
                        continue;
                    }

                    check_utf8string(false, byte1, byte2, byte3, byte4);
                    check_utf8dump(false, byte1, byte2, byte3, byte4);
                }
            }
        }
    }
}
  • cpp-test: [Unicode (5/5);RFC 3629;UTF8-4 (xF4 x80-8F UTF8-tail UTF8-tail);ill-formed: missing second byte] (tests/src/unit-unicode5.cpp)

SECTION("ill-formed: missing second byte")
{
    for (int byte1 = 0xF4; byte1 <= 0xF4; ++byte1)
    {
        check_utf8string(false, byte1);
        check_utf8dump(false, byte1);
    }
}
  • cpp-test: [Unicode (5/5);RFC 3629;UTF8-4 (xF4 x80-8F UTF8-tail UTF8-tail);ill-formed: missing third byte] (tests/src/unit-unicode5.cpp)

SECTION("ill-formed: missing third byte")
{
    for (int byte1 = 0xF4; byte1 <= 0xF4; ++byte1)
    {
        for (int byte2 = 0x80; byte2 <= 0x8F; ++byte2)
        {
            check_utf8string(false, byte1, byte2);
            check_utf8dump(false, byte1, byte2);
        }
    }
}
  • cpp-test: [Unicode (5/5);RFC 3629;UTF8-4 (xF4 x80-8F UTF8-tail UTF8-tail);ill-formed: missing fourth byte] (tests/src/unit-unicode5.cpp)

SECTION("ill-formed: missing fourth byte")
{
    for (int byte1 = 0xF4; byte1 <= 0xF4; ++byte1)
    {
        for (int byte2 = 0x80; byte2 <= 0x8F; ++byte2)
        {
            for (int byte3 = 0x80; byte3 <= 0xBF; ++byte3)
            {
                check_utf8string(false, byte1, byte2, byte3);
                check_utf8dump(false, byte1, byte2, byte3);
            }
        }
    }
}
  • cpp-test: [Unicode (5/5);RFC 3629;UTF8-4 (xF4 x80-8F UTF8-tail UTF8-tail);ill-formed: wrong second byte] (tests/src/unit-unicode5.cpp)

SECTION("ill-formed: wrong second byte")
{
    for (int byte1 = 0xF4; byte1 <= 0xF4; ++byte1)
    {
        for (int byte2 = 0x00; byte2 <= 0xFF; ++byte2)
        {
            // skip correct second byte
            if (0x80 <= byte2 && byte2 <= 0x8F)
            {
                continue;
            }

            for (int byte3 = 0x80; byte3 <= 0xBF; ++byte3)
            {
                for (int byte4 = 0x80; byte4 <= 0xBF; ++byte4)
                {
                    check_utf8string(false, byte1, byte2, byte3, byte4);
                    check_utf8dump(false, byte1, byte2, byte3, byte4);
                }
            }
        }
    }
}
  • cpp-test: [Unicode (5/5);RFC 3629;UTF8-4 (xF4 x80-8F UTF8-tail UTF8-tail);ill-formed: wrong third byte] (tests/src/unit-unicode5.cpp)

SECTION("ill-formed: wrong third byte")
{
    for (int byte1 = 0xF4; byte1 <= 0xF4; ++byte1)
    {
        for (int byte2 = 0x80; byte2 <= 0x8F; ++byte2)
        {
            for (int byte3 = 0x00; byte3 <= 0xFF; ++byte3)
            {
                // skip correct third byte
                if (0x80 <= byte3 && byte3 <= 0xBF)
                {
                    continue;
                }

                for (int byte4 = 0x80; byte4 <= 0xBF; ++byte4)
                {
                    check_utf8string(false, byte1, byte2, byte3, byte4);
                    check_utf8dump(false, byte1, byte2, byte3, byte4);
                }
            }
        }
    }
}
  • cpp-test: [Unicode (5/5);RFC 3629;UTF8-4 (xF4 x80-8F UTF8-tail UTF8-tail);ill-formed: wrong fourth byte] (tests/src/unit-unicode5.cpp)

SECTION("ill-formed: wrong fourth byte")
{
    for (int byte1 = 0xF4; byte1 <= 0xF4; ++byte1)
    {
        for (int byte2 = 0x80; byte2 <= 0x8F; ++byte2)
        {
            for (int byte3 = 0x80; byte3 <= 0xBF; ++byte3)
            {
                for (int byte4 = 0x00; byte4 <= 0xFF; ++byte4)
                {
                    // skip correct fourth byte
                    if (0x80 <= byte3 && byte3 <= 0xBF)
                    {
                        continue;
                    }

                    check_utf8string(false, byte1, byte2, byte3, byte4);
                    check_utf8dump(false, byte1, byte2, byte3, byte4);
                }
            }
        }
    }
}

Fallacies:

None

Graph:

No Historic Data Found