added more Unicode test cases

上级 734297ff
...@@ -74,523 +74,525 @@ void check_utf8string(bool success_expected, int byte1, int byte2 = -1, int byte ...@@ -74,523 +74,525 @@ void check_utf8string(bool success_expected, int byte1, int byte2 = -1, int byte
} }
} }
TEST_CASE("RFC 3629", "[hide]") TEST_CASE("Unicode", "[hide]")
{ {
/* SECTION("RFC 3629")
RFC 3629 describes in Sect. 4 the syntax of UTF-8 byte sequences as
follows:
A UTF-8 string is a sequence of octets representing a sequence of UCS
characters. An octet sequence is valid UTF-8 only if it matches the
following syntax, which is derived from the rules for encoding UTF-8
and is expressed in the ABNF of [RFC2234].
UTF8-octets = *( UTF8-char )
UTF8-char = UTF8-1 / UTF8-2 / UTF8-3 / UTF8-4
UTF8-1 = %x00-7F
UTF8-2 = %xC2-DF UTF8-tail
UTF8-3 = %xE0 %xA0-BF UTF8-tail / %xE1-EC 2( UTF8-tail ) /
%xED %x80-9F UTF8-tail / %xEE-EF 2( UTF8-tail )
UTF8-4 = %xF0 %x90-BF 2( UTF8-tail ) / %xF1-F3 3( UTF8-tail ) /
%xF4 %x80-8F 2( UTF8-tail )
UTF8-tail = %x80-BF
*/
SECTION("ill-formed first byte")
{ {
for (int byte1 = 0x80; byte1 <= 0xC1; ++byte1) /*
RFC 3629 describes in Sect. 4 the syntax of UTF-8 byte sequences as
follows:
A UTF-8 string is a sequence of octets representing a sequence of UCS
characters. An octet sequence is valid UTF-8 only if it matches the
following syntax, which is derived from the rules for encoding UTF-8
and is expressed in the ABNF of [RFC2234].
UTF8-octets = *( UTF8-char )
UTF8-char = UTF8-1 / UTF8-2 / UTF8-3 / UTF8-4
UTF8-1 = %x00-7F
UTF8-2 = %xC2-DF UTF8-tail
UTF8-3 = %xE0 %xA0-BF UTF8-tail / %xE1-EC 2( UTF8-tail ) /
%xED %x80-9F UTF8-tail / %xEE-EF 2( UTF8-tail )
UTF8-4 = %xF0 %x90-BF 2( UTF8-tail ) / %xF1-F3 3( UTF8-tail ) /
%xF4 %x80-8F 2( UTF8-tail )
UTF8-tail = %x80-BF
*/
SECTION("ill-formed first byte")
{ {
check_utf8string(false, byte1); for (int byte1 = 0x80; byte1 <= 0xC1; ++byte1)
} {
check_utf8string(false, byte1);
}
for (int byte1 = 0xF5; byte1 <= 0xFF; ++byte1) for (int byte1 = 0xF5; byte1 <= 0xFF; ++byte1)
{ {
check_utf8string(false, byte1); check_utf8string(false, byte1);
}
} }
}
SECTION("UTF8-1 (x00-x7F)") SECTION("UTF8-1 (x00-x7F)")
{
SECTION("well-formed")
{ {
for (int byte1 = 0x00; byte1 <= 0x7F; ++byte1) SECTION("well-formed")
{ {
// unescaped control characters are parse errors in JSON for (int byte1 = 0x00; byte1 <= 0x7F; ++byte1)
if (0x00 <= byte1 and byte1 <= 0x1F)
{ {
check_utf8string(false, byte1); // unescaped control characters are parse errors in JSON
continue; if (0x00 <= byte1 and byte1 <= 0x1F)
} {
check_utf8string(false, byte1);
continue;
}
// a single quote is a parse error in JSON // a single quote is a parse error in JSON
if (byte1 == 0x22) if (byte1 == 0x22)
{ {
check_utf8string(false, byte1); check_utf8string(false, byte1);
continue; continue;
} }
// a single backslash is a parse error in JSON // a single backslash is a parse error in JSON
if (byte1 == 0x5C) if (byte1 == 0x5C)
{ {
check_utf8string(false, byte1); check_utf8string(false, byte1);
continue; continue;
} }
// all other characters are OK // all other characters are OK
check_utf8string(true, byte1); check_utf8string(true, byte1);
}
} }
} }
}
SECTION("UTF8-2 (xC2-xDF UTF8-tail)") SECTION("UTF8-2 (xC2-xDF UTF8-tail)")
{
SECTION("well-formed")
{ {
for (int byte1 = 0xC2; byte1 <= 0xDF; ++byte1) SECTION("well-formed")
{ {
for (int byte2 = 0x80; byte2 <= 0xBF; ++byte2) for (int byte1 = 0xC2; byte1 <= 0xDF; ++byte1)
{ {
check_utf8string(true, byte1, byte2); for (int byte2 = 0x80; byte2 <= 0xBF; ++byte2)
{
check_utf8string(true, byte1, byte2);
}
} }
} }
}
SECTION("ill-formed: missing second byte") SECTION("ill-formed: missing second byte")
{
for (int byte1 = 0xC2; byte1 <= 0xDF; ++byte1)
{ {
check_utf8string(false, byte1); for (int byte1 = 0xC2; byte1 <= 0xDF; ++byte1)
{
check_utf8string(false, byte1);
}
} }
}
SECTION("ill-formed: wrong second byte") SECTION("ill-formed: wrong second byte")
{
for (int byte1 = 0xC2; byte1 <= 0xDF; ++byte1)
{ {
for (int byte2 = 0x00; byte2 <= 0xFF; ++byte2) for (int byte1 = 0xC2; byte1 <= 0xDF; ++byte1)
{ {
// skip correct second byte for (int byte2 = 0x00; byte2 <= 0xFF; ++byte2)
if (0x80 <= byte2 and byte2 <= 0xBF)
{ {
continue; // skip correct second byte
} if (0x80 <= byte2 and byte2 <= 0xBF)
{
continue;
}
check_utf8string(false, byte1, byte2); check_utf8string(false, byte1, byte2);
}
} }
} }
} }
}
SECTION("UTF8-3 (xE0 xA0-BF UTF8-tail)") SECTION("UTF8-3 (xE0 xA0-BF UTF8-tail)")
{
SECTION("well-formed")
{ {
for (int byte1 = 0xE0; byte1 <= 0xE0; ++byte1) SECTION("well-formed")
{ {
for (int byte2 = 0xA0; byte2 <= 0xBF; ++byte2) for (int byte1 = 0xE0; byte1 <= 0xE0; ++byte1)
{ {
for (int byte3 = 0x80; byte3 <= 0xBF; ++byte3) for (int byte2 = 0xA0; byte2 <= 0xBF; ++byte2)
{ {
check_utf8string(true, byte1, byte2, byte3); for (int byte3 = 0x80; byte3 <= 0xBF; ++byte3)
{
check_utf8string(true, byte1, byte2, byte3);
}
} }
} }
} }
}
SECTION("ill-formed: missing second byte")
{
for (int byte1 = 0xE0; byte1 <= 0xE0; ++byte1)
{
check_utf8string(false, byte1);
}
}
SECTION("ill-formed: missing third byte") SECTION("ill-formed: missing second byte")
{
for (int byte1 = 0xE0; byte1 <= 0xE0; ++byte1)
{ {
for (int byte2 = 0xA0; byte2 <= 0xBF; ++byte2) for (int byte1 = 0xE0; byte1 <= 0xE0; ++byte1)
{ {
check_utf8string(false, byte1, byte2); check_utf8string(false, byte1);
} }
} }
}
SECTION("ill-formed: wrong second byte") SECTION("ill-formed: missing third byte")
{
for (int byte1 = 0xE0; byte1 <= 0xE0; ++byte1)
{ {
for (int byte2 = 0x00; byte2 <= 0xFF; ++byte2) for (int byte1 = 0xE0; byte1 <= 0xE0; ++byte1)
{ {
// skip correct second byte for (int byte2 = 0xA0; byte2 <= 0xBF; ++byte2)
if (0xA0 <= byte2 and byte2 <= 0xBF)
{ {
continue; check_utf8string(false, byte1, byte2);
}
for (int byte3 = 0x80; byte3 <= 0xBF; ++byte3)
{
check_utf8string(false, byte1, byte2, byte3);
} }
} }
} }
}
SECTION("ill-formed: wrong third byte") SECTION("ill-formed: wrong second byte")
{
for (int byte1 = 0xE0; byte1 <= 0xE0; ++byte1)
{ {
for (int byte2 = 0xA0; byte2 <= 0xBF; ++byte2) for (int byte1 = 0xE0; byte1 <= 0xE0; ++byte1)
{ {
for (int byte3 = 0x00; byte3 <= 0xFF; ++byte3) for (int byte2 = 0x00; byte2 <= 0xFF; ++byte2)
{ {
// skip correct third byte // skip correct second byte
if (0x80 <= byte3 and byte3 <= 0xBF) if (0xA0 <= byte2 and byte2 <= 0xBF)
{ {
continue; continue;
} }
check_utf8string(false, byte1, byte2, byte3); for (int byte3 = 0x80; byte3 <= 0xBF; ++byte3)
{
check_utf8string(false, byte1, byte2, byte3);
}
} }
} }
} }
}
}
SECTION("UTF8-3 (xE1-xEC UTF8-tail UTF8-tail)") SECTION("ill-formed: wrong third byte")
{
SECTION("well-formed")
{
for (int byte1 = 0xE1; byte1 <= 0xEC; ++byte1)
{ {
for (int byte2 = 0x80; byte2 <= 0xBF; ++byte2) for (int byte1 = 0xE0; byte1 <= 0xE0; ++byte1)
{ {
for (int byte3 = 0x80; byte3 <= 0xBF; ++byte3) for (int byte2 = 0xA0; byte2 <= 0xBF; ++byte2)
{ {
check_utf8string(true, byte1, byte2, byte3); for (int byte3 = 0x00; byte3 <= 0xFF; ++byte3)
{
// skip correct third byte
if (0x80 <= byte3 and byte3 <= 0xBF)
{
continue;
}
check_utf8string(false, byte1, byte2, byte3);
}
} }
} }
} }
} }
SECTION("ill-formed: missing second byte") SECTION("UTF8-3 (xE1-xEC UTF8-tail UTF8-tail)")
{ {
for (int byte1 = 0xE1; byte1 <= 0xEC; ++byte1) SECTION("well-formed")
{ {
check_utf8string(false, byte1); 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);
}
}
}
} }
}
SECTION("ill-formed: missing third byte") SECTION("ill-formed: missing second byte")
{
for (int byte1 = 0xE1; byte1 <= 0xEC; ++byte1)
{ {
for (int byte2 = 0x80; byte2 <= 0xBF; ++byte2) for (int byte1 = 0xE1; byte1 <= 0xEC; ++byte1)
{ {
check_utf8string(false, byte1, byte2); check_utf8string(false, byte1);
} }
} }
}
SECTION("ill-formed: wrong second byte") SECTION("ill-formed: missing third byte")
{
for (int byte1 = 0xE1; byte1 <= 0xEC; ++byte1)
{ {
for (int byte2 = 0x00; byte2 <= 0xFF; ++byte2) for (int byte1 = 0xE1; byte1 <= 0xEC; ++byte1)
{ {
// skip correct second byte for (int byte2 = 0x80; byte2 <= 0xBF; ++byte2)
if (0x80 <= byte2 and byte2 <= 0xBF)
{
continue;
}
for (int byte3 = 0x80; byte3 <= 0xBF; ++byte3)
{ {
check_utf8string(false, byte1, byte2, byte3); check_utf8string(false, byte1, byte2);
} }
} }
} }
}
SECTION("ill-formed: wrong third byte") SECTION("ill-formed: wrong second byte")
{
for (int byte1 = 0xE1; byte1 <= 0xEC; ++byte1)
{ {
for (int byte2 = 0x80; byte2 <= 0xBF; ++byte2) for (int byte1 = 0xE1; byte1 <= 0xEC; ++byte1)
{ {
for (int byte3 = 0x00; byte3 <= 0xFF; ++byte3) for (int byte2 = 0x00; byte2 <= 0xFF; ++byte2)
{ {
// skip correct third byte // skip correct second byte
if (0x80 <= byte3 and byte3 <= 0xBF) if (0x80 <= byte2 and byte2 <= 0xBF)
{ {
continue; continue;
} }
check_utf8string(false, byte1, byte2, byte3); for (int byte3 = 0x80; byte3 <= 0xBF; ++byte3)
{
check_utf8string(false, byte1, byte2, byte3);
}
} }
} }
} }
}
}
SECTION("UTF8-3 (xED x80-9F UTF8-tail)") SECTION("ill-formed: wrong third byte")
{
SECTION("well-formed")
{
for (int byte1 = 0xED; byte1 <= 0xED; ++byte1)
{ {
for (int byte2 = 0x80; byte2 <= 0x9F; ++byte2) for (int byte1 = 0xE1; byte1 <= 0xEC; ++byte1)
{ {
for (int byte3 = 0x80; byte3 <= 0xBF; ++byte3) for (int byte2 = 0x80; byte2 <= 0xBF; ++byte2)
{ {
check_utf8string(true, byte1, byte2, byte3); for (int byte3 = 0x00; byte3 <= 0xFF; ++byte3)
{
// skip correct third byte
if (0x80 <= byte3 and byte3 <= 0xBF)
{
continue;
}
check_utf8string(false, byte1, byte2, byte3);
}
} }
} }
} }
} }
SECTION("ill-formed: missing second byte") SECTION("UTF8-3 (xED x80-9F UTF8-tail)")
{ {
for (int byte1 = 0xED; byte1 <= 0xED; ++byte1) SECTION("well-formed")
{ {
check_utf8string(false, byte1); 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);
}
}
}
} }
}
SECTION("ill-formed: missing third byte") SECTION("ill-formed: missing second byte")
{
for (int byte1 = 0xED; byte1 <= 0xED; ++byte1)
{ {
for (int byte2 = 0x80; byte2 <= 0x9F; ++byte2) for (int byte1 = 0xED; byte1 <= 0xED; ++byte1)
{ {
check_utf8string(false, byte1, byte2); check_utf8string(false, byte1);
} }
} }
}
SECTION("ill-formed: wrong second byte") SECTION("ill-formed: missing third byte")
{
for (int byte1 = 0xED; byte1 <= 0xED; ++byte1)
{ {
for (int byte2 = 0x00; byte2 <= 0xFF; ++byte2) for (int byte1 = 0xED; byte1 <= 0xED; ++byte1)
{ {
// skip correct second byte for (int byte2 = 0x80; byte2 <= 0x9F; ++byte2)
if (0x80 <= byte2 and byte2 <= 0x9F)
{
continue;
}
for (int byte3 = 0x80; byte3 <= 0xBF; ++byte3)
{ {
check_utf8string(false, byte1, byte2, byte3); check_utf8string(false, byte1, byte2);
} }
} }
} }
}
SECTION("ill-formed: wrong third byte") SECTION("ill-formed: wrong second byte")
{
for (int byte1 = 0xED; byte1 <= 0xED; ++byte1)
{ {
for (int byte2 = 0x80; byte2 <= 0x9F; ++byte2) for (int byte1 = 0xED; byte1 <= 0xED; ++byte1)
{ {
for (int byte3 = 0x00; byte3 <= 0xFF; ++byte3) for (int byte2 = 0x00; byte2 <= 0xFF; ++byte2)
{ {
// skip correct third byte // skip correct second byte
if (0x80 <= byte3 and byte3 <= 0xBF) if (0x80 <= byte2 and byte2 <= 0x9F)
{ {
continue; continue;
} }
check_utf8string(false, byte1, byte2, byte3); for (int byte3 = 0x80; byte3 <= 0xBF; ++byte3)
{
check_utf8string(false, byte1, byte2, byte3);
}
} }
} }
} }
}
}
SECTION("UTF8-3 (xEE-xEF UTF8-tail UTF8-tail)") SECTION("ill-formed: wrong third byte")
{
SECTION("well-formed")
{
for (int byte1 = 0xEE; byte1 <= 0xEF; ++byte1)
{ {
for (int byte2 = 0x80; byte2 <= 0xBF; ++byte2) for (int byte1 = 0xED; byte1 <= 0xED; ++byte1)
{ {
for (int byte3 = 0x80; byte3 <= 0xBF; ++byte3) for (int byte2 = 0x80; byte2 <= 0x9F; ++byte2)
{ {
check_utf8string(true, byte1, byte2, byte3); for (int byte3 = 0x00; byte3 <= 0xFF; ++byte3)
{
// skip correct third byte
if (0x80 <= byte3 and byte3 <= 0xBF)
{
continue;
}
check_utf8string(false, byte1, byte2, byte3);
}
} }
} }
} }
} }
SECTION("ill-formed: missing second byte") SECTION("UTF8-3 (xEE-xEF UTF8-tail UTF8-tail)")
{ {
for (int byte1 = 0xEE; byte1 <= 0xEF; ++byte1) SECTION("well-formed")
{ {
check_utf8string(false, byte1); 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);
}
}
}
} }
}
SECTION("ill-formed: missing third byte") SECTION("ill-formed: missing second byte")
{
for (int byte1 = 0xEE; byte1 <= 0xEF; ++byte1)
{ {
for (int byte2 = 0x80; byte2 <= 0xBF; ++byte2) for (int byte1 = 0xEE; byte1 <= 0xEF; ++byte1)
{ {
check_utf8string(false, byte1, byte2); check_utf8string(false, byte1);
} }
} }
}
SECTION("ill-formed: wrong second byte") SECTION("ill-formed: missing third byte")
{
for (int byte1 = 0xEE; byte1 <= 0xEF; ++byte1)
{ {
for (int byte2 = 0x00; byte2 <= 0xFF; ++byte2) for (int byte1 = 0xEE; byte1 <= 0xEF; ++byte1)
{ {
// skip correct second byte for (int byte2 = 0x80; byte2 <= 0xBF; ++byte2)
if (0x80 <= byte2 and byte2 <= 0xBF)
{ {
continue; check_utf8string(false, byte1, byte2);
}
for (int byte3 = 0x80; byte3 <= 0xBF; ++byte3)
{
check_utf8string(false, byte1, byte2, byte3);
} }
} }
} }
}
SECTION("ill-formed: wrong third byte") SECTION("ill-formed: wrong second byte")
{
for (int byte1 = 0xEE; byte1 <= 0xEF; ++byte1)
{ {
for (int byte2 = 0x80; byte2 <= 0xBF; ++byte2) for (int byte1 = 0xEE; byte1 <= 0xEF; ++byte1)
{ {
for (int byte3 = 0x00; byte3 <= 0xFF; ++byte3) for (int byte2 = 0x00; byte2 <= 0xFF; ++byte2)
{ {
// skip correct third byte // skip correct second byte
if (0x80 <= byte3 and byte3 <= 0xBF) if (0x80 <= byte2 and byte2 <= 0xBF)
{ {
continue; continue;
} }
check_utf8string(false, byte1, byte2, byte3); for (int byte3 = 0x80; byte3 <= 0xBF; ++byte3)
{
check_utf8string(false, byte1, byte2, byte3);
}
} }
} }
} }
}
}
SECTION("UTF8-4 (xF0 x90-BF UTF8-tail UTF8-tail)") SECTION("ill-formed: wrong third byte")
{
SECTION("well-formed")
{
for (int byte1 = 0xF0; byte1 <= 0xF0; ++byte1)
{ {
for (int byte2 = 0x90; byte2 <= 0xBF; ++byte2) for (int byte1 = 0xEE; byte1 <= 0xEF; ++byte1)
{ {
for (int byte3 = 0x80; byte3 <= 0xBF; ++byte3) for (int byte2 = 0x80; byte2 <= 0xBF; ++byte2)
{ {
for (int byte4 = 0x80; byte4 <= 0xBF; ++byte4) for (int byte3 = 0x00; byte3 <= 0xFF; ++byte3)
{ {
check_utf8string(true, byte1, byte2, byte3, byte4); // skip correct third byte
if (0x80 <= byte3 and byte3 <= 0xBF)
{
continue;
}
check_utf8string(false, byte1, byte2, byte3);
} }
} }
} }
} }
} }
SECTION("ill-formed: missing second byte") SECTION("UTF8-4 (xF0 x90-BF UTF8-tail UTF8-tail)")
{ {
for (int byte1 = 0xF0; byte1 <= 0xF0; ++byte1) SECTION("well-formed")
{ {
check_utf8string(false, byte1); 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);
}
}
}
}
} }
}
SECTION("ill-formed: missing third byte") SECTION("ill-formed: missing second byte")
{
for (int byte1 = 0xF0; byte1 <= 0xF0; ++byte1)
{ {
for (int byte2 = 0x90; byte2 <= 0xBF; ++byte2) for (int byte1 = 0xF0; byte1 <= 0xF0; ++byte1)
{ {
check_utf8string(false, byte1, byte2); check_utf8string(false, byte1);
} }
} }
}
SECTION("ill-formed: missing fourth byte") SECTION("ill-formed: missing third byte")
{
for (int byte1 = 0xF0; byte1 <= 0xF0; ++byte1)
{ {
for (int byte2 = 0x90; byte2 <= 0xBF; ++byte2) for (int byte1 = 0xF0; byte1 <= 0xF0; ++byte1)
{ {
for (int byte3 = 0x80; byte3 <= 0xBF; ++byte3) for (int byte2 = 0x90; byte2 <= 0xBF; ++byte2)
{ {
check_utf8string(false, byte1, byte2, byte3); check_utf8string(false, byte1, byte2);
} }
} }
} }
}
SECTION("ill-formed: wrong second byte") SECTION("ill-formed: missing fourth byte")
{
for (int byte1 = 0xF0; byte1 <= 0xF0; ++byte1)
{ {
for (int byte2 = 0x00; byte2 <= 0xFF; ++byte2) for (int byte1 = 0xF0; byte1 <= 0xF0; ++byte1)
{ {
// skip correct second byte for (int byte2 = 0x90; byte2 <= 0xBF; ++byte2)
if (0x90 <= byte2 and byte2 <= 0xBF)
{
continue;
}
for (int byte3 = 0x80; byte3 <= 0xBF; ++byte3)
{ {
for (int byte4 = 0x80; byte4 <= 0xBF; ++byte4) for (int byte3 = 0x80; byte3 <= 0xBF; ++byte3)
{ {
check_utf8string(false, byte1, byte2, byte3, byte4); check_utf8string(false, byte1, byte2, byte3);
} }
} }
} }
} }
}
SECTION("ill-formed: wrong third byte") SECTION("ill-formed: wrong second byte")
{
for (int byte1 = 0xF0; byte1 <= 0xF0; ++byte1)
{ {
for (int byte2 = 0x90; byte2 <= 0xBF; ++byte2) for (int byte1 = 0xF0; byte1 <= 0xF0; ++byte1)
{ {
for (int byte3 = 0x00; byte3 <= 0xFF; ++byte3) for (int byte2 = 0x00; byte2 <= 0xFF; ++byte2)
{ {
// skip correct third byte // skip correct second byte
if (0x80 <= byte3 and byte3 <= 0xBF) if (0x90 <= byte2 and byte2 <= 0xBF)
{ {
continue; continue;
} }
for (int byte4 = 0x80; byte4 <= 0xBF; ++byte4) for (int byte3 = 0x80; byte3 <= 0xBF; ++byte3)
{ {
check_utf8string(false, byte1, byte2, byte3, byte4); for (int byte4 = 0x80; byte4 <= 0xBF; ++byte4)
{
check_utf8string(false, byte1, byte2, byte3, byte4);
}
} }
} }
} }
} }
}
SECTION("ill-formed: wrong fourth byte") SECTION("ill-formed: wrong third byte")
{
for (int byte1 = 0xF0; byte1 <= 0xF0; ++byte1)
{ {
for (int byte2 = 0x90; byte2 <= 0xBF; ++byte2) for (int byte1 = 0xF0; byte1 <= 0xF0; ++byte1)
{ {
for (int byte3 = 0x80; byte3 <= 0xBF; ++byte3) for (int byte2 = 0x90; byte2 <= 0xBF; ++byte2)
{ {
for (int byte3 = 0x00; byte3 <= 0xFF; ++byte3)
{
// skip correct third byte
if (0x80 <= byte3 and byte3 <= 0xBF)
{
continue;
}
for (int byte4 = 0x80; byte4 <= 0xBF; ++byte4)
{
check_utf8string(false, byte1, byte2, byte3, byte4);
}
}
}
}
}
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) for (int byte4 = 0x00; byte4 <= 0xFF; ++byte4)
{ {
// skip fourth second byte // skip fourth second byte
...@@ -601,269 +603,263 @@ TEST_CASE("RFC 3629", "[hide]") ...@@ -601,269 +603,263 @@ TEST_CASE("RFC 3629", "[hide]")
check_utf8string(false, byte1, byte2, byte3, byte4); check_utf8string(false, byte1, byte2, byte3, byte4);
} }
}
} }
} }
} }
} }
}
SECTION("UTF8-4 (xF1-F3 UTF8-tail UTF8-tail UTF8-tail)") SECTION("UTF8-4 (xF1-F3 UTF8-tail UTF8-tail UTF8-tail)")
{
SECTION("well-formed")
{ {
for (int byte1 = 0xF1; byte1 <= 0xF3; ++byte1) SECTION("well-formed")
{ {
for (int byte2 = 0x80; byte2 <= 0xBF; ++byte2) for (int byte1 = 0xF1; byte1 <= 0xF3; ++byte1)
{ {
for (int byte3 = 0x80; byte3 <= 0xBF; ++byte3) for (int byte2 = 0x80; byte2 <= 0xBF; ++byte2)
{ {
for (int byte4 = 0x80; byte4 <= 0xBF; ++byte4) for (int byte3 = 0x80; byte3 <= 0xBF; ++byte3)
{ {
check_utf8string(true, byte1, byte2, byte3, byte4); for (int byte4 = 0x80; byte4 <= 0xBF; ++byte4)
{
check_utf8string(true, byte1, byte2, byte3, byte4);
}
} }
} }
} }
} }
}
SECTION("ill-formed: missing second byte")
{
for (int byte1 = 0xF1; byte1 <= 0xF3; ++byte1)
{
check_utf8string(false, byte1);
}
}
SECTION("ill-formed: missing third byte") SECTION("ill-formed: missing second byte")
{
for (int byte1 = 0xF1; byte1 <= 0xF3; ++byte1)
{ {
for (int byte2 = 0x80; byte2 <= 0xBF; ++byte2) for (int byte1 = 0xF1; byte1 <= 0xF3; ++byte1)
{ {
check_utf8string(false, byte1, byte2); check_utf8string(false, byte1);
} }
} }
}
SECTION("ill-formed: missing fourth byte") SECTION("ill-formed: missing third byte")
{
for (int byte1 = 0xF1; byte1 <= 0xF3; ++byte1)
{ {
for (int byte2 = 0x80; byte2 <= 0xBF; ++byte2) for (int byte1 = 0xF1; byte1 <= 0xF3; ++byte1)
{ {
for (int byte3 = 0x80; byte3 <= 0xBF; ++byte3) for (int byte2 = 0x80; byte2 <= 0xBF; ++byte2)
{ {
check_utf8string(false, byte1, byte2, byte3); check_utf8string(false, byte1, byte2);
} }
} }
} }
}
SECTION("ill-formed: wrong second byte") SECTION("ill-formed: missing fourth byte")
{
for (int byte1 = 0xF1; byte1 <= 0xF3; ++byte1)
{ {
for (int byte2 = 0x00; byte2 <= 0xFF; ++byte2) for (int byte1 = 0xF1; byte1 <= 0xF3; ++byte1)
{ {
// skip correct second byte for (int byte2 = 0x80; byte2 <= 0xBF; ++byte2)
if (0x80 <= byte2 and byte2 <= 0xBF)
{ {
continue; for (int byte3 = 0x80; byte3 <= 0xBF; ++byte3)
}
for (int byte3 = 0x80; byte3 <= 0xBF; ++byte3)
{
for (int byte4 = 0x80; byte4 <= 0xBF; ++byte4)
{ {
check_utf8string(false, byte1, byte2, byte3, byte4); check_utf8string(false, byte1, byte2, byte3);
} }
} }
} }
} }
}
SECTION("ill-formed: wrong third byte") SECTION("ill-formed: wrong second byte")
{
for (int byte1 = 0xF1; byte1 <= 0xF3; ++byte1)
{ {
for (int byte2 = 0x80; byte2 <= 0xBF; ++byte2) for (int byte1 = 0xF1; byte1 <= 0xF3; ++byte1)
{ {
for (int byte3 = 0x00; byte3 <= 0xFF; ++byte3) for (int byte2 = 0x00; byte2 <= 0xFF; ++byte2)
{ {
// skip correct third byte // skip correct second byte
if (0x80 <= byte3 and byte3 <= 0xBF) if (0x80 <= byte2 and byte2 <= 0xBF)
{ {
continue; continue;
} }
for (int byte4 = 0x80; byte4 <= 0xBF; ++byte4) for (int byte3 = 0x80; byte3 <= 0xBF; ++byte3)
{ {
check_utf8string(false, byte1, byte2, byte3, byte4); for (int byte4 = 0x80; byte4 <= 0xBF; ++byte4)
{
check_utf8string(false, byte1, byte2, byte3, byte4);
}
} }
} }
} }
} }
}
SECTION("ill-formed: wrong fourth byte") SECTION("ill-formed: wrong third byte")
{
for (int byte1 = 0xF1; byte1 <= 0xF3; ++byte1)
{ {
for (int byte2 = 0x80; byte2 <= 0xBF; ++byte2) for (int byte1 = 0xF1; byte1 <= 0xF3; ++byte1)
{ {
for (int byte3 = 0x80; byte3 <= 0xBF; ++byte3) for (int byte2 = 0x80; byte2 <= 0xBF; ++byte2)
{ {
for (int byte4 = 0x00; byte4 <= 0xFF; ++byte4) for (int byte3 = 0x00; byte3 <= 0xFF; ++byte3)
{ {
// skip correct fourth byte // skip correct third byte
if (0x80 <= byte3 and byte3 <= 0xBF) if (0x80 <= byte3 and byte3 <= 0xBF)
{ {
continue; continue;
} }
check_utf8string(false, byte1, byte2, byte3, byte4); for (int byte4 = 0x80; byte4 <= 0xBF; ++byte4)
{
check_utf8string(false, byte1, byte2, byte3, byte4);
}
} }
} }
} }
} }
}
}
SECTION("UTF8-4 (xF4 x80-8F UTF8-tail UTF8-tail)") SECTION("ill-formed: wrong fourth byte")
{
SECTION("well-formed")
{
for (int byte1 = 0xF4; byte1 <= 0xF4; ++byte1)
{ {
for (int byte2 = 0x80; byte2 <= 0x8F; ++byte2) for (int byte1 = 0xF1; byte1 <= 0xF3; ++byte1)
{ {
for (int byte3 = 0x80; byte3 <= 0xBF; ++byte3) for (int byte2 = 0x80; byte2 <= 0xBF; ++byte2)
{ {
for (int byte4 = 0x80; byte4 <= 0xBF; ++byte4) for (int byte3 = 0x80; byte3 <= 0xBF; ++byte3)
{ {
check_utf8string(true, byte1, byte2, byte3, byte4); for (int byte4 = 0x00; byte4 <= 0xFF; ++byte4)
{
// skip correct fourth byte
if (0x80 <= byte3 and byte3 <= 0xBF)
{
continue;
}
check_utf8string(false, byte1, byte2, byte3, byte4);
}
} }
} }
} }
} }
} }
SECTION("ill-formed: missing second byte") SECTION("UTF8-4 (xF4 x80-8F UTF8-tail UTF8-tail)")
{ {
for (int byte1 = 0xF4; byte1 <= 0xF4; ++byte1) SECTION("well-formed")
{ {
check_utf8string(false, byte1); 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);
}
}
}
}
} }
}
SECTION("ill-formed: missing third byte") SECTION("ill-formed: missing second byte")
{
for (int byte1 = 0xF4; byte1 <= 0xF4; ++byte1)
{ {
for (int byte2 = 0x80; byte2 <= 0x8F; ++byte2) for (int byte1 = 0xF4; byte1 <= 0xF4; ++byte1)
{ {
check_utf8string(false, byte1, byte2); check_utf8string(false, byte1);
} }
} }
}
SECTION("ill-formed: missing fourth byte") SECTION("ill-formed: missing third byte")
{
for (int byte1 = 0xF4; byte1 <= 0xF4; ++byte1)
{ {
for (int byte2 = 0x80; byte2 <= 0x8F; ++byte2) for (int byte1 = 0xF4; byte1 <= 0xF4; ++byte1)
{ {
for (int byte3 = 0x80; byte3 <= 0xBF; ++byte3) for (int byte2 = 0x80; byte2 <= 0x8F; ++byte2)
{ {
check_utf8string(false, byte1, byte2, byte3); check_utf8string(false, byte1, byte2);
} }
} }
} }
}
SECTION("ill-formed: wrong second byte") SECTION("ill-formed: missing fourth byte")
{
for (int byte1 = 0xF4; byte1 <= 0xF4; ++byte1)
{ {
for (int byte2 = 0x00; byte2 <= 0xFF; ++byte2) for (int byte1 = 0xF4; byte1 <= 0xF4; ++byte1)
{ {
// skip correct second byte for (int byte2 = 0x80; byte2 <= 0x8F; ++byte2)
if (0x80 <= byte2 and byte2 <= 0x8F)
{ {
continue; for (int byte3 = 0x80; byte3 <= 0xBF; ++byte3)
}
for (int byte3 = 0x80; byte3 <= 0xBF; ++byte3)
{
for (int byte4 = 0x80; byte4 <= 0xBF; ++byte4)
{ {
check_utf8string(false, byte1, byte2, byte3, byte4); check_utf8string(false, byte1, byte2, byte3);
} }
} }
} }
} }
}
SECTION("ill-formed: wrong third byte") SECTION("ill-formed: wrong second byte")
{
for (int byte1 = 0xF4; byte1 <= 0xF4; ++byte1)
{ {
for (int byte2 = 0x80; byte2 <= 0x8F; ++byte2) for (int byte1 = 0xF4; byte1 <= 0xF4; ++byte1)
{ {
for (int byte3 = 0x00; byte3 <= 0xFF; ++byte3) for (int byte2 = 0x00; byte2 <= 0xFF; ++byte2)
{ {
// skip correct third byte // skip correct second byte
if (0x80 <= byte3 and byte3 <= 0xBF) if (0x80 <= byte2 and byte2 <= 0x8F)
{ {
continue; continue;
} }
for (int byte4 = 0x80; byte4 <= 0xBF; ++byte4) for (int byte3 = 0x80; byte3 <= 0xBF; ++byte3)
{ {
check_utf8string(false, byte1, byte2, byte3, byte4); for (int byte4 = 0x80; byte4 <= 0xBF; ++byte4)
{
check_utf8string(false, byte1, byte2, byte3, byte4);
}
} }
} }
} }
} }
}
SECTION("ill-formed: wrong fourth byte") SECTION("ill-formed: wrong third byte")
{
for (int byte1 = 0xF4; byte1 <= 0xF4; ++byte1)
{ {
for (int byte2 = 0x80; byte2 <= 0x8F; ++byte2) for (int byte1 = 0xF4; byte1 <= 0xF4; ++byte1)
{ {
for (int byte3 = 0x80; byte3 <= 0xBF; ++byte3) for (int byte2 = 0x80; byte2 <= 0x8F; ++byte2)
{ {
for (int byte4 = 0x00; byte4 <= 0xFF; ++byte4) for (int byte3 = 0x00; byte3 <= 0xFF; ++byte3)
{ {
// skip correct fourth byte // skip correct third byte
if (0x80 <= byte3 and byte3 <= 0xBF) if (0x80 <= byte3 and byte3 <= 0xBF)
{ {
continue; continue;
} }
check_utf8string(false, byte1, byte2, byte3, byte4); for (int byte4 = 0x80; byte4 <= 0xBF; ++byte4)
{
check_utf8string(false, byte1, byte2, byte3, byte4);
}
}
}
}
}
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 and byte3 <= 0xBF)
{
continue;
}
check_utf8string(false, byte1, byte2, byte3, byte4);
}
} }
} }
} }
} }
} }
} }
}
TEST_CASE("Unicode", "[hide]") SECTION("\\uxxxx sequences")
{
/* NOTE: to_unicode is not used any more
SECTION("full enumeration of Unicode code points")
{ {
// lexer to call to_unicode on
json::lexer dummy_lexer("", 0);
// create an escaped string from a code point // create an escaped string from a code point
const auto codepoint_to_unicode = [](std::size_t cp) const auto codepoint_to_unicode = [](std::size_t cp)
{ {
// copd points are represented as a six-character sequence: a // code points are represented as a six-character sequence: a
// reverse solidus, followed by the lowercase letter u, followed // reverse solidus, followed by the lowercase letter u, followed
// by four hexadecimal digits that encode the character's code // by four hexadecimal digits that encode the character's code
// point // point
...@@ -872,72 +868,101 @@ TEST_CASE("Unicode", "[hide]") ...@@ -872,72 +868,101 @@ TEST_CASE("Unicode", "[hide]")
return ss.str(); return ss.str();
}; };
// generate all UTF-8 code points; in total, 1112064 code points are SECTION("correct sequences")
// generated: 0x1FFFFF code points - 2048 invalid values between
// 0xD800 and 0xDFFF.
for (std::size_t cp = 0; cp <= 0x10FFFFu; ++cp)
{ {
// The Unicode standard permanently reserves these code point // generate all UTF-8 code points; in total, 1112064 code points are
// values for UTF-16 encoding of the high and low surrogates, and // generated: 0x1FFFFF code points - 2048 invalid values between
// they will never be assigned a character, so there should be no // 0xD800 and 0xDFFF.
// reason to encode them. The official Unicode standard says that for (std::size_t cp = 0; cp <= 0x10FFFFu; ++cp)
// no UTF forms, including UTF-16, can encode these code points.
if (cp >= 0xD800u and cp <= 0xDFFFu)
{ {
// if we would not skip these code points, we would get a // string to store the code point as in \uxxxx format
// "missing low surrogate" exception std::string json_text = "\"";
continue;
}
// string to store the code point as in \uxxxx format
std::string escaped_string;
// string to store the code point as unescaped character sequence
std::string unescaped_string;
if (cp < 0x10000u) // decide whether to use one or two \uxxxx sequences
{ if (cp < 0x10000u)
// code points in the Basic Multilingual Plane can be {
// represented with one \\uxxxx sequence // The Unicode standard permanently reserves these code point
escaped_string = codepoint_to_unicode(cp); // 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 and cp <= 0xDFFFu)
{
// if we would not skip these code points, we would get a
// "missing low surrogate" exception
continue;
}
// All Unicode characters may be placed within the quotation // code points in the Basic Multilingual Plane can be
// marks, except for the characters that must be escaped: // represented with one \uxxxx sequence
// quotation mark, reverse solidus, and the control characters json_text += codepoint_to_unicode(cp);
// (U+0000 through U+001F); we ignore these code points as }
// they are checked with codepoint_to_unicode. else
if (cp > 0x1f and cp != 0x22 and cp != 0x5c)
{ {
unescaped_string = dummy_lexer.to_unicode(cp); // 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);
CHECK_NOTHROW(json::parse(json_text));
} }
else }
SECTION("incorrect sequences")
{
SECTION("high surrogate without low surrogate")
{ {
// To escape an extended character that is not in the Basic // D800..DBFF are high surrogates and must be followed by low
// Multilingual Plane, the character is represented as a // surrogates DC00..DFFF; here, nothing follows
// 12-character sequence, encoding the UTF-16 surrogate pair for (std::size_t cp = 0xD800u; cp <= 0xDBFFu; ++cp)
const auto codepoint1 = 0xd800u + (((cp - 0x10000u) >> 10) & 0x3ffu); {
const auto codepoint2 = 0xdc00u + ((cp - 0x10000u) & 0x3ffu); std::string json_text = "\"" + codepoint_to_unicode(cp) + "\"";
escaped_string = codepoint_to_unicode(codepoint1); CAPTURE(json_text);
escaped_string += codepoint_to_unicode(codepoint2); CHECK_THROWS_AS(json::parse(json_text), json::parse_error);
unescaped_string += dummy_lexer.to_unicode(codepoint1, codepoint2); }
} }
// all other code points are valid and must not yield parse errors #if 0
CAPTURE(cp); SECTION("high surrogate with wrong low surrogate")
CAPTURE(escaped_string); {
CAPTURE(unescaped_string); // D800..DBFF are high surrogates and must be followed by low
// surrogates DC00..DFFF; here a different sequence follows
for (std::size_t cp1 = 0xD800u; cp1 <= 0xDBFFu; ++cp1)
{
for (std::size_t cp2 = 0x0000u; cp2 <= 0xFFFFu; ++cp2)
{
if (0xDC00u <= cp2 and cp2 <= 0xDFFFu)
{
continue;
}
std::string json_text = "\"" + codepoint_to_unicode(cp1) + codepoint_to_unicode(cp2) + "\"";
CAPTURE(json_text);
CHECK_THROWS_AS(json::parse(json_text), json::parse_error);
}
}
}
#endif
json j1, j2, j3, j4; SECTION("low surrogate without high surrogate")
CHECK_NOTHROW(j1 = json::parse("\"" + escaped_string + "\"")); {
CHECK_NOTHROW(j2 = json::parse(j1.dump())); // low surrogates DC00..DFFF must follow high surrogates; here,
CHECK(j1 == j2); // they occur alone
for (std::size_t cp = 0xDC00u; cp <= 0xDFFFu; ++cp)
{
std::string json_text = "\"" + codepoint_to_unicode(cp) + "\"";
CAPTURE(json_text);
CHECK_THROWS_AS(json::parse(json_text), json::parse_error);
}
}
CHECK_NOTHROW(j3 = json::parse("\"" + unescaped_string + "\""));
CHECK_NOTHROW(j4 = json::parse(j3.dump()));
CHECK(j3 == j4);
} }
} }
*/
SECTION("read all unicode characters") SECTION("read all unicode characters")
{ {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册