Skip to content

Commit 348f1a1

Browse files
committed
Web.JSON: Convert control chars.
1 parent 04deee5 commit 348f1a1

File tree

2 files changed

+49
-8
lines changed

2 files changed

+49
-8
lines changed

autoload/vital/__vital__/Web/JSON.vim

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,43 @@ let s:special_constants = {
1515
\ 'v:null': 'null',
1616
\ 'v:none': 'null',
1717
\ }
18+
let s:control_chars = {
19+
\ '\': '\\',
20+
\ '"': '\"',
21+
\ "\x01": '\u0001',
22+
\ "\x02": '\u0002',
23+
\ "\x03": '\u0003',
24+
\ "\x04": '\u0004',
25+
\ "\x05": '\u0005',
26+
\ "\x06": '\u0006',
27+
\ "\x07": '\u0007',
28+
\ "\x08": '\b',
29+
\ "\x09": '\t',
30+
\ "\x0a": '\n',
31+
\ "\x0b": '\u000b',
32+
\ "\x0c": '\f',
33+
\ "\x0d": '\r',
34+
\ "\x0e": '\u000e',
35+
\ "\x0f": '\u000f',
36+
\ "\x10": '\u0010',
37+
\ "\x11": '\u0011',
38+
\ "\x12": '\u0012',
39+
\ "\x13": '\u0013',
40+
\ "\x14": '\u0014',
41+
\ "\x15": '\u0015',
42+
\ "\x16": '\u0016',
43+
\ "\x17": '\u0017',
44+
\ "\x18": '\u0018',
45+
\ "\x19": '\u0019',
46+
\ "\x1a": '\u001a',
47+
\ "\x1b": '\u001b',
48+
\ "\x1c": '\u001c',
49+
\ "\x1d": '\u001d',
50+
\ "\x1e": '\u001e',
51+
\ "\x1f": '\u001f',
52+
\ }
1853
lockvar s:float_constants s:float_nan s:float_inf
19-
lockvar s:special_constants
54+
lockvar s:special_constants s:control_chars
2055

2156
function! s:_true() abort
2257
return v:true
@@ -75,8 +110,7 @@ function! s:decode(json, ...) abort
75110
\ 'use_token': 0,
76111
\ 'allow_nan': 1,
77112
\}, get(a:000, 0, {}))
78-
let json = iconv(a:json, 'utf-8', &encoding)
79-
let json = join(split(json, "\n"), '')
113+
let json = join(split(a:json, "\n"), '')
80114
let json = substitute(json, '\\u34;', '\\"', 'g')
81115
let json = substitute(json, '\\u\(\x\x\x\x\)', '\=s:string.nr2enc_char("0x".submatch(1))', 'g')
82116
if settings.allow_nan
@@ -110,11 +144,8 @@ function! s:encode(val, ...) abort
110144
if t == 0
111145
return a:val
112146
elseif t == 1
113-
let json = '"' . escape(a:val, '\"') . '"'
114-
let json = substitute(json, "\r", '\\r', 'g')
115-
let json = substitute(json, "\n", '\\n', 'g')
116-
let json = substitute(json, "\t", '\\t', 'g')
117-
return iconv(json, &encoding, 'utf-8')
147+
let s = substitute(a:val, '[\x01-\x1f\\"]', '\=s:control_chars[submatch(0)]', 'g')
148+
return '"' . s . '"'
118149
elseif t == 2
119150
if s:const.true == a:val
120151
return 'true'

test/Web/JSON.vimspec

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@ Describe Web.JSON
2929
\ JSON.decode('"He said \"I''m a vimmer\""'),
3030
\ 'He said "I''m a vimmer"'
3131
\)
32+
" control chars
33+
Assert Equals(JSON.decode('"\u0001\u0002\u0003\u0004\u0005\u0006\u0007"'), "\x01\x02\x03\x04\x05\x06\x07")
34+
Assert Equals(JSON.decode('"\b\t\n\u000b\f\r\u000e\u000f"'), "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f")
35+
Assert Equals(JSON.decode('"\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017"'), "\x10\x11\x12\x13\x14\x15\x16\x17")
36+
Assert Equals(JSON.decode('"\u0018\u0019\u001a\u001b\u001c\u001d\u001e\u001f"'), "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f")
3237
" there should be iconv tests as well
3338
End
3439

@@ -105,6 +110,11 @@ Describe Web.JSON
105110
\ JSON.encode('He said "I''m a vimmer"'),
106111
\ '"He said \"I''m a vimmer\""'
107112
\)
113+
" control chars
114+
Assert Equals(JSON.encode("\x01\x02\x03\x04\x05\x06\x07"), '"\u0001\u0002\u0003\u0004\u0005\u0006\u0007"')
115+
Assert Equals(JSON.encode("\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"), '"\b\t\n\u000b\f\r\u000e\u000f"')
116+
Assert Equals(JSON.encode("\x10\x11\x12\x13\x14\x15\x16\x17"), '"\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017"')
117+
Assert Equals(JSON.encode("\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"), '"\u0018\u0019\u001a\u001b\u001c\u001d\u001e\u001f"')
108118
" there should be iconv tests as well
109119
End
110120

0 commit comments

Comments
 (0)