2019-11-23 03:52:29 +00:00
|
|
|
package yqlib
|
2015-10-03 05:10:29 +00:00
|
|
|
|
2019-12-01 19:44:44 +00:00
|
|
|
type PathParser interface {
|
|
|
|
ParsePath(path string) []string
|
2015-10-03 05:10:29 +00:00
|
|
|
}
|
|
|
|
|
2019-12-01 19:44:44 +00:00
|
|
|
type parser struct {}
|
|
|
|
|
|
|
|
func NewPathParser() PathParser {
|
|
|
|
return &parser{}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *parser) ParsePath(path string) []string {
|
|
|
|
return p.parsePathAccum([]string{}, path)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *parser) parsePathAccum(paths []string, remaining string) []string {
|
|
|
|
head, tail := p.nextYamlPath(remaining)
|
2015-10-03 05:10:29 +00:00
|
|
|
if tail == "" {
|
|
|
|
return append(paths, head)
|
|
|
|
}
|
2019-12-01 19:44:44 +00:00
|
|
|
return p.parsePathAccum(append(paths, head), tail)
|
2015-10-03 05:10:29 +00:00
|
|
|
}
|
|
|
|
|
2019-12-01 19:44:44 +00:00
|
|
|
func (p *parser) nextYamlPath(path string) (pathElement string, remaining string) {
|
2015-10-03 05:10:29 +00:00
|
|
|
switch path[0] {
|
|
|
|
case '[':
|
|
|
|
// e.g [0].blah.cat -> we need to return "0" and "blah.cat"
|
2019-12-01 19:44:44 +00:00
|
|
|
return p.search(path[1:], []uint8{']'}, true)
|
2015-10-03 05:10:29 +00:00
|
|
|
case '"':
|
|
|
|
// e.g "a.b".blah.cat -> we need to return "a.b" and "blah.cat"
|
2019-12-01 19:44:44 +00:00
|
|
|
return p.search(path[1:], []uint8{'"'}, true)
|
2015-10-03 05:10:29 +00:00
|
|
|
default:
|
|
|
|
// e.g "a.blah.cat" -> return "a" and "blah.cat"
|
2019-12-01 19:44:44 +00:00
|
|
|
return p.search(path[0:], []uint8{'.', '['}, false)
|
2015-10-03 05:10:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-01 19:44:44 +00:00
|
|
|
func (p *parser) search(path string, matchingChars []uint8, skipNext bool) (pathElement string, remaining string) {
|
2015-10-03 05:10:29 +00:00
|
|
|
for i := 0; i < len(path); i++ {
|
|
|
|
var char = path[i]
|
2019-12-01 19:44:44 +00:00
|
|
|
if p.contains(matchingChars, char) {
|
2015-10-03 05:10:29 +00:00
|
|
|
var remainingStart = i + 1
|
|
|
|
if skipNext {
|
|
|
|
remainingStart = remainingStart + 1
|
|
|
|
} else if !skipNext && char != '.' {
|
|
|
|
remainingStart = i
|
|
|
|
}
|
|
|
|
if remainingStart > len(path) {
|
|
|
|
remainingStart = len(path)
|
|
|
|
}
|
2017-09-20 23:40:33 +00:00
|
|
|
return path[0:i], path[remainingStart:]
|
2015-10-03 05:10:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return path, ""
|
|
|
|
}
|
|
|
|
|
2019-12-01 19:44:44 +00:00
|
|
|
func (p *parser) contains(matchingChars []uint8, candidate uint8) bool {
|
2015-10-03 05:10:29 +00:00
|
|
|
for _, a := range matchingChars {
|
|
|
|
if a == candidate {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|