Version 0.0.1

master v0.0.1
DustyP 5 years ago
parent a7853c1177
commit 1be805317f

@ -5,6 +5,11 @@ import (
"unicode/utf8" "unicode/utf8"
) )
var (
lowerHex = []rune{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}
upperHex = []rune{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}
)
const ( const (
QAElideNullBytes = 0x01 QAElideNullBytes = 0x01
QAElideOuterQuotes = 0x02 QAElideOuterQuotes = 0x02
@ -59,7 +64,7 @@ func GetTextQuote(s QuotingStyle) rune {
} }
} }
func QuoteargBufferRestyled( func Quote(
buffer []rune, buffer []rune,
arg []rune, arg []rune,
style QuotingStyle, style QuotingStyle,
@ -67,24 +72,18 @@ func QuoteargBufferRestyled(
quoteTheseToo uint, quoteTheseToo uint,
leftQuote rune, leftQuote rune,
rightQuote rune, rightQuote rune,
) { ) []rune {
var pos int
var elideOuterQuotes bool = (flags & QAElideOuterQuotes) != 0 var elideOuterQuotes bool = (flags & QAElideOuterQuotes) != 0
var pendingShellEscapeEnd bool var pendingShellEscapeEnd bool
var escaping bool var escaping bool
var quoteRune rune var quoteRune rune
var backslashEscapes bool var backslashEscapes bool
var allCAndShellQuoteCompat bool = true
store := func(c rune) { store := func(c rune) {
buffer[pos] = c buffer = append(buffer, c)
pos++
} }
startESC := func() { startESC := func() {
if elideOuterQuotes {
goto ForceOuterQuotingStyle
}
escaping = true escaping = true
if style == ShellAlwaysQuotingStyle && !pendingShellEscapeEnd { if style == ShellAlwaysQuotingStyle && !pendingShellEscapeEnd {
store('\'') store('\'')
@ -159,9 +158,9 @@ func QuoteargBufferRestyled(
for i := 0; i < len(arg); i++ { for i := 0; i < len(arg); i++ {
var esc rune var esc rune
var isRightQuote bool var isRightQuote bool
var cAndShellQuoteCompat bool escaping = false
quoteIsNext := arg[i+1] == quoteRune quoteIsNext := len(arg) > i+1 && arg[i+1] == quoteRune
if backslashEscapes && if backslashEscapes &&
style != ShellAlwaysQuotingStyle && style != ShellAlwaysQuotingStyle &&
@ -177,6 +176,9 @@ func QuoteargBufferRestyled(
switch c { switch c {
case 0x00: case 0x00:
if backslashEscapes { if backslashEscapes {
if elideOuterQuotes {
goto ForceOuterQuotingStyle
}
startESC() startESC()
if style != ShellQuotingStyle && if style != ShellQuotingStyle &&
i+1 < len(arg) && i+1 < len(arg) &&
@ -189,7 +191,7 @@ func QuoteargBufferRestyled(
} else if flags&QAElideNullBytes != 0 { } else if flags&QAElideNullBytes != 0 {
continue continue
} }
break goto StoreEscape
case '?': case '?':
switch style { switch style {
case ShellAlwaysQuotingStyle: case ShellAlwaysQuotingStyle:
@ -222,7 +224,7 @@ func QuoteargBufferRestyled(
default: default:
break break
} }
break goto StoreEscape
case '\a': case '\a':
esc = 'a' esc = 'a'
goto CEscape goto CEscape
@ -257,30 +259,19 @@ func QuoteargBufferRestyled(
goto StoreC goto StoreC
} }
CAndShellEscape: goto CAndShellEscape
if style == ShellAlwaysQuotingStyle && elideOuterQuotes {
goto ForceOuterQuotingStyle
}
CEscape:
if backslashEscapes {
c = esc
goto StoreEscape
}
break
case '{', '}': case '{', '}':
if len(arg) != 1 { if len(arg) != 1 {
break goto StoreEscape
} }
fallthrough fallthrough
case '#', '~': case '#', '~':
if i != 0 { if i != 0 {
break goto StoreEscape
} }
fallthrough fallthrough
case ' ': case ' ':
cAndShellQuoteCompat = true
fallthrough fallthrough
case '!', '"', '$', '&', '(', ')', '*', ';', '<', '=', '>', '[': case '!', '"', '$', '&', '(', ')', '*', ';', '<', '=', '>', '[':
fallthrough fallthrough
@ -288,10 +279,8 @@ func QuoteargBufferRestyled(
if style == ShellAlwaysQuotingStyle && elideOuterQuotes { if style == ShellAlwaysQuotingStyle && elideOuterQuotes {
goto ForceOuterQuotingStyle goto ForceOuterQuotingStyle
} }
break goto StoreEscape
case '\'': case '\'':
encounteredSingleQuote = true
cAndShellQuoteCompat = true
if style == ShellAlwaysQuotingStyle { if style == ShellAlwaysQuotingStyle {
if elideOuterQuotes { if elideOuterQuotes {
goto ForceOuterQuotingStyle goto ForceOuterQuotingStyle
@ -303,7 +292,7 @@ func QuoteargBufferRestyled(
store('\'') store('\'')
pendingShellEscapeEnd = false pendingShellEscapeEnd = false
} }
break goto StoreC
case '%', '+', ',', '-', '.', '/', '0', '1', '2', '3', '4', '5': case '%', '+', ',', '-', '.', '/', '0', '1', '2', '3', '4', '5':
fallthrough fallthrough
case '6', '7', '8', '9', ':', 'A', 'B', 'C', 'D', 'E', 'F': case '6', '7', '8', '9', ':', 'A', 'B', 'C', 'D', 'E', 'F':
@ -315,64 +304,82 @@ func QuoteargBufferRestyled(
case 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n': case 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n':
fallthrough fallthrough
case 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z': case 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z':
cAndShellQuoteCompat = true goto StoreC
break
default: default:
printable := strconv.IsPrint(c) if backslashEscapes && !strconv.IsPrint(c) {
cAndShellQuoteCompat = printable if elideOuterQuotes {
if backslashEscapes && !printable { goto ForceOuterQuotingStyle
startESC() }
store('x')
switch { switch {
case c < ' ': case c < ' ':
store(byte(c) >> 4) startESC()
store(byte(c) & 0xF) store('x')
store(upperHex[byte(c)>>4])
store(upperHex[byte(c)&0xF])
case c > utf8.MaxRune: case c > utf8.MaxRune:
c = 0xFFFD c = 0xFFFD
fallthrough fallthrough
case c < 0x10000: case c < 0x10000:
startESC()
store('u')
for s := 12; s >= 0; s -= 4 { for s := 12; s >= 0; s -= 4 {
store(c >> uint(s) & 0xF) store(upperHex[c>>uint(s)&0xF])
} }
default: default:
startESC()
store('U')
for s := 28; s >= 0; s -= 4 { for s := 28; s >= 0; s -= 4 {
store(c >> uint(s) & 0xF) store(upperHex[c>>uint(s)&0xF])
} }
} }
goto StoreC
} else if isRightQuote { } else if isRightQuote {
store('\\') store('\\')
isRightQuote = false isRightQuote = false
} }
}
continue
CAndShellEscape:
if style == ShellAlwaysQuotingStyle && elideOuterQuotes {
goto ForceOuterQuotingStyle
}
CEscape:
if backslashEscapes {
c = esc
goto StoreEscape
}
if !(((backslashEscapes && style != ShellAlwaysQuotingStyle) ||
elideOuterQuotes) && !isRightQuote) {
goto StoreC goto StoreC
} }
}
if !(((backslashEscapes && style != ShellAlwaysQuotingStyle) || StoreEscape:
elideOuterQuotes) && !isRightQuote) { if elideOuterQuotes {
goto StoreC goto ForceOuterQuotingStyle
} }
startESC()
StoreEscape: StoreC:
startESC() endESC()
store(c)
StoreC: }
endESC()
store(c)
if !cAndShellQuoteCompat { if quoteRune != 0 && !elideOuterQuotes {
allCAndShellQuoteCompat = false store(quoteRune)
} }
if len == 0 && style == ShellAlwaysQuotingStyle && elideOuterQuotes { if style == ShellAlwaysQuotingStyle && elideOuterQuotes {
goto ForceOuterQuotingStyle goto ForceOuterQuotingStyle
} }
return buffer
ForceOuterQuotingStyle: ForceOuterQuotingStyle:
if style == ShellAlwaysQuotingStyle && backslashEscapes { if style == ShellAlwaysQuotingStyle && backslashEscapes {
style = ShellEscapeAlwaysQuotingStyle style = ShellEscapeAlwaysQuotingStyle
} }
QuoteargBufferRestyled( return Quote(
buffer, buffer,
arg, arg,
style, style,

Loading…
Cancel
Save