All checks were successful
Go Action / goaction (push) Successful in 29s
Reviewed-on: #12
122 lines
1.8 KiB
Go
122 lines
1.8 KiB
Go
package key
|
|
|
|
import (
|
|
"strings"
|
|
)
|
|
|
|
const (
|
|
prefixByPath = "byPath"
|
|
)
|
|
|
|
func newMap() *Map {
|
|
return &Map{
|
|
idx: 0,
|
|
wild: nil,
|
|
children: nil,
|
|
}
|
|
}
|
|
|
|
type Map struct {
|
|
idx int
|
|
wild *Map
|
|
children map[string]*Map
|
|
}
|
|
|
|
func ByPath(name, sep string) []string {
|
|
return []string{prefixByPath, name, sep}
|
|
}
|
|
|
|
func (m *Map) Index(path []string) (int, bool) {
|
|
if data, ok := m.find(path); ok {
|
|
return data.idx, true
|
|
}
|
|
|
|
if len(path) == 3 && path[0] == prefixByPath {
|
|
data, ok := m.byPath(path[1], path[2])
|
|
|
|
return data.idx, ok
|
|
}
|
|
|
|
return 0, false
|
|
}
|
|
|
|
func (m *Map) Add(idx int, path []string) {
|
|
m.add(path).idx = idx
|
|
}
|
|
|
|
func (m *Map) add(path []string) *Map {
|
|
name, path := path[0], path[1:]
|
|
|
|
if IsWild(name) {
|
|
m.wild = newMap()
|
|
|
|
return m.wild.add(path)
|
|
}
|
|
|
|
if m.children == nil {
|
|
m.children = map[string]*Map{}
|
|
}
|
|
|
|
if _, ok := m.children[name]; !ok {
|
|
m.children[name] = newMap()
|
|
}
|
|
|
|
if len(path) > 0 {
|
|
return m.children[name].add(path)
|
|
}
|
|
|
|
return m.children[name]
|
|
}
|
|
|
|
func (m *Map) byPath(path, sep string) (*Map, bool) {
|
|
for name := range m.children {
|
|
if after, ok := strings.CutPrefix(path, name); ok {
|
|
data := m.children[name]
|
|
if len(after) == 0 {
|
|
return data, true
|
|
}
|
|
|
|
after, ok = strings.CutPrefix(after, sep)
|
|
if !ok {
|
|
return data, false
|
|
}
|
|
|
|
if data.wild == nil {
|
|
return data.byPath(after, sep)
|
|
}
|
|
|
|
if idx := strings.Index(after, sep); idx != -1 {
|
|
return data.wild.byPath(after[idx+1:], sep)
|
|
}
|
|
|
|
return data, false
|
|
}
|
|
}
|
|
|
|
return m, false
|
|
}
|
|
|
|
func (m *Map) find(path []string) (*Map, bool) {
|
|
name := path[0]
|
|
|
|
last := len(path) == 1
|
|
if !last {
|
|
path = path[1:]
|
|
}
|
|
|
|
if m.wild != nil {
|
|
return m.wild.find(path)
|
|
}
|
|
|
|
data, ok := m.children[name]
|
|
if !ok {
|
|
return data, false
|
|
}
|
|
|
|
if last {
|
|
return data, data.children == nil
|
|
}
|
|
|
|
return data.find(path)
|
|
}
|