53 lines
1.2 KiB
Go
53 lines
1.2 KiB
Go
package engine
|
|
|
|
import "gitea.maximumdirect.net/eric/ConfigKit/internal/document"
|
|
|
|
// documentLookup contains read-only mapping positions for a completed document.
|
|
type documentLookup struct {
|
|
byNode map[*document.Node]map[string]int
|
|
}
|
|
|
|
func buildDocumentLookup(root *document.Node) *documentLookup {
|
|
lookup := &documentLookup{byNode: make(map[*document.Node]map[string]int)}
|
|
visited := make(map[*document.Node]struct{})
|
|
var visit func(*document.Node)
|
|
visit = func(node *document.Node) {
|
|
if node == nil {
|
|
return
|
|
}
|
|
if _, ok := visited[node]; ok {
|
|
return
|
|
}
|
|
visited[node] = struct{}{}
|
|
switch node.Kind {
|
|
case document.Mapping:
|
|
entries := make(map[string]int, len(node.Mapping))
|
|
for index, entry := range node.Mapping {
|
|
if _, exists := entries[entry.Key]; !exists {
|
|
entries[entry.Key] = index
|
|
}
|
|
visit(entry.Value)
|
|
}
|
|
lookup.byNode[node] = entries
|
|
case document.Sequence:
|
|
for _, child := range node.Sequence {
|
|
visit(child)
|
|
}
|
|
}
|
|
}
|
|
visit(root)
|
|
return lookup
|
|
}
|
|
|
|
func (lookup *documentLookup) find(node *document.Node, key string) int {
|
|
if lookup == nil {
|
|
return -1
|
|
}
|
|
if entries := lookup.byNode[node]; entries != nil {
|
|
if index, ok := entries[key]; ok {
|
|
return index
|
|
}
|
|
}
|
|
return -1
|
|
}
|