v.util: simplify smart_quote more

pull/10538/head
Delyan Angelov 2021-06-21 15:02:53 +03:00
parent 5d0e9417db
commit 71523c86a1
No known key found for this signature in database
GPG Key ID: 66886C0F12D595ED
1 changed files with 61 additions and 47 deletions

View File

@ -14,13 +14,34 @@ const double_quote = 34
const double_escape = '\\\\' const double_escape = '\\\\'
//[direct_array_access] [direct_array_access]
pub fn smart_quote(str string, raw bool) string { pub fn smart_quote(str string, raw bool) string {
len := str.len len := str.len
if len == 0 { if len == 0 {
return '' return ''
} }
mut result := strings.new_builder(len) if len < 256 {
mut is_pure := true
for i := 0; i < len; i++ {
ch := byte(str[i])
if (ch >= 37 && ch <= 90) || (ch >= 95 && ch <= 126)
|| (ch in [` `, `!`, `#`, `[`, `]`]) {
// safe punctuation + digits + big latin letters,
// small latin letters + more safe punctuation,
// important punctuation exceptions, that are not
// placed conveniently in a consequitive span in
// the ASCII table.
continue
}
is_pure = false
break
}
if is_pure {
return str
}
}
// ensure there is enough space for the potential expansion of several \\ or \n
mut result := strings.new_builder(len + 10)
mut pos := -1 mut pos := -1
mut last := byte(0) mut last := byte(0)
mut current := byte(0) mut current := byte(0)
@ -35,85 +56,78 @@ pub fn smart_quote(str string, raw bool) string {
if pos >= len { if pos >= len {
break break
} }
last = current
current = str[pos]
if pos + 1 < len { if pos + 1 < len {
next = str[pos + 1] next = str[pos + 1]
} else {
next = 0
} }
current = str[pos]
// double quote
if current == util.double_quote { if current == util.double_quote {
current = 0 current = 0
last = current
result.write_b(util.backslash) result.write_b(util.backslash)
result.write_b(util.double_quote) result.write_b(util.double_quote)
continue continue
} }
if current == util.backslash { if current == util.backslash {
if raw { if raw {
last = current
result.write_string(util.double_escape) result.write_string(util.double_escape)
continue continue
} else { }
// escaped backslash - keep as is
if next == util.backslash { if next == util.backslash {
// escaped backslash - keep as is
skip_next = true skip_next = true
last = current
result.write_string(util.double_escape) result.write_string(util.double_escape)
continue continue
} else if next != 0 { }
if next != 0 {
if raw { if raw {
skip_next = true skip_next = true
last = current
result.write_string(util.double_escape) result.write_string(util.double_escape)
continue continue
} else if next in util.invalid_escapes { }
if next in util.invalid_escapes {
skip_next = true skip_next = true
last = current
result.write_b(next) result.write_b(next)
continue continue
} else { }
// keep all valid escape sequences // keep all valid escape sequences
skip_next = true skip_next = true
last = current
result.write_b(current) result.write_b(current)
result.write_b(next) result.write_b(next)
continue continue
} }
} }
}
}
// keep newlines in string
if current == util.backslash_n { if current == util.backslash_n {
// keep newlines in string
current = 0 current = 0
last = current
result.write_b(util.backslash) result.write_b(util.backslash)
result.write_b(`n`) result.write_b(`n`)
continue continue
} else if current == util.backslash_r && next == util.backslash_n { }
if current == util.backslash_r && next == util.backslash_n {
result.write_b(current) result.write_b(current)
result.write_b(next) result.write_b(next)
current = 0 current = 0
skip_next = true skip_next = true
last = current
continue continue
} }
// Dolar sign if !raw {
if !raw && current == `$` { if current == `$` {
if last == util.backslash { if last == util.backslash {
result.write_b(last) result.write_b(last)
result.write_b(current) result.write_b(current)
last = current
continue continue
} }
} }
if current == util.backslash_r && next == util.backslash_n {
// Windows style new line \r\n // Windows style new line \r\n
if !raw && current == util.backslash_r && next == util.backslash_n {
skip_next = true skip_next = true
result.write_b(util.backslash) result.write_b(util.backslash)
result.write_b(`n`) result.write_b(`n`)
last = current
continue continue
} }
last = current }
result.write_b(current) result.write_b(current)
} }
return result.str() return result.str()