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