diff --git a/pkg/yqlib/candidate_node.go b/pkg/yqlib/candidate_node.go index f2ad1069..493fb118 100644 --- a/pkg/yqlib/candidate_node.go +++ b/pkg/yqlib/candidate_node.go @@ -191,10 +191,11 @@ func (n *CandidateNode) CreateReplacement(kind Kind, tag string, value string) * } } -func (n *CandidateNode) CreateReplacementWithDocWrappers(kind Kind, tag string, value string) *CandidateNode { - replacement := n.CreateReplacement(kind, tag, value) +func (n *CandidateNode) CreateReplacementWithDocWrappers(kind Kind, tag string, style Style) *CandidateNode { + replacement := n.CreateReplacement(kind, tag, "") replacement.LeadingContent = n.LeadingContent replacement.TrailingContent = n.TrailingContent + replacement.Style = style return replacement } diff --git a/pkg/yqlib/operator_add.go b/pkg/yqlib/operator_add.go index f0281bdf..d201f717 100644 --- a/pkg/yqlib/operator_add.go +++ b/pkg/yqlib/operator_add.go @@ -5,8 +5,6 @@ import ( "strconv" "strings" "time" - - yaml "gopkg.in/yaml.v3" ) func createAddOp(lhs *ExpressionNode, rhs *ExpressionNode) *ExpressionNode { @@ -19,23 +17,20 @@ func addAssignOperator(d *dataTreeNavigator, context Context, expressionNode *Ex return compoundAssignFunction(d, context, expressionNode, createAddOp) } -func toNodes(candidate *CandidateNode, lhs *CandidateNode) ([]*yaml.Node, error) { - if candidate.Node.Tag == "!!null" { - return []*yaml.Node{}, nil - } - clone, err := candidate.Copy() - if err != nil { - return nil, err +func toNodes(candidate *CandidateNode, lhs *CandidateNode) ([]*CandidateNode, error) { + if candidate.Tag == "!!null" { + return []*CandidateNode{}, nil } + clone := candidate.Copy() - switch candidate.Node.Kind { - case yaml.SequenceNode: - return clone.Node.Content, nil + switch candidate.Kind { + case SequenceNode: + return clone.Content, nil default: - if len(lhs.Node.Content) > 0 { - clone.Node.Style = lhs.Node.Content[0].Style + if len(lhs.Content) > 0 { + clone.Style = lhs.Content[0].Style } - return []*yaml.Node{clone.Node}, nil + return []*CandidateNode{clone}, nil } } @@ -47,50 +42,50 @@ func addOperator(d *dataTreeNavigator, context Context, expressionNode *Expressi } func add(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) { - lhs.Node = unwrapDoc(lhs.Node) - rhs.Node = unwrapDoc(rhs.Node) + lhs = lhs.unwrapDocument() + rhs = rhs.unwrapDocument() - lhsNode := lhs.Node + lhsNode := lhs if lhsNode.Tag == "!!null" { - return lhs.CreateReplacement(rhs.Node), nil + return lhs.CreateReplacement(rhs), nil } - target := lhs.CreateReplacement(&yaml.Node{ - Anchor: lhs.Node.Anchor, + target := lhs.CreateReplacement(&yaml{ + Anchor: lhs.Anchor, }) switch lhsNode.Kind { - case yaml.MappingNode: - if rhs.Node.Kind != yaml.MappingNode { - return nil, fmt.Errorf("%v (%v) cannot be added to a %v (%v)", rhs.Node.Tag, rhs.GetNicePath(), lhsNode.Tag, lhs.GetNicePath()) + case MappingNode: + if rhs.Kind != MappingNode { + return nil, fmt.Errorf("%v (%v) cannot be added to a %v (%v)", rhs.Tag, rhs.GetNicePath(), lhsNode.Tag, lhs.GetNicePath()) } addMaps(target, lhs, rhs) - case yaml.SequenceNode: + case SequenceNode: if err := addSequences(target, lhs, rhs); err != nil { return nil, err } - case yaml.ScalarNode: - if rhs.Node.Kind != yaml.ScalarNode { - return nil, fmt.Errorf("%v (%v) cannot be added to a %v (%v)", rhs.Node.Tag, rhs.GetNicePath(), lhsNode.Tag, lhs.GetNicePath()) + case ScalarNode: + if rhs.Kind != ScalarNode { + return nil, fmt.Errorf("%v (%v) cannot be added to a %v (%v)", rhs.Tag, rhs.GetNicePath(), lhsNode.Tag, lhs.GetNicePath()) } - target.Node.Kind = yaml.ScalarNode - target.Node.Style = lhsNode.Style - if err := addScalars(context, target, lhsNode, rhs.Node); err != nil { + target.Kind = ScalarNode + target.Style = lhsNode.Style + if err := addScalars(context, target, lhsNode, rhs); err != nil { return nil, err } } return target, nil } -func addScalars(context Context, target *CandidateNode, lhs *yaml.Node, rhs *yaml.Node) error { +func addScalars(context Context, target *CandidateNode, lhs *CandidateNode, rhs *CandidateNode) error { lhsTag := lhs.Tag - rhsTag := guessTagFromCustomType(rhs) + rhsTag := rhs.guessTagFromCustomType() lhsIsCustom := false if !strings.HasPrefix(lhsTag, "!!") { // custom tag - we have to have a guess - lhsTag = guessTagFromCustomType(lhs) + lhsTag = lhs.guessTagFromCustomType() lhsIsCustom = true } @@ -106,11 +101,11 @@ func addScalars(context Context, target *CandidateNode, lhs *yaml.Node, rhs *yam return addDateTimes(context.GetDateTimeLayout(), target, lhs, rhs) } else if lhsTag == "!!str" { - target.Node.Tag = lhs.Tag - target.Node.Value = lhs.Value + rhs.Value + target.Tag = lhs.Tag + target.Value = lhs.Value + rhs.Value } else if rhsTag == "!!str" { - target.Node.Tag = rhs.Tag - target.Node.Value = lhs.Value + rhs.Value + target.Tag = rhs.Tag + target.Value = lhs.Value + rhs.Value } else if lhsTag == "!!int" && rhsTag == "!!int" { format, lhsNum, err := parseInt64(lhs.Value) if err != nil { @@ -121,8 +116,8 @@ func addScalars(context Context, target *CandidateNode, lhs *yaml.Node, rhs *yam return err } sum := lhsNum + rhsNum - target.Node.Tag = lhs.Tag - target.Node.Value = fmt.Sprintf(format, sum) + target.Tag = lhs.Tag + target.Value = fmt.Sprintf(format, sum) } else if (lhsTag == "!!int" || lhsTag == "!!float") && (rhsTag == "!!int" || rhsTag == "!!float") { lhsNum, err := strconv.ParseFloat(lhs.Value, 64) if err != nil { @@ -134,18 +129,18 @@ func addScalars(context Context, target *CandidateNode, lhs *yaml.Node, rhs *yam } sum := lhsNum + rhsNum if lhsIsCustom { - target.Node.Tag = lhs.Tag + target.Tag = lhs.Tag } else { - target.Node.Tag = "!!float" + target.Tag = "!!float" } - target.Node.Value = fmt.Sprintf("%v", sum) + target.Value = fmt.Sprintf("%v", sum) } else { return fmt.Errorf("%v cannot be added to %v", lhsTag, rhsTag) } return nil } -func addDateTimes(layout string, target *CandidateNode, lhs *yaml.Node, rhs *yaml.Node) error { +func addDateTimes(layout string, target *CandidateNode, lhs *CandidateNode, rhs *CandidateNode) error { duration, err := time.ParseDuration(rhs.Value) if err != nil { @@ -158,52 +153,52 @@ func addDateTimes(layout string, target *CandidateNode, lhs *yaml.Node, rhs *yam } newTime := currentTime.Add(duration) - target.Node.Value = newTime.Format(layout) + target.Value = newTime.Format(layout) return nil } func addSequences(target *CandidateNode, lhs *CandidateNode, rhs *CandidateNode) error { - target.Node.Kind = yaml.SequenceNode - if len(lhs.Node.Content) > 0 { - target.Node.Style = lhs.Node.Style + target.Kind = SequenceNode + if len(lhs.Content) > 0 { + target.Style = lhs.Style } - target.Node.Tag = lhs.Node.Tag + target.Tag = lhs.Tag extraNodes, err := toNodes(rhs, lhs) if err != nil { return err } - target.Node.Content = append(deepCloneContent(lhs.Node.Content), extraNodes...) + target.Content = append(lhs.CopyChildren(), extraNodes...) return nil } func addMaps(target *CandidateNode, lhsC *CandidateNode, rhsC *CandidateNode) { - lhs := lhsC.Node - rhs := rhsC.Node + lhs := lhsC + rhs := rhsC - target.Node.Content = make([]*yaml.Node, len(lhs.Content)) - copy(target.Node.Content, lhs.Content) + target.Content = make([]*CandidateNode, len(lhs.Content)) + copy(target.Content, lhs.Content) for index := 0; index < len(rhs.Content); index = index + 2 { key := rhs.Content[index] value := rhs.Content[index+1] log.Debug("finding %v", key.Value) - indexInLHS := findKeyInMap(target.Node, key) + indexInLHS := findKeyInMap(target, key) log.Debug("indexInLhs %v", indexInLHS) if indexInLHS < 0 { // not in there, append it - target.Node.Content = append(target.Node.Content, key, value) + target.Content = append(target.Content, key, value) } else { // it's there, replace it - target.Node.Content[indexInLHS+1] = value + target.Content[indexInLHS+1] = value } } - target.Node.Kind = yaml.MappingNode + target.Kind = MappingNode if len(lhs.Content) > 0 { - target.Node.Style = lhs.Style + target.Style = lhs.Style } - target.Node.Tag = lhs.Tag + target.Tag = lhs.Tag } diff --git a/pkg/yqlib/operator_alternative.go b/pkg/yqlib/operator_alternative.go index ca8569fc..0c45cbf0 100644 --- a/pkg/yqlib/operator_alternative.go +++ b/pkg/yqlib/operator_alternative.go @@ -9,7 +9,7 @@ func alternativeOperator(d *dataTreeNavigator, context Context, expressionNode * if lhs == nil { return nil, nil } - truthy, err := isTruthy(lhs) + truthy, err := isTruthyNode(lhs) if err != nil { return nil, err } @@ -29,12 +29,8 @@ func alternativeFunc(d *dataTreeNavigator, context Context, lhs *CandidateNode, if rhs == nil { return lhs, nil } - lhs.Node = unwrapDoc(lhs.Node) - rhs.Node = unwrapDoc(rhs.Node) - log.Debugf("Alternative LHS: %v", lhs.Node.Tag) - log.Debugf("- RHS: %v", rhs.Node.Tag) - isTrue, err := isTruthy(lhs) + isTrue, err := isTruthyNode(lhs) if err != nil { return nil, err } else if isTrue { diff --git a/pkg/yqlib/operator_assign.go b/pkg/yqlib/operator_assign.go index f21f4522..0d856da7 100644 --- a/pkg/yqlib/operator_assign.go +++ b/pkg/yqlib/operator_assign.go @@ -8,9 +8,8 @@ type assignPreferences struct { func assignUpdateFunc(prefs assignPreferences) crossFunctionCalculation { return func(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) { - rhs.Node = unwrapDoc(rhs.Node) - if !prefs.OnlyWriteNull || lhs.Node.Tag == "!!null" { - lhs.UpdateFrom(rhs, prefs) + if !prefs.OnlyWriteNull || lhs.Tag == "!!null" { + lhs.UpdateFrom(rhs.unwrapDocument(), prefs) } return lhs, nil } @@ -60,8 +59,7 @@ func assignUpdateOperator(d *dataTreeNavigator, context Context, expressionNode if first != nil { rhsCandidate := first.Value.(*CandidateNode) - rhsCandidate.Node = unwrapDoc(rhsCandidate.Node) - candidate.UpdateFrom(rhsCandidate, prefs) + candidate.UpdateFrom(rhsCandidate.unwrapDocument(), prefs) } } @@ -92,7 +90,7 @@ func assignAttributesOperator(d *dataTreeNavigator, context Context, expressionN if expressionNode.Operation.Preferences != nil { prefs = expressionNode.Operation.Preferences.(assignPreferences) } - if !prefs.OnlyWriteNull || candidate.Node.Tag == "!!null" { + if !prefs.OnlyWriteNull || candidate.Tag == "!!null" { candidate.UpdateAttributesFrom(first.Value.(*CandidateNode), prefs) } } diff --git a/pkg/yqlib/operator_booleans.go b/pkg/yqlib/operator_booleans.go index d919b9a6..87aac785 100644 --- a/pkg/yqlib/operator_booleans.go +++ b/pkg/yqlib/operator_booleans.go @@ -3,36 +3,26 @@ package yqlib import ( "container/list" "fmt" - - yaml "gopkg.in/yaml.v3" + "strings" ) -func isTruthyNode(node *yaml.Node) (bool, error) { - value := true +func isTruthyNode(candidate *CandidateNode) (bool, error) { + if candidate == nil { + return false, nil + } + node := candidate.unwrapDocument() if node.Tag == "!!null" { return false, nil } - if node.Kind == yaml.ScalarNode && node.Tag == "!!bool" { - errDecoding := node.Decode(&value) - if errDecoding != nil { - return false, errDecoding - } + if node.Kind == ScalarNode && node.Tag == "!!bool" { + // yes/y/true/on + return (strings.EqualFold(node.Value, "y") || + strings.EqualFold(node.Value, "yes") || + strings.EqualFold(node.Value, "on") || + strings.EqualFold(node.Value, "true")), nil } - return value, nil -} - -func isTruthy(c *CandidateNode) (bool, error) { - node := unwrapDoc(c.Node) - return isTruthyNode(node) -} - -func getBoolean(candidate *CandidateNode) (bool, error) { - if candidate != nil { - candidate.Node = unwrapDoc(candidate.Node) - return isTruthy(candidate) - } - return false, nil + return true, nil } func getOwner(lhs *CandidateNode, rhs *CandidateNode) *CandidateNode { @@ -48,7 +38,7 @@ func getOwner(lhs *CandidateNode, rhs *CandidateNode) *CandidateNode { func returnRhsTruthy(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) { owner := getOwner(lhs, rhs) - rhsBool, err := getBoolean(rhs) + rhsBool, err := isTruthyNode(rhs) if err != nil { return nil, err } @@ -61,7 +51,7 @@ func returnLHSWhen(targetBool bool) func(lhs *CandidateNode) (*CandidateNode, er var err error var lhsBool bool - if lhsBool, err = getBoolean(lhs); err != nil || lhsBool != targetBool { + if lhsBool, err = isTruthyNode(lhs); err != nil || lhsBool != targetBool { return nil, err } owner := &CandidateNode{} @@ -72,18 +62,17 @@ func returnLHSWhen(targetBool bool) func(lhs *CandidateNode) (*CandidateNode, er } } -func findBoolean(wantBool bool, d *dataTreeNavigator, context Context, expressionNode *ExpressionNode, sequenceNode *yaml.Node) (bool, error) { +func findBoolean(wantBool bool, d *dataTreeNavigator, context Context, expressionNode *ExpressionNode, sequenceNode *CandidateNode) (bool, error) { for _, node := range sequenceNode.Content { if expressionNode != nil { //need to evaluate the expression against the node - candidate := &CandidateNode{Node: node} - rhs, err := d.GetMatchingNodes(context.SingleReadonlyChildContext(candidate), expressionNode) + rhs, err := d.GetMatchingNodes(context.SingleReadonlyChildContext(node), expressionNode) if err != nil { return false, err } if rhs.MatchingNodes.Len() > 0 { - node = rhs.MatchingNodes.Front().Value.(*CandidateNode).Node + node = rhs.MatchingNodes.Front().Value.(*CandidateNode) } else { // no results found, ignore this entry continue @@ -106,8 +95,8 @@ func allOperator(d *dataTreeNavigator, context Context, expressionNode *Expressi for el := context.MatchingNodes.Front(); el != nil; el = el.Next() { candidate := el.Value.(*CandidateNode) - candidateNode := unwrapDoc(candidate.Node) - if candidateNode.Kind != yaml.SequenceNode { + candidateNode := candidate.unwrapDocument() + if candidateNode.Kind != SequenceNode { return Context{}, fmt.Errorf("any only supports arrays, was %v", candidateNode.Tag) } booleanResult, err := findBoolean(false, d, context, expressionNode.RHS, candidateNode) @@ -125,8 +114,8 @@ func anyOperator(d *dataTreeNavigator, context Context, expressionNode *Expressi for el := context.MatchingNodes.Front(); el != nil; el = el.Next() { candidate := el.Value.(*CandidateNode) - candidateNode := unwrapDoc(candidate.Node) - if candidateNode.Kind != yaml.SequenceNode { + candidateNode := candidate.unwrapDocument() + if candidateNode.Kind != SequenceNode { return Context{}, fmt.Errorf("any only supports arrays, was %v", candidateNode.Tag) } booleanResult, err := findBoolean(true, d, context, expressionNode.RHS, candidateNode) @@ -164,7 +153,7 @@ func notOperator(d *dataTreeNavigator, context Context, expressionNode *Expressi for el := context.MatchingNodes.Front(); el != nil; el = el.Next() { candidate := el.Value.(*CandidateNode) log.Debug("notOperation checking %v", candidate) - truthy, errDecoding := isTruthy(candidate) + truthy, errDecoding := isTruthyNode(candidate) if errDecoding != nil { return Context{}, errDecoding } diff --git a/pkg/yqlib/operator_collect.go b/pkg/yqlib/operator_collect.go index b153952c..3272f15f 100644 --- a/pkg/yqlib/operator_collect.go +++ b/pkg/yqlib/operator_collect.go @@ -2,12 +2,10 @@ package yqlib import ( "container/list" - - yaml "gopkg.in/yaml.v3" ) func collectTogether(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (*CandidateNode, error) { - collectedNode := &yaml.Node{Kind: yaml.SequenceNode, Tag: "!!seq"} + collectedNode := &CandidateNode{Kind: SequenceNode, Tag: "!!seq"} for el := context.MatchingNodes.Front(); el != nil; el = el.Next() { candidate := el.Value.(*CandidateNode) collectExpResults, err := d.GetMatchingNodes(context.SingleReadonlyChildContext(candidate), expressionNode) @@ -17,10 +15,10 @@ func collectTogether(d *dataTreeNavigator, context Context, expressionNode *Expr for result := collectExpResults.MatchingNodes.Front(); result != nil; result = result.Next() { resultC := result.Value.(*CandidateNode) log.Debugf("found this: %v", NodeToString(resultC)) - collectedNode.Content = append(collectedNode.Content, unwrapDoc(resultC.Node)) + collectedNode.Content = append(collectedNode.Content, resultC.unwrapDocument()) } } - return &CandidateNode{Node: collectedNode}, nil + return collectedNode, nil } func collectOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) { @@ -28,9 +26,8 @@ func collectOperator(d *dataTreeNavigator, context Context, expressionNode *Expr if context.MatchingNodes.Len() == 0 { log.Debugf("nothing to collect") - node := &yaml.Node{Kind: yaml.SequenceNode, Tag: "!!seq", Value: "[]"} - candidate := &CandidateNode{Node: node} - return context.SingleChildContext(candidate), nil + node := &CandidateNode{Kind: SequenceNode, Tag: "!!seq", Value: "[]"} + return context.SingleChildContext(node), nil } var evaluateAllTogether = true diff --git a/pkg/yqlib/operator_collect_object.go b/pkg/yqlib/operator_collect_object.go index 59417a62..0c4bb1a0 100644 --- a/pkg/yqlib/operator_collect_object.go +++ b/pkg/yqlib/operator_collect_object.go @@ -2,8 +2,6 @@ package yqlib import ( "container/list" - - yaml "gopkg.in/yaml.v3" ) /* @@ -23,26 +21,26 @@ func collectObjectOperator(d *dataTreeNavigator, originalContext Context, expres context := originalContext.WritableClone() if context.MatchingNodes.Len() == 0 { - node := &yaml.Node{Kind: yaml.MappingNode, Tag: "!!map", Value: "{}"} - candidate := &CandidateNode{Node: node} + candidate := &CandidateNode{Kind: MappingNode, Tag: "!!map", Value: "{}"} return context.SingleChildContext(candidate), nil } first := context.MatchingNodes.Front().Value.(*CandidateNode) - var rotated = make([]*list.List, len(first.Node.Content)) + var rotated = make([]*list.List, len(first.Content)) - for i := 0; i < len(first.Node.Content); i++ { + for i := 0; i < len(first.Content); i++ { rotated[i] = list.New() } for el := context.MatchingNodes.Front(); el != nil; el = el.Next() { candidateNode := el.Value.(*CandidateNode) - for i := 0; i < len(first.Node.Content); i++ { - rotated[i].PushBack(candidateNode.CreateChildInArray(i, candidateNode.Node.Content[i])) + for i := 0; i < len(first.Content); i++ { + + rotated[i].PushBack(candidateNode.CreateChildInArray(i, candidateNode.Content[i])) } } newObject := list.New() - for i := 0; i < len(first.Node.Content); i++ { + for i := 0; i < len(first.Content); i++ { additions, err := collect(d, context.ChildContext(list.New()), rotated[i]) if err != nil { return Context{}, err @@ -82,10 +80,7 @@ func collect(d *dataTreeNavigator, context Context, remainingMatches *list.List) aggCandidate := el.Value.(*CandidateNode) for splatEl := splatted.MatchingNodes.Front(); splatEl != nil; splatEl = splatEl.Next() { splatCandidate := splatEl.Value.(*CandidateNode) - newCandidate, err := aggCandidate.Copy() - if err != nil { - return Context{}, err - } + newCandidate := aggCandidate.Copy() newCandidate.Path = nil diff --git a/pkg/yqlib/operator_delete.go b/pkg/yqlib/operator_delete.go index eb475da5..ea89aa29 100644 --- a/pkg/yqlib/operator_delete.go +++ b/pkg/yqlib/operator_delete.go @@ -3,8 +3,6 @@ package yqlib import ( "container/list" "fmt" - - yaml "gopkg.in/yaml.v3" ) func deleteChildOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) { @@ -17,12 +15,12 @@ func deleteChildOperator(d *dataTreeNavigator, context Context, expressionNode * for el := nodesToDelete.MatchingNodes.Back(); el != nil; el = el.Prev() { candidate := el.Value.(*CandidateNode) - if candidate.Node.Kind == yaml.DocumentNode { + if candidate.Kind == DocumentNode { //need to delete this node from context. newResults := list.New() for item := context.MatchingNodes.Front(); item != nil; item = item.Next() { nodeInContext := item.Value.(*CandidateNode) - if nodeInContext.Node != candidate.Node { + if nodeInContext != candidate { newResults.PushBack(nodeInContext) } else { log.Info("Need to delete this %v", NodeToString(nodeInContext)) @@ -36,12 +34,12 @@ func deleteChildOperator(d *dataTreeNavigator, context Context, expressionNode * return context, nil } - parentNode := candidate.Parent.Node + parentNode := candidate.Parent childPath := candidate.Path[len(candidate.Path)-1] - if parentNode.Kind == yaml.MappingNode { + if parentNode.Kind == MappingNode { deleteFromMap(candidate.Parent, childPath) - } else if parentNode.Kind == yaml.SequenceNode { + } else if parentNode.Kind == SequenceNode { deleteFromArray(candidate.Parent, childPath) } else { return Context{}, fmt.Errorf("Cannot delete nodes from parent of tag %v", parentNode.Tag) @@ -52,19 +50,17 @@ func deleteChildOperator(d *dataTreeNavigator, context Context, expressionNode * func deleteFromMap(candidate *CandidateNode, childPath interface{}) { log.Debug("deleteFromMap") - node := unwrapDoc(candidate.Node) + node := candidate.unwrapDocument() contents := node.Content - newContents := make([]*yaml.Node, 0) + newContents := make([]*CandidateNode, 0) for index := 0; index < len(contents); index = index + 2 { key := contents[index] value := contents[index+1] - childCandidate := candidate.CreateChildInMap(key, value) - shouldDelete := key.Value == childPath - log.Debugf("shouldDelete %v ? %v", childCandidate.GetKey(), shouldDelete) + log.Debugf("shouldDelete %v ? %v", value.GetKey(), shouldDelete) if !shouldDelete { newContents = append(newContents, key, value) @@ -75,9 +71,9 @@ func deleteFromMap(candidate *CandidateNode, childPath interface{}) { func deleteFromArray(candidate *CandidateNode, childPath interface{}) { log.Debug("deleteFromArray") - node := unwrapDoc(candidate.Node) + node := candidate.unwrapDocument() contents := node.Content - newContents := make([]*yaml.Node, 0) + newContents := make([]*CandidateNode, 0) for index := 0; index < len(contents); index = index + 1 { value := contents[index] diff --git a/pkg/yqlib/operator_document_index.go b/pkg/yqlib/operator_document_index.go index 566fe9df..42597759 100644 --- a/pkg/yqlib/operator_document_index.go +++ b/pkg/yqlib/operator_document_index.go @@ -3,8 +3,6 @@ package yqlib import ( "container/list" "fmt" - - "gopkg.in/yaml.v3" ) func getDocumentIndexOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) { @@ -12,8 +10,7 @@ func getDocumentIndexOperator(d *dataTreeNavigator, context Context, expressionN for el := context.MatchingNodes.Front(); el != nil; el = el.Next() { candidate := el.Value.(*CandidateNode) - node := &yaml.Node{Kind: yaml.ScalarNode, Value: fmt.Sprintf("%v", candidate.Document), Tag: "!!int"} - scalar := candidate.CreateReplacement(node) + scalar := candidate.CreateReplacement(ScalarNode, "!!int", fmt.Sprintf("%v", candidate.Document)) results.PushBack(scalar) } return context.ChildContext(results), nil diff --git a/pkg/yqlib/operator_encoder_decoder.go b/pkg/yqlib/operator_encoder_decoder.go index 877a0902..3e8d8149 100644 --- a/pkg/yqlib/operator_encoder_decoder.go +++ b/pkg/yqlib/operator_encoder_decoder.go @@ -7,8 +7,6 @@ import ( "errors" "regexp" "strings" - - "gopkg.in/yaml.v3" ) func configureEncoder(format PrinterOutputFormat, indent int) Encoder { @@ -78,7 +76,7 @@ func encodeOperator(d *dataTreeNavigator, context Context, expressionNode *Expre if originalList != nil && originalList.Len() > 0 && hasOnlyOneNewLine.MatchString(stringValue) { original := originalList.Front().Value.(*CandidateNode) - originalNode := unwrapDoc(original.Node) + originalNode := original.unwrapDocument() // original block did not have a newline at the end, get rid of this one too if !endWithNewLine.MatchString(originalNode.Value) { stringValue = chomper.ReplaceAllString(stringValue, "") @@ -92,8 +90,7 @@ func encodeOperator(d *dataTreeNavigator, context Context, expressionNode *Expre stringValue = chomper.ReplaceAllString(stringValue, "") } - stringContentNode := &yaml.Node{Kind: yaml.ScalarNode, Tag: "!!str", Value: stringValue} - results.PushBack(candidate.CreateReplacement(stringContentNode)) + results.PushBack(candidate.CreateReplacement(ScalarNode, "!!str", stringValue)) } return context.ChildContext(results), nil } @@ -141,9 +138,9 @@ func decodeOperator(d *dataTreeNavigator, context Context, expressionNode *Expre context.SetVariable("decoded: "+candidate.GetKey(), candidate.AsList()) - log.Debugf("got: [%v]", candidate.Node.Value) + log.Debugf("got: [%v]", candidate.Value) - err := decoder.Init(strings.NewReader(unwrapDoc(candidate.Node).Value)) + err := decoder.Init(strings.NewReader(candidate.unwrapDocument().Value)) if err != nil { return Context{}, err } @@ -153,9 +150,15 @@ func decodeOperator(d *dataTreeNavigator, context Context, expressionNode *Expre return Context{}, errorReading } //first node is a doc - node := unwrapDoc(decodedNode.Node) + node := decodedNode.unwrapDocument() + node.Path = candidate.Path + node.Key = candidate.Key + node.Parent = candidate.Parent + node.Document = candidate.Document + node.FileIndex = candidate.FileIndex + node.Filename = candidate.Filename - results.PushBack(candidate.CreateReplacement(node)) + results.PushBack(node) } return context.ChildContext(results), nil } diff --git a/pkg/yqlib/operator_entries.go b/pkg/yqlib/operator_entries.go index 2af9fe94..dd246358 100644 --- a/pkg/yqlib/operator_entries.go +++ b/pkg/yqlib/operator_entries.go @@ -3,64 +3,60 @@ package yqlib import ( "container/list" "fmt" - - yaml "gopkg.in/yaml.v3" ) -func entrySeqFor(key *yaml.Node, value *yaml.Node) *yaml.Node { - var keyKey = &yaml.Node{Kind: yaml.ScalarNode, Tag: "!!str", Value: "key"} - var valueKey = &yaml.Node{Kind: yaml.ScalarNode, Tag: "!!str", Value: "value"} +func entrySeqFor(key *CandidateNode, value *CandidateNode) *CandidateNode { + var keyKey = &CandidateNode{Kind: ScalarNode, Tag: "!!str", Value: "key"} + var valueKey = &CandidateNode{Kind: ScalarNode, Tag: "!!str", Value: "value"} - return &yaml.Node{ - Kind: yaml.MappingNode, + return &CandidateNode{ + Kind: MappingNode, Tag: "!!map", - Content: []*yaml.Node{keyKey, key, valueKey, value}, + Content: []*CandidateNode{keyKey, key, valueKey, value}, } } func toEntriesFromMap(candidateNode *CandidateNode) *CandidateNode { - var sequence = &yaml.Node{Kind: yaml.SequenceNode, Tag: "!!seq"} - var entriesNode = candidateNode.CreateReplacementWithDocWrappers(sequence) + var sequence = candidateNode.CreateReplacementWithDocWrappers(SequenceNode, "!!seq", 0) - var contents = unwrapDoc(candidateNode.Node).Content + var contents = candidateNode.unwrapDocument().Content for index := 0; index < len(contents); index = index + 2 { key := contents[index] value := contents[index+1] sequence.Content = append(sequence.Content, entrySeqFor(key, value)) } - return entriesNode + return sequence } func toEntriesfromSeq(candidateNode *CandidateNode) *CandidateNode { - var sequence = &yaml.Node{Kind: yaml.SequenceNode, Tag: "!!seq"} - var entriesNode = candidateNode.CreateReplacementWithDocWrappers(sequence) + var sequence = candidateNode.CreateReplacementWithDocWrappers(SequenceNode, "!!seq", 0) - var contents = unwrapDoc(candidateNode.Node).Content + var contents = candidateNode.unwrapDocument().Content for index := 0; index < len(contents); index = index + 1 { - key := &yaml.Node{Kind: yaml.ScalarNode, Tag: "!!int", Value: fmt.Sprintf("%v", index)} + key := &CandidateNode{Kind: ScalarNode, Tag: "!!int", Value: fmt.Sprintf("%v", index)} value := contents[index] sequence.Content = append(sequence.Content, entrySeqFor(key, value)) } - return entriesNode + return sequence } func toEntriesOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) { var results = list.New() for el := context.MatchingNodes.Front(); el != nil; el = el.Next() { candidate := el.Value.(*CandidateNode) - candidateNode := unwrapDoc(candidate.Node) + candidateNode := candidate.unwrapDocument() switch candidateNode.Kind { - case yaml.MappingNode: + case MappingNode: results.PushBack(toEntriesFromMap(candidate)) - case yaml.SequenceNode: + case SequenceNode: results.PushBack(toEntriesfromSeq(candidate)) default: if candidateNode.Tag != "!!null" { - return Context{}, fmt.Errorf("%v has no keys", candidate.Node.Tag) + return Context{}, fmt.Errorf("%v has no keys", candidate.Tag) } } } @@ -68,9 +64,8 @@ func toEntriesOperator(d *dataTreeNavigator, context Context, expressionNode *Ex return context.ChildContext(results), nil } -func parseEntry(entry *yaml.Node, position int) (*yaml.Node, *yaml.Node, error) { +func parseEntry(candidateNode *CandidateNode, position int) (*CandidateNode, *CandidateNode, error) { prefs := traversePreferences{DontAutoCreate: true} - candidateNode := &CandidateNode{Node: entry} keyResults, err := traverseMap(Context{}, candidateNode, createStringScalarNode("key"), prefs, false) @@ -88,15 +83,14 @@ func parseEntry(entry *yaml.Node, position int) (*yaml.Node, *yaml.Node, error) return nil, nil, fmt.Errorf("expected to find one 'value' entry but found %v in position %v", valueResults.Len(), position) } - return keyResults.Front().Value.(*CandidateNode).Node, valueResults.Front().Value.(*CandidateNode).Node, nil + return keyResults.Front().Value.(*CandidateNode), valueResults.Front().Value.(*CandidateNode), nil } func fromEntries(candidateNode *CandidateNode) (*CandidateNode, error) { - var node = &yaml.Node{Kind: yaml.MappingNode, Tag: "!!map"} - var mapCandidateNode = candidateNode.CreateReplacementWithDocWrappers(node) + var node = candidateNode.CopyWithoutContent() - var contents = unwrapDoc(candidateNode.Node).Content + var contents = candidateNode.unwrapDocument().Content for index := 0; index < len(contents); index = index + 1 { key, value, err := parseEntry(contents[index], index) @@ -106,17 +100,17 @@ func fromEntries(candidateNode *CandidateNode) (*CandidateNode, error) { node.Content = append(node.Content, key, value) } - return mapCandidateNode, nil + return node, nil } func fromEntriesOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) { var results = list.New() for el := context.MatchingNodes.Front(); el != nil; el = el.Next() { candidate := el.Value.(*CandidateNode) - candidateNode := unwrapDoc(candidate.Node) + candidateNode := candidate.unwrapDocument() switch candidateNode.Kind { - case yaml.SequenceNode: + case SequenceNode: mapResult, err := fromEntries(candidate) if err != nil { return Context{}, err diff --git a/pkg/yqlib/operator_env.go b/pkg/yqlib/operator_env.go index ed3f51e2..c83499be 100644 --- a/pkg/yqlib/operator_env.go +++ b/pkg/yqlib/operator_env.go @@ -4,10 +4,8 @@ import ( "container/list" "fmt" "os" - "strings" parse "github.com/a8m/envsubst/parse" - yaml "gopkg.in/yaml.v3" ) type envOpPreferences struct { @@ -18,39 +16,37 @@ type envOpPreferences struct { } func envOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) { - envName := expressionNode.Operation.CandidateNode.Node.Value + envName := expressionNode.Operation.CandidateNode.Value log.Debug("EnvOperator, env name:", envName) rawValue := os.Getenv(envName) preferences := expressionNode.Operation.Preferences.(envOpPreferences) - var node *yaml.Node + var node *CandidateNode if preferences.StringValue { - node = &yaml.Node{ - Kind: yaml.ScalarNode, + node = &CandidateNode{ + Kind: ScalarNode, Tag: "!!str", Value: rawValue, } } else if rawValue == "" { return Context{}, fmt.Errorf("Value for env variable '%v' not provided in env()", envName) } else { - var dataBucket yaml.Node - decoder := yaml.NewDecoder(strings.NewReader(rawValue)) - errorReading := decoder.Decode(&dataBucket) - if errorReading != nil { - return Context{}, errorReading + decoder := NewYamlDecoder(ConfiguredYamlPreferences) + result, err := decoder.Decode() + + if err != nil { + return Context{}, err } - //first node is a doc - node = unwrapDoc(&dataBucket) + node = result.unwrapDocument() + } log.Debug("ENV tag", node.Tag) log.Debug("ENV value", node.Value) log.Debug("ENV Kind", node.Kind) - target := &CandidateNode{Node: node} - - return context.SingleChildContext(target), nil + return context.SingleChildContext(node), nil } func envsubstOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) { @@ -71,7 +67,7 @@ func envsubstOperator(d *dataTreeNavigator, context Context, expressionNode *Exp for el := context.MatchingNodes.Front(); el != nil; el = el.Next() { candidate := el.Value.(*CandidateNode) - node := unwrapDoc(candidate.Node) + node := candidate.unwrapDocument() if node.Tag != "!!str" { log.Warning("EnvSubstOperator, env name:", node.Tag, node.Value) return Context{}, fmt.Errorf("cannot substitute with %v, can only substitute strings. Hint: Most often you'll want to use '|=' over '=' for this operation", node.Tag) @@ -81,8 +77,7 @@ func envsubstOperator(d *dataTreeNavigator, context Context, expressionNode *Exp if err != nil { return Context{}, err } - targetNode := &yaml.Node{Kind: yaml.ScalarNode, Value: value, Tag: "!!str"} - result := candidate.CreateReplacement(targetNode) + result := candidate.CreateReplacement(ScalarNode, "!!str", value) results.PushBack(result) } diff --git a/pkg/yqlib/operator_file.go b/pkg/yqlib/operator_file.go index c0ffaad8..118da5ae 100644 --- a/pkg/yqlib/operator_file.go +++ b/pkg/yqlib/operator_file.go @@ -3,8 +3,6 @@ package yqlib import ( "container/list" "fmt" - - yaml "gopkg.in/yaml.v3" ) func getFilenameOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) { @@ -14,8 +12,7 @@ func getFilenameOperator(d *dataTreeNavigator, context Context, expressionNode * for el := context.MatchingNodes.Front(); el != nil; el = el.Next() { candidate := el.Value.(*CandidateNode) - node := &yaml.Node{Kind: yaml.ScalarNode, Value: candidate.Filename, Tag: "!!str"} - result := candidate.CreateReplacement(node) + result := candidate.CreateReplacement(ScalarNode, "!!str", candidate.Filename) results.PushBack(result) } @@ -29,8 +26,7 @@ func getFileIndexOperator(d *dataTreeNavigator, context Context, expressionNode for el := context.MatchingNodes.Front(); el != nil; el = el.Next() { candidate := el.Value.(*CandidateNode) - node := &yaml.Node{Kind: yaml.ScalarNode, Value: fmt.Sprintf("%v", candidate.FileIndex), Tag: "!!int"} - result := candidate.CreateReplacement(node) + result := candidate.CreateReplacement(ScalarNode, "!!int", fmt.Sprintf("%v", candidate.FileIndex)) results.PushBack(result) } diff --git a/pkg/yqlib/operator_load.go b/pkg/yqlib/operator_load.go index 678854f6..d24bba90 100644 --- a/pkg/yqlib/operator_load.go +++ b/pkg/yqlib/operator_load.go @@ -5,8 +5,6 @@ import ( "container/list" "fmt" "os" - - "gopkg.in/yaml.v3" ) var LoadYamlPreferences = YamlPreferences{ @@ -30,7 +28,7 @@ func loadString(filename string) (*CandidateNode, error) { return nil, err } - return &CandidateNode{Node: &yaml.Node{Kind: yaml.ScalarNode, Tag: "!!str", Value: string(filebytes)}}, nil + return &CandidateNode{Kind: ScalarNode, Tag: "!!str", Value: string(filebytes)}, nil } func loadYaml(filename string, decoder Decoder) (*CandidateNode, error) { @@ -51,15 +49,15 @@ func loadYaml(filename string, decoder Decoder) (*CandidateNode, error) { if documents.Len() == 0 { // return null candidate - return &CandidateNode{Node: &yaml.Node{Kind: yaml.ScalarNode, Tag: "!!null"}}, nil + return &CandidateNode{Kind: ScalarNode, Tag: "!!null"}, nil } else if documents.Len() == 1 { candidate := documents.Front().Value.(*CandidateNode) return candidate, nil } else { - sequenceNode := &CandidateNode{Node: &yaml.Node{Kind: yaml.SequenceNode}} + sequenceNode := &CandidateNode{Kind: SequenceNode} for doc := documents.Front(); doc != nil; doc = doc.Next() { - sequenceNode.Node.Content = append(sequenceNode.Node.Content, unwrapDoc(doc.Value.(*CandidateNode).Node)) + sequenceNode.Content = append(sequenceNode.Content, doc.Value.(*CandidateNode).unwrapDocument()) } return sequenceNode, nil } @@ -87,7 +85,7 @@ func loadYamlOperator(d *dataTreeNavigator, context Context, expressionNode *Exp } nameCandidateNode := rhs.MatchingNodes.Front().Value.(*CandidateNode) - filename := nameCandidateNode.Node.Value + filename := nameCandidateNode.Value var contentsCandidate *CandidateNode diff --git a/pkg/yqlib/operator_path.go b/pkg/yqlib/operator_path.go index cdad7f1b..c956f353 100644 --- a/pkg/yqlib/operator_path.go +++ b/pkg/yqlib/operator_path.go @@ -3,21 +3,19 @@ package yqlib import ( "container/list" "fmt" - - yaml "gopkg.in/yaml.v3" ) -func createPathNodeFor(pathElement interface{}) *yaml.Node { +func createPathNodeFor(pathElement interface{}) *CandidateNode { switch pathElement := pathElement.(type) { case string: - return &yaml.Node{Kind: yaml.ScalarNode, Value: pathElement, Tag: "!!str"} + return &CandidateNode{Kind: ScalarNode, Value: pathElement, Tag: "!!str"} default: - return &yaml.Node{Kind: yaml.ScalarNode, Value: fmt.Sprintf("%v", pathElement), Tag: "!!int"} + return &CandidateNode{Kind: ScalarNode, Value: fmt.Sprintf("%v", pathElement), Tag: "!!int"} } } -func getPathArrayFromNode(funcName string, node *yaml.Node) ([]interface{}, error) { - if node.Kind != yaml.SequenceNode { +func getPathArrayFromNode(funcName string, node *CandidateNode) ([]interface{}, error) { + if node.Kind != SequenceNode { return nil, fmt.Errorf("%v: expected path array, but got %v instead", funcName, node.Tag) } @@ -59,7 +57,7 @@ func setPathOperator(d *dataTreeNavigator, context Context, expressionNode *Expr } lhsValue := lhsPathContext.MatchingNodes.Front().Value.(*CandidateNode) - lhsPath, err := getPathArrayFromNode("SETPATH", lhsValue.Node) + lhsPath, err := getPathArrayFromNode("SETPATH", lhsValue) if err != nil { return Context{}, err @@ -110,7 +108,7 @@ func delPathsOperator(d *dataTreeNavigator, context Context, expressionNode *Exp if pathArraysContext.MatchingNodes.Len() != 1 { return Context{}, fmt.Errorf("DELPATHS: expected single value but found %v", pathArraysContext.MatchingNodes.Len()) } - pathArraysNode := pathArraysContext.MatchingNodes.Front().Value.(*CandidateNode).Node + pathArraysNode := pathArraysContext.MatchingNodes.Front().Value.(*CandidateNode) if pathArraysNode.Tag != "!!seq" { return Context{}, fmt.Errorf("DELPATHS: expected a sequence of sequences, but found %v", pathArraysNode.Tag) @@ -156,16 +154,15 @@ func getPathOperator(d *dataTreeNavigator, context Context, expressionNode *Expr for el := context.MatchingNodes.Front(); el != nil; el = el.Next() { candidate := el.Value.(*CandidateNode) - node := &yaml.Node{Kind: yaml.SequenceNode, Tag: "!!seq"} + node := candidate.CreateReplacement(SequenceNode, "!!seq", "") - content := make([]*yaml.Node, len(candidate.Path)) + content := make([]*CandidateNode, len(candidate.Path)) for pathIndex := 0; pathIndex < len(candidate.Path); pathIndex++ { path := candidate.Path[pathIndex] content[pathIndex] = createPathNodeFor(path) } node.Content = content - result := candidate.CreateReplacement(node) - results.PushBack(result) + results.PushBack(node) } return context.ChildContext(results), nil diff --git a/pkg/yqlib/operator_reverse.go b/pkg/yqlib/operator_reverse.go index 1693308f..2ea97c5f 100644 --- a/pkg/yqlib/operator_reverse.go +++ b/pkg/yqlib/operator_reverse.go @@ -3,8 +3,6 @@ package yqlib import ( "container/list" "fmt" - - yaml "gopkg.in/yaml.v3" ) func reverseOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) { @@ -13,19 +11,19 @@ func reverseOperator(d *dataTreeNavigator, context Context, expressionNode *Expr for el := context.MatchingNodes.Front(); el != nil; el = el.Next() { candidate := el.Value.(*CandidateNode) - candidateNode := unwrapDoc(candidate.Node) + candidateNode := candidate.unwrapDocument() - if candidateNode.Kind != yaml.SequenceNode { + if candidateNode.Kind != SequenceNode { return context, fmt.Errorf("node at path [%v] is not an array (it's a %v)", candidate.GetNicePath(), candidate.GetNiceTag()) } - reverseList := &yaml.Node{Kind: yaml.SequenceNode, Tag: "!!seq", Style: candidateNode.Style} - reverseList.Content = make([]*yaml.Node, len(candidateNode.Content)) + reverseList := candidate.CreateReplacementWithDocWrappers(SequenceNode, "!!tag", candidateNode.Style) + reverseList.Content = make([]*CandidateNode, len(candidateNode.Content)) for i, originalNode := range candidateNode.Content { reverseList.Content[len(candidateNode.Content)-i-1] = originalNode } - results.PushBack(candidate.CreateReplacementWithDocWrappers(reverseList)) + results.PushBack(reverseList) } diff --git a/pkg/yqlib/operator_select.go b/pkg/yqlib/operator_select.go index 57b9e2ce..dc2358bf 100644 --- a/pkg/yqlib/operator_select.go +++ b/pkg/yqlib/operator_select.go @@ -23,7 +23,7 @@ func selectOperator(d *dataTreeNavigator, context Context, expressionNode *Expre for resultEl := rhs.MatchingNodes.Front(); resultEl != nil; resultEl = resultEl.Next() { result := resultEl.Value.(*CandidateNode) - includeResult, errDecoding = isTruthy(result) + includeResult, errDecoding = isTruthyNode(result) log.Debugf("isTruthy %v", includeResult) if errDecoding != nil { return Context{}, errDecoding diff --git a/pkg/yqlib/operator_sort.go b/pkg/yqlib/operator_sort.go index 01070f2d..8ba7e2e1 100644 --- a/pkg/yqlib/operator_sort.go +++ b/pkg/yqlib/operator_sort.go @@ -7,8 +7,6 @@ import ( "strconv" "strings" "time" - - yaml "gopkg.in/yaml.v3" ) func sortOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) { @@ -26,9 +24,9 @@ func sortByOperator(d *dataTreeNavigator, context Context, expressionNode *Expre for el := context.MatchingNodes.Front(); el != nil; el = el.Next() { candidate := el.Value.(*CandidateNode) - candidateNode := unwrapDoc(candidate.Node) + candidateNode := candidate.unwrapDocument() - if candidateNode.Kind != yaml.SequenceNode { + if candidateNode.Kind != SequenceNode { return context, fmt.Errorf("node at path [%v] is not an array (it's a %v)", candidate.GetNicePath(), candidate.GetNiceTag()) } @@ -36,8 +34,7 @@ func sortByOperator(d *dataTreeNavigator, context Context, expressionNode *Expre for i, originalNode := range candidateNode.Content { - childCandidate := candidate.CreateChildInArray(i, originalNode) - compareContext, err := d.GetMatchingNodes(context.SingleReadonlyChildContext(childCandidate), expressionNode.RHS) + compareContext, err := d.GetMatchingNodes(context.SingleReadonlyChildContext(originalNode), expressionNode.RHS) if err != nil { return Context{}, err } @@ -48,19 +45,20 @@ func sortByOperator(d *dataTreeNavigator, context Context, expressionNode *Expre sort.Stable(sortableArray) - sortedList := &yaml.Node{Kind: yaml.SequenceNode, Tag: "!!seq", Style: candidateNode.Style} - sortedList.Content = make([]*yaml.Node, len(candidateNode.Content)) + sortedList := candidate.CreateReplacementWithDocWrappers(SequenceNode, "!!seq", candidateNode.Style) + + sortedList.Content = make([]*CandidateNode, len(candidateNode.Content)) for i, sortedNode := range sortableArray { sortedList.Content[i] = sortedNode.Node } - results.PushBack(candidate.CreateReplacementWithDocWrappers(sortedList)) + results.PushBack(sortedList) } return context.ChildContext(results), nil } type sortableNode struct { - Node *yaml.Node + Node *CandidateNode CompareContext Context dateTimeLayout string } @@ -79,7 +77,7 @@ func (a sortableNodeArray) Less(i, j int) bool { lhs := lhsEl.Value.(*CandidateNode) rhs := rhsEl.Value.(*CandidateNode) - result := a.compare(lhs.Node, rhs.Node, a[i].dateTimeLayout) + result := a.compare(lhs, rhs, a[i].dateTimeLayout) if result < 0 { return true @@ -92,18 +90,18 @@ func (a sortableNodeArray) Less(i, j int) bool { return false } -func (a sortableNodeArray) compare(lhs *yaml.Node, rhs *yaml.Node, dateTimeLayout string) int { +func (a sortableNodeArray) compare(lhs *CandidateNode, rhs *CandidateNode, dateTimeLayout string) int { lhsTag := lhs.Tag rhsTag := rhs.Tag if !strings.HasPrefix(lhsTag, "!!") { // custom tag - we have to have a guess - lhsTag = guessTagFromCustomType(lhs) + lhsTag = lhs.guessTagFromCustomType() } if !strings.HasPrefix(rhsTag, "!!") { // custom tag - we have to have a guess - rhsTag = guessTagFromCustomType(rhs) + rhsTag = rhs.guessTagFromCustomType() } isDateTime := lhsTag == "!!timestamp" && rhsTag == "!!timestamp" diff --git a/pkg/yqlib/operator_style.go b/pkg/yqlib/operator_style.go index ed7f6549..f4e354bf 100644 --- a/pkg/yqlib/operator_style.go +++ b/pkg/yqlib/operator_style.go @@ -3,23 +3,21 @@ package yqlib import ( "container/list" "fmt" - - yaml "gopkg.in/yaml.v3" ) -func parseStyle(customStyle string) (yaml.Style, error) { +func parseStyle(customStyle string) (Style, error) { if customStyle == "tagged" { - return yaml.TaggedStyle, nil + return TaggedStyle, nil } else if customStyle == "double" { - return yaml.DoubleQuotedStyle, nil + return DoubleQuotedStyle, nil } else if customStyle == "single" { - return yaml.SingleQuotedStyle, nil + return SingleQuotedStyle, nil } else if customStyle == "literal" { - return yaml.LiteralStyle, nil + return LiteralStyle, nil } else if customStyle == "folded" { - return yaml.FoldedStyle, nil + return FoldedStyle, nil } else if customStyle == "flow" { - return yaml.FlowStyle, nil + return FlowStyle, nil } else if customStyle != "" { return 0, fmt.Errorf("Unknown style %v", customStyle) } @@ -29,7 +27,7 @@ func parseStyle(customStyle string) (yaml.Style, error) { func assignStyleOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) { log.Debugf("AssignStyleOperator: %v") - var style yaml.Style + var style Style if !expressionNode.Operation.UpdateAssign { rhs, err := d.GetMatchingNodes(context.ReadOnlyClone(), expressionNode.RHS) if err != nil { @@ -37,7 +35,7 @@ func assignStyleOperator(d *dataTreeNavigator, context Context, expressionNode * } if rhs.MatchingNodes.Front() != nil { - style, err = parseStyle(rhs.MatchingNodes.Front().Value.(*CandidateNode).Node.Value) + style, err = parseStyle(rhs.MatchingNodes.Front().Value.(*CandidateNode).Value) if err != nil { return Context{}, err } @@ -60,14 +58,14 @@ func assignStyleOperator(d *dataTreeNavigator, context Context, expressionNode * } if rhs.MatchingNodes.Front() != nil { - style, err = parseStyle(rhs.MatchingNodes.Front().Value.(*CandidateNode).Node.Value) + style, err = parseStyle(rhs.MatchingNodes.Front().Value.(*CandidateNode).Value) if err != nil { return Context{}, err } } } - candidate.Node.Style = style + candidate.Style = style } return context, nil @@ -81,26 +79,25 @@ func getStyleOperator(d *dataTreeNavigator, context Context, expressionNode *Exp for el := context.MatchingNodes.Front(); el != nil; el = el.Next() { candidate := el.Value.(*CandidateNode) var style string - switch candidate.Node.Style { - case yaml.TaggedStyle: + switch candidate.Style { + case TaggedStyle: style = "tagged" - case yaml.DoubleQuotedStyle: + case DoubleQuotedStyle: style = "double" - case yaml.SingleQuotedStyle: + case SingleQuotedStyle: style = "single" - case yaml.LiteralStyle: + case LiteralStyle: style = "literal" - case yaml.FoldedStyle: + case FoldedStyle: style = "folded" - case yaml.FlowStyle: + case FlowStyle: style = "flow" case 0: style = "" default: style = "" } - node := &yaml.Node{Kind: yaml.ScalarNode, Value: style, Tag: "!!str"} - result := candidate.CreateReplacement(node) + result := candidate.CreateReplacement(ScalarNode, "!!str", style) results.PushBack(result) } diff --git a/pkg/yqlib/operator_tag.go b/pkg/yqlib/operator_tag.go index 59b07d89..fff3c888 100644 --- a/pkg/yqlib/operator_tag.go +++ b/pkg/yqlib/operator_tag.go @@ -2,8 +2,6 @@ package yqlib import ( "container/list" - - yaml "gopkg.in/yaml.v3" ) func assignTagOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) { @@ -18,7 +16,7 @@ func assignTagOperator(d *dataTreeNavigator, context Context, expressionNode *Ex } if rhs.MatchingNodes.Front() != nil { - tag = rhs.MatchingNodes.Front().Value.(*CandidateNode).Node.Value + tag = rhs.MatchingNodes.Front().Value.(*CandidateNode).Value } } @@ -38,10 +36,10 @@ func assignTagOperator(d *dataTreeNavigator, context Context, expressionNode *Ex } if rhs.MatchingNodes.Front() != nil { - tag = rhs.MatchingNodes.Front().Value.(*CandidateNode).Node.Value + tag = rhs.MatchingNodes.Front().Value.(*CandidateNode).Value } } - unwrapDoc(candidate.Node).Tag = tag + candidate.unwrapDocument().Tag = tag } return context, nil @@ -54,8 +52,7 @@ func getTagOperator(d *dataTreeNavigator, context Context, expressionNode *Expre for el := context.MatchingNodes.Front(); el != nil; el = el.Next() { candidate := el.Value.(*CandidateNode) - node := &yaml.Node{Kind: yaml.ScalarNode, Value: unwrapDoc(candidate.Node).Tag, Tag: "!!str"} - result := candidate.CreateReplacement(node) + result := candidate.CreateReplacement(ScalarNode, "!!str", candidate.unwrapDocument().Tag) results.PushBack(result) } diff --git a/pkg/yqlib/operator_unique.go b/pkg/yqlib/operator_unique.go index 1a821538..6c8c0c67 100644 --- a/pkg/yqlib/operator_unique.go +++ b/pkg/yqlib/operator_unique.go @@ -49,7 +49,7 @@ func uniqueBy(d *dataTreeNavigator, context Context, expressionNode *ExpressionN newMatches.Set(keyValue, child) } } - resultNode := candidate.CreateReplacementWithDocWrappers(SequenceNode, "!!seq", "") + resultNode := candidate.CreateReplacementWithDocWrappers(SequenceNode, "!!seq", candidateNode.Style) for el := newMatches.Front(); el != nil; el = el.Next() { resultNode.Content = append(resultNode.Content, el.Value.(*CandidateNode)) } diff --git a/pkg/yqlib/operator_value.go b/pkg/yqlib/operator_value.go index b4296acc..740893af 100644 --- a/pkg/yqlib/operator_value.go +++ b/pkg/yqlib/operator_value.go @@ -7,22 +7,16 @@ func referenceOperator(d *dataTreeNavigator, context Context, expressionNode *Ex } func valueOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) { - log.Debug("value = %v", expressionNode.Operation.CandidateNode.Node.Value) + log.Debug("value = %v", expressionNode.Operation.CandidateNode.Value) if context.MatchingNodes.Len() == 0 { - clone, err := expressionNode.Operation.CandidateNode.Copy() - if err != nil { - return Context{}, err - } + clone := expressionNode.Operation.CandidateNode.Copy() return context.SingleChildContext(clone), nil } var results = list.New() for el := context.MatchingNodes.Front(); el != nil; el = el.Next() { - clone, err := expressionNode.Operation.CandidateNode.Copy() - if err != nil { - return Context{}, err - } + clone := expressionNode.Operation.CandidateNode.Copy() results.PushBack(clone) }