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.go107
1 files changed, 87 insertions, 20 deletions
diff --git a/vendor/github.com/pelletier/go-toml/keysparsing.go b/vendor/github.com/pelletier/go-toml/keysparsing.go
index d62ca5fd1..9707c6884 100644
--- a/vendor/github.com/pelletier/go-toml/keysparsing.go
+++ b/vendor/github.com/pelletier/go-toml/keysparsing.go
@@ -6,15 +6,37 @@ import (
"bytes"
"errors"
"fmt"
+ "strconv"
"unicode"
)
+var escapeSequenceMap = map[rune]rune{
+ 'b': '\b',
+ 't': '\t',
+ 'n': '\n',
+ 'f': '\f',
+ 'r': '\r',
+ '"': '"',
+ '\\': '\\',
+}
+
+type parseKeyState int
+
+const (
+ BARE parseKeyState = iota
+ BASIC
+ LITERAL
+ ESC
+ UNICODE_4
+ UNICODE_8
+)
+
func parseKey(key string) ([]string, error) {
groups := []string{}
var buffer bytes.Buffer
- inQuotes := false
+ var hex bytes.Buffer
+ state := BARE
wasInQuotes := false
- escapeNext := false
ignoreSpace := true
expectDot := false
@@ -25,25 +47,67 @@ func parseKey(key string) ([]string, error) {
}
ignoreSpace = false
}
- if escapeNext {
- buffer.WriteRune(char)
- escapeNext = false
+
+ if state == ESC {
+ if char == 'u' {
+ state = UNICODE_4
+ hex.Reset()
+ } else if char == 'U' {
+ state = UNICODE_8
+ hex.Reset()
+ } else if newChar, ok := escapeSequenceMap[char]; ok {
+ buffer.WriteRune(newChar)
+ state = BASIC
+ } else {
+ return nil, fmt.Errorf(`invalid escape sequence \%c`, char)
+ }
+ continue
+ }
+
+ if state == UNICODE_4 || state == UNICODE_8 {
+ if isHexDigit(char) {
+ hex.WriteRune(char)
+ }
+ if (state == UNICODE_4 && hex.Len() == 4) || (state == UNICODE_8 && hex.Len() == 8) {
+ if value, err := strconv.ParseInt(hex.String(), 16, 32); err == nil {
+ buffer.WriteRune(rune(value))
+ } else {
+ return nil, err
+ }
+ state = BASIC
+ }
continue
}
+
switch char {
case '\\':
- escapeNext = true
- continue
+ if state == BASIC {
+ state = ESC
+ } else if state == LITERAL {
+ buffer.WriteRune(char)
+ }
+ case '\'':
+ if state == BARE {
+ state = LITERAL
+ } else if state == LITERAL {
+ groups = append(groups, buffer.String())
+ buffer.Reset()
+ wasInQuotes = true
+ state = BARE
+ }
+ expectDot = false
case '"':
- if inQuotes {
+ if state == BARE {
+ state = BASIC
+ } else if state == BASIC {
groups = append(groups, buffer.String())
buffer.Reset()
+ state = BARE
wasInQuotes = true
}
- inQuotes = !inQuotes
expectDot = false
case '.':
- if inQuotes {
+ if state != BARE {
buffer.WriteRune(char)
} else {
if !wasInQuotes {
@@ -58,28 +122,31 @@ func parseKey(key string) ([]string, error) {
wasInQuotes = false
}
case ' ':
- if inQuotes {
+ if state == BASIC {
buffer.WriteRune(char)
} else {
expectDot = true
}
default:
- if !inQuotes && !isValidBareChar(char) {
- return nil, fmt.Errorf("invalid bare character: %c", char)
- }
- if !inQuotes && expectDot {
- return nil, errors.New("what?")
+ if state == BARE {
+ if !isValidBareChar(char) {
+ return nil, fmt.Errorf("invalid bare character: %c", char)
+ } else if expectDot {
+ return nil, errors.New("what?")
+ }
}
buffer.WriteRune(char)
expectDot = false
}
}
- if inQuotes {
- return nil, errors.New("mismatched quotes")
- }
- if escapeNext {
+
+ // state must be BARE at the end
+ if state == ESC {
return nil, errors.New("unfinished escape sequence")
+ } else if state != BARE {
+ return nil, errors.New("mismatched quotes")
}
+
if buffer.Len() > 0 {
groups = append(groups, buffer.String())
}