2023-02-02 01:22:52 +00:00
package yqlib
import (
"fmt"
"io"
"regexp"
"strings"
)
2023-02-09 07:15:07 +00:00
var unsafeChars = regexp . MustCompile ( ` [^\w@%+=:,./-] ` )
2023-02-02 01:22:52 +00:00
type shEncoder struct {
2023-02-09 07:15:07 +00:00
quoteAll bool
2023-02-02 01:22:52 +00:00
}
func NewShEncoder ( ) Encoder {
2023-02-09 07:15:07 +00:00
return & shEncoder { false }
2023-02-02 01:22:52 +00:00
}
func ( e * shEncoder ) CanHandleAliases ( ) bool {
return false
}
func ( e * shEncoder ) PrintDocumentSeparator ( writer io . Writer ) error {
return nil
}
func ( e * shEncoder ) PrintLeadingContent ( writer io . Writer , content string ) error {
return nil
}
2023-04-08 09:56:35 +00:00
func ( e * shEncoder ) Encode ( writer io . Writer , originalNode * CandidateNode ) error {
node := originalNode . unwrapDocument ( )
if node . guessTagFromCustomType ( ) != "!!str" {
2023-02-02 01:22:52 +00:00
return fmt . Errorf ( "cannot encode %v as URI, can only operate on strings. Please first pipe through another encoding operator to convert the value to a string" , node . Tag )
}
2023-02-09 07:15:07 +00:00
return writeString ( writer , e . encode ( originalNode . Value ) )
}
// put any (shell-unsafe) characters into a single-quoted block, close the block lazily
func ( e * shEncoder ) encode ( input string ) string {
const quote = '\''
var inQuoteBlock = false
var encoded strings . Builder
encoded . Grow ( len ( input ) )
for _ , ir := range input {
// open or close a single-quote block
if ir == quote {
if inQuoteBlock {
// get out of a quote block for an input quote
encoded . WriteRune ( quote )
inQuoteBlock = ! inQuoteBlock
}
// escape the quote with a backslash
encoded . WriteRune ( '\\' )
} else {
if e . shouldQuote ( ir ) && ! inQuoteBlock {
// start a quote block for any (unsafe) characters
encoded . WriteRune ( quote )
inQuoteBlock = ! inQuoteBlock
}
}
// pass on the input character
encoded . WriteRune ( ir )
2023-02-02 01:22:52 +00:00
}
2023-02-09 07:15:07 +00:00
// close any pending quote block
if inQuoteBlock {
encoded . WriteRune ( quote )
}
return encoded . String ( )
}
func ( e * shEncoder ) shouldQuote ( ir rune ) bool {
return e . quoteAll || unsafeChars . MatchString ( string ( ir ) )
2023-02-02 01:22:52 +00:00
}