Files
v/vlib/json2/json5_encode.v

73 lines
1.7 KiB
V

module json2
fn (mut encoder Encoder) encode_key(key string) {
if encoder.json5 && encoder.unquoted_keys && json5_is_identifier(key) {
for byte in key {
encoder.output << byte
}
} else {
encoder.encode_string(key)
}
}
fn json5_is_identifier(key string) bool {
if key.len == 0 {
return false
}
for i, ch in key.runes_iterator() {
if i == 0 {
if !json5_is_ident_start(int(ch)) {
return false
}
} else if !json5_is_ident_part(int(ch)) {
return false
}
}
return true
}
@[manualfree]
fn (mut encoder Encoder) encode_json5_string(value string) {
quote := if encoder.single_quotes { u8(`'`) } else { u8(`"`) }
encoder.output << quote
runes := value.runes()
defer { unsafe { runes.free() } }
mut utf8_buffer := [5]u8{}
for ch in runes {
if int(ch) == int(quote) || int(ch) == r_backslash {
encoder.output << `\\`
encoder.output << u8(ch)
continue
}
match ch {
`\n`, `\r`, `\t`, `\b`, `\f` {
encoder.output << `\\`
encoder.output << match ch {
`\n` { u8(`n`) }
`\r` { u8(`r`) }
`\t` { u8(`t`) }
`\b` { u8(`b`) }
else { u8(`f`) }
}
}
else {
if ch < 0x20 || ch == 0x2028 || ch == 0x2029
|| (encoder.escape_unicode && ch >= 0x80) {
if ch > 0xffff {
point := u32(ch) - 0x10000
encoder.encode_unicode_escape(0xD800 + (point >> 10), false)
encoder.encode_unicode_escape(0xDC00 + (point & 0x3ff), false)
} else {
encoder.encode_unicode_escape(u32(ch), false)
}
} else {
// This view borrows the local UTF-8 buffer and is copied immediately.
encoded := unsafe { utf32_to_str_no_malloc(u32(ch), mut &utf8_buffer[0]) }
unsafe { encoder.output.push_many(encoded.str, encoded.len) }
}
}
}
}
encoder.output << quote
}