mirror of
https://codeberg.org/superseriousbusiness/gotosocial.git
synced 2024-12-24 18:08:18 +03:00
0884f89431
* start pulling out + replacing urfave and config * replace many many instances of config * move more stuff => viper * properly remove urfave * move some flags to root command * add testrig commands to root * alias config file keys * start adding cli parsing tests * reorder viper init * remove config path alias * fmt * change config file keys to non-nested * we're more or less in business now * tidy up the common func * go fmt * get tests passing again * add note about the cliparsing tests * reorganize * update docs with changes * structure cmd dir better * rename + move some files around * fix dangling comma
112 lines
2.4 KiB
Go
112 lines
2.4 KiB
Go
// Parsing keys handling both bare and quoted keys.
|
|
|
|
package toml
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
)
|
|
|
|
// Convert the bare key group string to an array.
|
|
// The input supports double quotation and single quotation,
|
|
// but escape sequences are not supported. Lexers must unescape them beforehand.
|
|
func parseKey(key string) ([]string, error) {
|
|
runes := []rune(key)
|
|
var groups []string
|
|
|
|
if len(key) == 0 {
|
|
return nil, errors.New("empty key")
|
|
}
|
|
|
|
idx := 0
|
|
for idx < len(runes) {
|
|
for ; idx < len(runes) && isSpace(runes[idx]); idx++ {
|
|
// skip leading whitespace
|
|
}
|
|
if idx >= len(runes) {
|
|
break
|
|
}
|
|
r := runes[idx]
|
|
if isValidBareChar(r) {
|
|
// parse bare key
|
|
startIdx := idx
|
|
endIdx := -1
|
|
idx++
|
|
for idx < len(runes) {
|
|
r = runes[idx]
|
|
if isValidBareChar(r) {
|
|
idx++
|
|
} else if r == '.' {
|
|
endIdx = idx
|
|
break
|
|
} else if isSpace(r) {
|
|
endIdx = idx
|
|
for ; idx < len(runes) && isSpace(runes[idx]); idx++ {
|
|
// skip trailing whitespace
|
|
}
|
|
if idx < len(runes) && runes[idx] != '.' {
|
|
return nil, fmt.Errorf("invalid key character after whitespace: %c", runes[idx])
|
|
}
|
|
break
|
|
} else {
|
|
return nil, fmt.Errorf("invalid bare key character: %c", r)
|
|
}
|
|
}
|
|
if endIdx == -1 {
|
|
endIdx = idx
|
|
}
|
|
groups = append(groups, string(runes[startIdx:endIdx]))
|
|
} else if r == '\'' {
|
|
// parse single quoted key
|
|
idx++
|
|
startIdx := idx
|
|
for {
|
|
if idx >= len(runes) {
|
|
return nil, fmt.Errorf("unclosed single-quoted key")
|
|
}
|
|
r = runes[idx]
|
|
if r == '\'' {
|
|
groups = append(groups, string(runes[startIdx:idx]))
|
|
idx++
|
|
break
|
|
}
|
|
idx++
|
|
}
|
|
} else if r == '"' {
|
|
// parse double quoted key
|
|
idx++
|
|
startIdx := idx
|
|
for {
|
|
if idx >= len(runes) {
|
|
return nil, fmt.Errorf("unclosed double-quoted key")
|
|
}
|
|
r = runes[idx]
|
|
if r == '"' {
|
|
groups = append(groups, string(runes[startIdx:idx]))
|
|
idx++
|
|
break
|
|
}
|
|
idx++
|
|
}
|
|
} else if r == '.' {
|
|
idx++
|
|
if idx >= len(runes) {
|
|
return nil, fmt.Errorf("unexpected end of key")
|
|
}
|
|
r = runes[idx]
|
|
if !isValidBareChar(r) && r != '\'' && r != '"' && r != ' ' {
|
|
return nil, fmt.Errorf("expecting key part after dot")
|
|
}
|
|
} else {
|
|
return nil, fmt.Errorf("invalid key character: %c", r)
|
|
}
|
|
}
|
|
if len(groups) == 0 {
|
|
return nil, fmt.Errorf("empty key")
|
|
}
|
|
return groups, nil
|
|
}
|
|
|
|
func isValidBareChar(r rune) bool {
|
|
return isAlphanumeric(r) || r == '-' || isDigit(r)
|
|
}
|