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 = '\\\\'
//[direct_array_access]
[direct_array_access]
pub fn smart_quote(str string, raw bool) string {
len := str.len
if len == 0 {
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 last := byte(0)
mut current := byte(0)
@ -35,85 +56,78 @@ pub fn smart_quote(str string, raw bool) string {
if pos >= len {
break
}
last = current
current = str[pos]
if pos + 1 < len {
next = str[pos + 1]
} else {
next = 0
}
current = str[pos]
// double quote
if current == util.double_quote {
current = 0
last = current
result.write_b(util.backslash)
result.write_b(util.double_quote)
continue
}
if current == util.backslash {
if raw {
last = current
result.write_string(util.double_escape)
continue
} else {
}
if next == util.backslash {
// escaped backslash - keep as is
if next == util.backslash {
skip_next = true
result.write_string(util.double_escape)
continue
}
if next != 0 {
if raw {
skip_next = true
last = current
result.write_string(util.double_escape)
continue
} else if next != 0 {
if raw {
skip_next = true
last = current
result.write_string(util.double_escape)
continue
} else if next in util.invalid_escapes {
skip_next = true
last = current
result.write_b(next)
continue
} else {
// keep all valid escape sequences
skip_next = true
last = current
result.write_b(current)
result.write_b(next)
continue
}
}
if next in util.invalid_escapes {
skip_next = true
result.write_b(next)
continue
}
// keep all valid escape sequences
skip_next = true
result.write_b(current)
result.write_b(next)
continue
}
}
// keep newlines in string
if current == util.backslash_n {
// keep newlines in string
current = 0
last = current
result.write_b(util.backslash)
result.write_b(`n`)
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(next)
current = 0
skip_next = true
last = current
continue
}
// Dolar sign
if !raw && current == `$` {
if last == util.backslash {
result.write_b(last)
result.write_b(current)
last = current
if !raw {
if current == `$` {
if last == util.backslash {
result.write_b(last)
result.write_b(current)
continue
}
}
if current == util.backslash_r && next == util.backslash_n {
// Windows style new line \r\n
skip_next = true
result.write_b(util.backslash)
result.write_b(`n`)
continue
}
}
// Windows style new line \r\n
if !raw && current == util.backslash_r && next == util.backslash_n {
skip_next = true
result.write_b(util.backslash)
result.write_b(`n`)
last = current
continue
}
last = current
result.write_b(current)
}
return result.str()