yq/pkg/yqlib/operator_create_map.go

92 lines
2.6 KiB
Go
Raw Normal View History

2020-11-03 23:48:43 +00:00
package yqlib
2020-10-21 01:54:58 +00:00
import (
"container/list"
)
func createMapOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
2020-10-21 01:54:58 +00:00
log.Debugf("-- createMapOperation")
2020-11-13 02:19:54 +00:00
//each matchingNodes entry should turn into a sequence of keys to create.
//then collect object should do a cross function of the same index sequence for all matches.
var path []interface{}
var document uint
2020-11-13 02:19:54 +00:00
sequences := list.New()
if context.MatchingNodes.Len() > 0 {
2020-11-13 02:19:54 +00:00
for matchingNodeEl := context.MatchingNodes.Front(); matchingNodeEl != nil; matchingNodeEl = matchingNodeEl.Next() {
2020-11-13 02:19:54 +00:00
matchingNode := matchingNodeEl.Value.(*CandidateNode)
sequenceNode, err := sequenceFor(d, context, matchingNode, expressionNode)
2020-11-13 02:19:54 +00:00
if err != nil {
return Context{}, err
2020-11-13 02:19:54 +00:00
}
sequences.PushBack(sequenceNode)
}
} else {
sequenceNode, err := sequenceFor(d, context, nil, expressionNode)
2020-11-13 02:19:54 +00:00
if err != nil {
return Context{}, err
2020-11-13 02:19:54 +00:00
}
sequences.PushBack(sequenceNode)
}
2023-04-08 10:17:13 +00:00
node := listToNodeSeq(sequences)
node.Document = document
node.Path = path
return context.SingleChildContext(node), nil
2020-11-13 02:19:54 +00:00
}
func sequenceFor(d *dataTreeNavigator, context Context, matchingNode *CandidateNode, expressionNode *ExpressionNode) (*CandidateNode, error) {
2020-11-13 02:19:54 +00:00
var path []interface{}
var document uint
2020-11-13 02:19:54 +00:00
var matches = list.New()
if matchingNode != nil {
path = matchingNode.Path
document = matchingNode.Document
matches.PushBack(matchingNode)
2020-10-21 01:54:58 +00:00
}
mapPairs, err := crossFunction(d, context.ChildContext(matches), expressionNode,
func(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) {
2023-04-08 10:17:13 +00:00
node := CandidateNode{Kind: MappingNode, Tag: "!!map"}
2020-10-28 02:00:26 +00:00
log.Debugf("LHS:", NodeToString(lhs))
log.Debugf("RHS:", NodeToString(rhs))
2023-04-08 10:17:13 +00:00
node.Content = []*CandidateNode{
lhs.unwrapDocument(),
rhs.unwrapDocument(),
2020-10-21 01:54:58 +00:00
}
2023-04-08 10:17:13 +00:00
node.Document = document
node.Path = path
2020-10-21 01:54:58 +00:00
2023-04-08 10:17:13 +00:00
return &node, nil
}, false)
2020-10-21 01:54:58 +00:00
if err != nil {
return nil, err
}
innerList := listToNodeSeq(mapPairs.MatchingNodes)
2023-04-08 10:17:13 +00:00
innerList.Style = FlowStyle
innerList.Document = document
innerList.Path = path
return innerList, nil
2020-11-13 02:19:54 +00:00
}
// NOTE: here the document index gets dropped so we
2020-11-13 02:19:54 +00:00
// no longer know where the node originates from.
2023-04-08 10:17:13 +00:00
func listToNodeSeq(list *list.List) *CandidateNode {
node := CandidateNode{Kind: SequenceNode, Tag: "!!seq"}
2020-11-13 02:19:54 +00:00
for entry := list.Front(); entry != nil; entry = entry.Next() {
entryCandidate := entry.Value.(*CandidateNode)
log.Debugf("Collecting %v into sequence", NodeToString(entryCandidate))
2023-04-08 10:17:13 +00:00
node.Content = append(node.Content, entryCandidate)
2020-10-21 01:54:58 +00:00
}
2020-11-13 02:19:54 +00:00
return &node
2020-10-21 01:54:58 +00:00
}