json2: unescape characters (#6836)

pull/6841/head
Anton Zavodchikov 2020-11-15 17:58:17 +05:00 committed by GitHub
parent c8b7cfc297
commit fe3d2a9aba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 71 additions and 12 deletions

View File

@ -223,8 +223,6 @@ fn (mut p Parser) decode_value() ?Any {
fn (mut p Parser) decode_string() ?Any {
mut strwr := strings.new_builder(200)
for i := 0; i < p.tok.lit.len; i++ {
// s := p.tok.lit[i].str()
// println('$i $s')
if ((i-1 >= 0 && p.tok.lit[i-1] != `/`) || i == 0) && int(p.tok.lit[i]) in [9, 10, 0] {
return error('character must be escaped with a backslash.')
}
@ -235,8 +233,33 @@ fn (mut p Parser) decode_string() ?Any {
if i+1 < p.tok.lit.len && p.tok.lit[i] == 92 {
peek := p.tok.lit[i+1]
if peek in [`b`, `f`, `n`, `r`, `t`, `u`, `\\`, `"`, `/`] {
if peek == `u` {
match peek{
`b` {
i++
strwr.write_b(`\b`)
continue
}
`f` {
i++
strwr.write_b(`\f`)
continue
}
`n` {
i++
strwr.write_b(`\n`)
continue
}
`r` {
i++
strwr.write_b(`\r`)
continue
}
`t` {
i++
strwr.write_b(`\t`)
continue
}
`u` {
if i+5 < p.tok.lit.len {
codepoint := p.tok.lit[i+2..i+6]
check_valid_hex(codepoint)?
@ -248,13 +271,23 @@ fn (mut p Parser) decode_string() ?Any {
return error('incomplete unicode escape.')
}
}
i++
strwr.write_b(p.tok.lit[i])
continue
} else {
return error('invalid backslash escape.')
}
`\\` {
i++
strwr.write_b(`\\`)
continue
}
`"` {
i++
strwr.write_b(`\"`)
continue
}
`/` {
i++
strwr.write_b(`/`)
continue
}
else { return error('invalid backslash escape.') }
}
if int(peek) == 85 {
return error('unicode endpoints must be in lowercase `u`.')

View File

@ -7,7 +7,11 @@ import strings
fn write_value(v Any, i int, len int, mut wr strings.Builder) {
str := v.str()
wr.write(if v is string { '"$str"' } else { str })
if v is string {
wr.write('"$str"')
} else {
wr.write(str)
}
if i >= len-1 { return }
wr.write_b(`,`)
}

View File

@ -69,6 +69,28 @@ fn test_fast_raw_decode() {
assert str == '{"name":"Peter","age":"28","salary":"95000.5","title":"2"}'
}
fn test_character_unescape() {
// Need to test `\r`, `\b`, `\f` ??
message := '{
"newline":"new\\nline",
"tab":"\\ttab",
"backslash": "back\\\\slash",
"quotes": "\\"quotes\\"",
"slash":"\/dev\/null"
}'
mut obj := json2.raw_decode(message) or {
assert false
json2.Any{}
}
lines := obj.as_map()
eprintln("$lines")
assert lines['newline'].str() == 'new\nline'
assert lines['tab'].str() == '\ttab'
assert lines['backslash'].str() == 'back\\slash'
assert lines['quotes'].str() == '\"quotes\"'
assert lines['slash'].str() == '/dev/null'
}
/*
struct User2 {
age int