patch 9.2.1141: JSON encoding can be improved
Commit:
https://github.com/vim/vim/commit/8a26d0b99e84d362539aa80b00d754cba99a2462
Author: Yasuhiro Matsumoto <
matt...@gmail.com>
Date: Mon Sep 28 19:41:55 2026 +0000
patch 9.2.1141: JSON encoding can be improved
Problem: Encoding a control character in JSON uses vim_snprintf() which
is slow
Solution: Write the "\u00XX" escape directly (Yasuhiro Matsumoto).
Cover all control escapes mixed with multibyte text across buffer growth.
All eight JSON tests pass. Local five-run medians improve by 93% for
control-only text and 43% for mixed text; plain ASCII is unchanged.
closes: #21381
Signed-off-by: Yasuhiro Matsumoto <
matt...@gmail.com>
Signed-off-by: Christian Brabandt <
c...@256bit.org>
diff --git a/src/json.c b/src/json.c
index fb7755d0f..001a29db0 100644
--- a/src/json.c
+++ b/src/json.c
@@ -204,11 +204,12 @@ write_string(garray_T *gap, char_u *str)
GA_CONCAT_LITERAL(gap, "\\"); break;
default:
{
- size_t numbuflen;
+ char_u escaped[] = "\u0000";
- numbuflen = vim_snprintf_safelen((char *)numbuf,
- sizeof(numbuf), "\u%04lx", (long)c);
- ga_concat_len(gap, numbuf, numbuflen);
+ // Only control characters below 0x20 reach this case.
+ escaped[4] = '0' + (c >> 4);
+ escaped[5] = "0123456789abcdef"[c & 0xf];
+ ga_concat_len(gap, escaped, STRLEN_LITERAL("\u0000"));
}
}
diff --git a/src/testdir/test_json.vim b/src/testdir/test_json.vim
index c65d85c8f..98f25289b 100644
--- a/src/testdir/test_json.vim
+++ b/src/testdir/test_json.vim
@@ -117,6 +117,17 @@ func Test_json_encode()
call assert_equal("", res)
endfunc
+func Test_json_encode_control_text()
+ let text = '日本語' .. s:var2 .. s:var3 .. s:var4 .. s:var5 .. 'text'
+ let escaped = '日本語' .. s:json2[1:-2] .. s:json3[1:-2]
+ \ .. s:json4[1:-2] .. s:json5[1:-2] .. 'text'
+ let text = repeat(text, 200)
+ let expected = '"' .. repeat(escaped, 200) .. '"'
+ call assert_equal(expected, json_encode(text))
+ call assert_equal(expected, js_encode(text))
+ call assert_equal(text, json_decode(expected))
+endfunc
+
func Test_json_decode()
call assert_equal(s:var1, json_decode(s:json1))
call assert_equal(s:var2, json_decode(s:json2))
diff --git a/src/version.c b/src/version.c
index bbfa29c5f..8c16ad046 100644
--- a/src/version.c
+++ b/src/version.c
@@ -763,6 +763,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
+/**/
+ 1141,
/**/
1140,
/**/