bine/torutil/string.go

117 lines
3.2 KiB
Go
Raw Normal View History

package torutil
2018-05-10 18:11:18 +00:00
import (
"fmt"
"strings"
)
2018-05-14 20:36:29 +00:00
// 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.
2018-05-10 21:29:16 +00:00
func PartitionString(str string, ch byte) (string, string, bool) {
2018-05-10 18:11:18 +00:00
index := strings.IndexByte(str, ch)
if index == -1 {
return str, "", false
}
return str[:index], str[index+1:], true
}
2018-05-14 20:36:29 +00:00
// PartitionStringFromEnd is same as PartitionString except it delimts by the
// last occurrence of ch instead of the first.
2018-05-11 19:43:58 +00:00
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
}
2018-05-14 20:36:29 +00:00
// EscapeSimpleQuotedStringIfNeeded calls EscapeSimpleQuotedString only if the
// string contains a space, backslash, double quote, newline, or carriage return
// character.
2018-05-11 04:08:20 +00:00
func EscapeSimpleQuotedStringIfNeeded(str string) string {
if strings.ContainsAny(str, " \\\"\r\n") {
return EscapeSimpleQuotedString(str)
}
return str
}
2018-05-14 19:47:05 +00:00
var simpleQuotedStringEscapeReplacer = strings.NewReplacer(
2018-05-11 04:08:20 +00:00
"\\", "\\\\",
"\"", "\\\"",
"\r", "\\r",
"\n", "\\n",
)
2018-05-14 20:36:29 +00:00
// EscapeSimpleQuotedString calls EscapeSimpleQuotedStringContents and then
// surrounds the entire string with double quotes.
2018-05-11 04:08:20 +00:00
func EscapeSimpleQuotedString(str string) string {
return "\"" + EscapeSimpleQuotedStringContents(str) + "\""
2018-05-11 04:08:20 +00:00
}
2018-05-14 20:36:29 +00:00
// EscapeSimpleQuotedStringContents escapes backslashes, double quotes,
// newlines, and carriage returns in str.
2018-05-14 19:47:05 +00:00
func EscapeSimpleQuotedStringContents(str string) string {
return simpleQuotedStringEscapeReplacer.Replace(str)
}
2018-05-14 20:36:29 +00:00
// UnescapeSimpleQuotedStringIfNeeded calls UnescapeSimpleQuotedString only if
// str is surrounded with double quotes.
2018-05-11 04:08:20 +00:00
func UnescapeSimpleQuotedStringIfNeeded(str string) (string, error) {
if len(str) >= 2 && str[0] == '"' && str[len(str)-1] == '"' {
return UnescapeSimpleQuotedString(str)
}
return str, nil
}
2018-05-14 20:36:29 +00:00
// UnescapeSimpleQuotedString removes surrounding double quotes and calls
// UnescapeSimpleQuotedStringContents.
2018-05-11 04:08:20 +00:00
func UnescapeSimpleQuotedString(str string) (string, error) {
2018-05-10 18:11:18 +00:00
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
2018-05-10 18:11:18 +00:00
}
2018-05-14 20:36:29 +00:00
// UnescapeSimpleQuotedStringContents unescapes backslashes, double quotes,
// newlines, and carriage returns. Also errors if those aren't escaped.
2018-05-11 04:08:20 +00:00
func UnescapeSimpleQuotedStringContents(str string) (string, error) {
2018-05-10 18:11:18 +00:00
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")
2018-05-10 18:11:18 +00:00
default:
if escaping {
2018-05-14 19:47:05 +00:00
if c == 'r' {
ret += "\r"
} else if c == 'n' {
ret += "\n"
} else {
return "", fmt.Errorf("Unexpected escape")
}
} else {
ret += string(c)
2018-05-10 18:11:18 +00:00
}
escaping = false
2018-05-10 18:11:18 +00:00
}
}
return ret, nil
}