-
-
Notifications
You must be signed in to change notification settings - Fork 551
/
operator_load.go
129 lines (98 loc) · 3.41 KB
/
operator_load.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
package yqlib
import (
"bufio"
"container/list"
"fmt"
"os"
)
var LoadYamlPreferences = YamlPreferences{
LeadingContentPreProcessing: false,
PrintDocSeparators: true,
UnwrapScalar: true,
EvaluateTogether: false,
}
type loadPrefs struct {
decoder Decoder
}
func loadString(filename string) (*CandidateNode, error) {
// ignore CWE-22 gosec issue - that's more targeted for http based apps that run in a public directory,
// and ensuring that it's not possible to give a path to a file outside that directory.
filebytes, err := os.ReadFile(filename) // #nosec
if err != nil {
return nil, err
}
return &CandidateNode{Kind: ScalarNode, Tag: "!!str", Value: string(filebytes)}, nil
}
func loadWithDecoder(filename string, decoder Decoder) (*CandidateNode, error) {
if decoder == nil {
return nil, fmt.Errorf("could not load %s", filename)
}
file, err := os.Open(filename) // #nosec
if err != nil {
return nil, err
}
reader := bufio.NewReader(file)
documents, err := readDocuments(reader, filename, 0, decoder)
if err != nil {
return nil, err
}
if documents.Len() == 0 {
// return null candidate
return &CandidateNode{Kind: ScalarNode, Tag: "!!null"}, nil
} else if documents.Len() == 1 {
candidate := documents.Front().Value.(*CandidateNode)
return candidate, nil
}
sequenceNode := &CandidateNode{Kind: SequenceNode}
for doc := documents.Front(); doc != nil; doc = doc.Next() {
sequenceNode.AddChild(doc.Value.(*CandidateNode))
}
return sequenceNode, nil
}
func loadStringOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
log.Debugf("loadString")
var results = list.New()
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
candidate := el.Value.(*CandidateNode)
rhs, err := d.GetMatchingNodes(context.SingleReadonlyChildContext(candidate), expressionNode.RHS)
if err != nil {
return Context{}, err
}
if rhs.MatchingNodes.Front() == nil {
return Context{}, fmt.Errorf("filename expression returned nil")
}
nameCandidateNode := rhs.MatchingNodes.Front().Value.(*CandidateNode)
filename := nameCandidateNode.Value
contentsCandidate, err := loadString(filename)
if err != nil {
return Context{}, fmt.Errorf("Failed to load %v: %w", filename, err)
}
results.PushBack(contentsCandidate)
}
return context.ChildContext(results), nil
}
func loadOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
log.Debugf("loadOperator")
loadPrefs := expressionNode.Operation.Preferences.(loadPrefs)
// need to evaluate the 1st parameter against the context
// and return the data accordingly.
var results = list.New()
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
candidate := el.Value.(*CandidateNode)
rhs, err := d.GetMatchingNodes(context.SingleReadonlyChildContext(candidate), expressionNode.RHS)
if err != nil {
return Context{}, err
}
if rhs.MatchingNodes.Front() == nil {
return Context{}, fmt.Errorf("filename expression returned nil")
}
nameCandidateNode := rhs.MatchingNodes.Front().Value.(*CandidateNode)
filename := nameCandidateNode.Value
contentsCandidate, err := loadWithDecoder(filename, loadPrefs.decoder)
if err != nil {
return Context{}, fmt.Errorf("Failed to load %v: %w", filename, err)
}
results.PushBack(contentsCandidate)
}
return context.ChildContext(results), nil
}