Sped up explode operator

This commit is contained in:
Mike Farah 2021-10-11 10:41:15 +11:00
parent 839f795710
commit 4a4aae00af

View File

@ -141,6 +141,48 @@ func explodeOperator(d *dataTreeNavigator, context Context, expressionNode *Expr
return context, nil return context, nil
} }
func reconstructAliasedMap(node *yaml.Node, context Context) error {
var newContent = list.New()
// can I short cut here by prechecking if there's an anchor in the map?
// no it needs to recurse in overrideEntry.
for index := 0; index < len(node.Content); index = index + 2 {
keyNode := node.Content[index]
valueNode := node.Content[index+1]
log.Debugf("traversing %v", keyNode.Value)
if keyNode.Value != "<<" {
err := overrideEntry(node, keyNode, valueNode, index, context.ChildContext(newContent))
if err != nil {
return err
}
} else {
if valueNode.Kind == yaml.SequenceNode {
log.Debugf("an alias merge list!")
for index := len(valueNode.Content) - 1; index >= 0; index = index - 1 {
aliasNode := valueNode.Content[index]
err := applyAlias(node, aliasNode.Alias, index, context.ChildContext(newContent))
if err != nil {
return err
}
}
} else {
log.Debugf("an alias merge!")
err := applyAlias(node, valueNode.Alias, index, context.ChildContext(newContent))
if err != nil {
return err
}
}
}
}
node.Content = make([]*yaml.Node, newContent.Len())
index := 0
for newEl := newContent.Front(); newEl != nil; newEl = newEl.Next() {
node.Content[index] = newEl.Value.(*yaml.Node)
index++
}
return nil
}
func explodeNode(node *yaml.Node, context Context) error { func explodeNode(node *yaml.Node, context Context) error {
node.Anchor = "" node.Anchor = ""
switch node.Kind { switch node.Kind {
@ -165,43 +207,35 @@ func explodeNode(node *yaml.Node, context Context) error {
} }
return nil return nil
case yaml.MappingNode: case yaml.MappingNode:
var newContent = list.New() // //check the map has an alias in it
hasAlias := false
for index := 0; index < len(node.Content); index = index + 2 { for index := 0; index < len(node.Content); index = index + 2 {
keyNode := node.Content[index] keyNode := node.Content[index]
valueNode := node.Content[index+1] if keyNode.Value == "<<" {
log.Debugf("traversing %v", keyNode.Value) hasAlias = true
if keyNode.Value != "<<" { break
err := overrideEntry(node, keyNode, valueNode, index, context.ChildContext(newContent)) }
}
if hasAlias {
// this is a slow op, which is why we want to check before running it.
return reconstructAliasedMap(node, context)
} else {
// this map has no aliases, but it's kids might
for index := 0; index < len(node.Content); index = index + 2 {
keyNode := node.Content[index]
valueNode := node.Content[index+1]
err := explodeNode(keyNode, context)
if err != nil { if err != nil {
return err return err
} }
} else { err = explodeNode(valueNode, context)
if valueNode.Kind == yaml.SequenceNode { if err != nil {
log.Debugf("an alias merge list!") return err
for index := len(valueNode.Content) - 1; index >= 0; index = index - 1 {
aliasNode := valueNode.Content[index]
err := applyAlias(node, aliasNode.Alias, index, context.ChildContext(newContent))
if err != nil {
return err
}
}
} else {
log.Debugf("an alias merge!")
err := applyAlias(node, valueNode.Alias, index, context.ChildContext(newContent))
if err != nil {
return err
}
} }
} }
return nil
} }
node.Content = make([]*yaml.Node, newContent.Len())
index := 0
for newEl := newContent.Front(); newEl != nil; newEl = newEl.Next() {
node.Content[index] = newEl.Value.(*yaml.Node)
index++
}
return nil
default: default:
return nil return nil
} }