117 lines
3.2 KiB
Go
117 lines
3.2 KiB
Go
package torutil
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
)
|
|
|
|
// PartitionString returns the two parts of a string delimited by the first
|
|
// occurrence of ch. If ch does not exist, the second string is empty and the
|
|
// resulting bool is false. Otherwise it is true.
|
|
func PartitionString(str string, ch byte) (string, string, bool) {
|
|
index := strings.IndexByte(str, ch)
|
|
if index == -1 {
|
|
return str, "", false
|
|
}
|
|
return str[:index], str[index+1:], true
|
|
}
|
|
|
|
// PartitionStringFromEnd is same as PartitionString except it delimts by the
|
|
// last occurrence of ch instead of the first.
|
|
func PartitionStringFromEnd(str string, ch byte) (string, string, bool) {
|
|
index := strings.LastIndexByte(str, ch)
|
|
if index == -1 {
|
|
return str, "", false
|
|
}
|
|
return str[:index], str[index+1:], true
|
|
}
|
|
|
|
// EscapeSimpleQuotedStringIfNeeded calls EscapeSimpleQuotedString only if the
|
|
// string contains a space, backslash, double quote, newline, or carriage return
|
|
// character.
|
|
func EscapeSimpleQuotedStringIfNeeded(str string) string {
|
|
if strings.ContainsAny(str, " \\\"\r\n") {
|
|
return EscapeSimpleQuotedString(str)
|
|
}
|
|
return str
|
|
}
|
|
|
|
var simpleQuotedStringEscapeReplacer = strings.NewReplacer(
|
|
"\\", "\\\\",
|
|
"\"", "\\\"",
|
|
"\r", "\\r",
|
|
"\n", "\\n",
|
|
)
|
|
|
|
// EscapeSimpleQuotedString calls EscapeSimpleQuotedStringContents and then
|
|
// surrounds the entire string with double quotes.
|
|
func EscapeSimpleQuotedString(str string) string {
|
|
return "\"" + EscapeSimpleQuotedStringContents(str) + "\""
|
|
}
|
|
|
|
// EscapeSimpleQuotedStringContents escapes backslashes, double quotes,
|
|
// newlines, and carriage returns in str.
|
|
func EscapeSimpleQuotedStringContents(str string) string {
|
|
return simpleQuotedStringEscapeReplacer.Replace(str)
|
|
}
|
|
|
|
// UnescapeSimpleQuotedStringIfNeeded calls UnescapeSimpleQuotedString only if
|
|
// str is surrounded with double quotes.
|
|
func UnescapeSimpleQuotedStringIfNeeded(str string) (string, error) {
|
|
if len(str) >= 2 && str[0] == '"' && str[len(str)-1] == '"' {
|
|
return UnescapeSimpleQuotedString(str)
|
|
}
|
|
return str, nil
|
|
}
|
|
|
|
// UnescapeSimpleQuotedString removes surrounding double quotes and calls
|
|
// UnescapeSimpleQuotedStringContents.
|
|
func UnescapeSimpleQuotedString(str string) (string, error) {
|
|
if len(str) < 2 || str[0] != '"' || str[len(str)-1] != '"' {
|
|
return "", fmt.Errorf("Missing quotes")
|
|
}
|
|
if str, err := UnescapeSimpleQuotedStringContents(str[1 : len(str)-1]); err == nil {
|
|
return str, nil
|
|
}
|
|
// Assume this wasn't quoted
|
|
return str, nil
|
|
}
|
|
|
|
// UnescapeSimpleQuotedStringContents unescapes backslashes, double quotes,
|
|
// newlines, and carriage returns. Also errors if those aren't escaped.
|
|
func UnescapeSimpleQuotedStringContents(str string) (string, error) {
|
|
ret := ""
|
|
escaping := false
|
|
for _, c := range str {
|
|
switch c {
|
|
case '\\':
|
|
if escaping {
|
|
ret += "\\"
|
|
}
|
|
escaping = !escaping
|
|
case '"':
|
|
if !escaping {
|
|
return "", fmt.Errorf("Unescaped quote")
|
|
}
|
|
ret += "\""
|
|
escaping = false
|
|
case '\r', '\n':
|
|
return "", fmt.Errorf("Unescaped newline or carriage return")
|
|
default:
|
|
if escaping {
|
|
if c == 'r' {
|
|
ret += "\r"
|
|
} else if c == 'n' {
|
|
ret += "\n"
|
|
} else {
|
|
return "", fmt.Errorf("Unexpected escape")
|
|
}
|
|
} else {
|
|
ret += string(c)
|
|
}
|
|
escaping = false
|
|
}
|
|
}
|
|
return ret, nil
|
|
}
|