mirror of
https://github.com/nlohmann/json.git
synced 2026-07-08 03:25:10 +00:00
Replace snprintf with a branch-free writer for \uXXXX escapes
dump_escaped called std::snprintf(..., "\u%04x", ...) once per escaped code point in the string serialization hot path. snprintf re-parses the format string and pulls in locale/printf machinery on every call, which is far heavier than the fixed 6-/12-byte output warrants. This is hot for any string containing control characters, and for all non-ASCII text when ensure_ascii is set. Replace it with write_u_escape, a small helper that writes the escape directly into string_buffer via a nibble-to-hex lookup table, mirroring the existing hand-rolled dump_integer fast path in the same file. Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
@@ -168,6 +168,32 @@ TEST_CASE("convenience functions")
|
||||
CHECK_THROWS_WITH_AS(check_escaped("\xC2"), "[json.exception.type_error.316] incomplete UTF-8 string; last byte: 0xC2", json::type_error&);
|
||||
}
|
||||
|
||||
SECTION("string escape with ensure_ascii")
|
||||
{
|
||||
// control characters are escaped regardless of ensure_ascii
|
||||
check_escaped("\x01", "\\u0001", true);
|
||||
check_escaped("\x1f", "\\u001f", true);
|
||||
|
||||
// non-ASCII code points in the Basic Multilingual Plane are emitted as
|
||||
// a single lowercase \uXXXX escape (exercises every nibble position)
|
||||
check_escaped("\xC2\x80", "\\u0080", true); // U+0080
|
||||
check_escaped("\xC3\xBF", "\\u00ff", true); // U+00FF (ÿ)
|
||||
check_escaped("\xDF\xBF", "\\u07ff", true); // U+07FF
|
||||
check_escaped("\xE4\xBD\xA0", "\\u4f60", true); // U+4F60 (你)
|
||||
check_escaped("\xEA\xAF\x8D", "\\uabcd", true); // U+ABCD
|
||||
check_escaped("\xEF\xBF\xBD", "\\ufffd", true); // U+FFFD (replacement char, all-f nibbles)
|
||||
|
||||
// code points outside the BMP are emitted as a UTF-16 surrogate pair
|
||||
// of two lowercase \uXXXX escapes
|
||||
check_escaped("\xF0\x90\x80\x80", "\\ud800\\udc00", true); // U+10000 (lowest astral)
|
||||
check_escaped("\xF0\x9F\x98\x80", "\\ud83d\\ude00", true); // U+1F600 (😀)
|
||||
check_escaped("\xF4\x8F\xBF\xBF", "\\udbff\\udfff", true); // U+10FFFF (highest code point)
|
||||
|
||||
// with ensure_ascii disabled, non-ASCII input is passed through verbatim
|
||||
check_escaped("\xE4\xBD\xA0", "\xE4\xBD\xA0", false);
|
||||
check_escaped("\xF0\x9F\x98\x80", "\xF0\x9F\x98\x80", false);
|
||||
}
|
||||
|
||||
SECTION("string concat")
|
||||
{
|
||||
using nlohmann::detail::concat;
|
||||
|
||||
Reference in New Issue
Block a user