summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/pelletier/go-toml/keysparsing.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/pelletier/go-toml/keysparsing.go')
-rw-r--r--vendor/github.com/pelletier/go-toml/keysparsing.go136
1 files changed, 82 insertions, 54 deletions
diff --git a/vendor/github.com/pelletier/go-toml/keysparsing.go b/vendor/github.com/pelletier/go-toml/keysparsing.go
index 284db646..e923bc4f 100644
--- a/vendor/github.com/pelletier/go-toml/keysparsing.go
+++ b/vendor/github.com/pelletier/go-toml/keysparsing.go
@@ -3,79 +3,107 @@
package toml
import (
- "bytes"
"errors"
"fmt"
"unicode"
)
// Convert the bare key group string to an array.
-// The input supports double quotation to allow "." inside the key name,
+// 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) {
- groups := []string{}
- var buffer bytes.Buffer
- inQuotes := false
- wasInQuotes := false
- ignoreSpace := true
- expectDot := false
+ runes := []rune(key)
+ var groups []string
- for _, char := range key {
- if ignoreSpace {
- if char == ' ' {
- continue
- }
- ignoreSpace = false
+ 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
}
- switch char {
- case '"':
- if inQuotes {
- groups = append(groups, buffer.String())
- buffer.Reset()
- wasInQuotes = true
- }
- inQuotes = !inQuotes
- expectDot = false
- case '.':
- if inQuotes {
- buffer.WriteRune(char)
- } else {
- if !wasInQuotes {
- if buffer.Len() == 0 {
- return nil, errors.New("empty table key")
+ 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
}
- groups = append(groups, buffer.String())
- buffer.Reset()
+ 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")
}
- ignoreSpace = true
- expectDot = false
- wasInQuotes = false
+ r = runes[idx]
+ if r == '\'' {
+ groups = append(groups, string(runes[startIdx:idx]))
+ idx++
+ break
+ }
+ idx++
}
- case ' ':
- if inQuotes {
- buffer.WriteRune(char)
- } else {
- expectDot = true
+ } 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++
}
- default:
- if !inQuotes && !isValidBareChar(char) {
- return nil, fmt.Errorf("invalid bare character: %c", char)
+ } else if r == '.' {
+ idx++
+ if idx >= len(runes) {
+ return nil, fmt.Errorf("unexpected end of key")
}
- if !inQuotes && expectDot {
- return nil, errors.New("what?")
+ r = runes[idx]
+ if !isValidBareChar(r) && r != '\'' && r != '"' && r != ' ' {
+ return nil, fmt.Errorf("expecting key part after dot")
}
- buffer.WriteRune(char)
- expectDot = false
+ } else {
+ return nil, fmt.Errorf("invalid key character: %c", r)
}
}
- if inQuotes {
- return nil, errors.New("mismatched quotes")
- }
- if buffer.Len() > 0 {
- groups = append(groups, buffer.String())
- }
if len(groups) == 0 {
- return nil, errors.New("empty key")
+ return nil, fmt.Errorf("empty key")
}
return groups, nil
}