yq/pkg/yqlib/string_evaluator.go

74 lines
1.6 KiB
Go

package yqlib
import (
"bufio"
"bytes"
"container/list"
"errors"
"fmt"
"io"
"strings"
)
type StringEvaluator interface {
Evaluate(expression string, input string, encoder Encoder, decoder Decoder) (string, error)
}
type stringEvaluator struct {
treeNavigator DataTreeNavigator
fileIndex int
}
func NewStringEvaluator() StringEvaluator {
return &stringEvaluator{
treeNavigator: NewDataTreeNavigator(),
}
}
func (s *stringEvaluator) Evaluate(expression string, input string, encoder Encoder, decoder Decoder) (string, error) {
// Use bytes.Buffer for output of string
out := new(bytes.Buffer)
printer := NewPrinter(encoder, NewSinglePrinterWriter(out))
InitExpressionParser()
node, err := ExpressionParser.ParseExpression(expression)
if err != nil {
return "", err
}
reader := bufio.NewReader(strings.NewReader(input))
var currentIndex uint
err = decoder.Init(reader)
if err != nil {
return "", err
}
for {
candidateNode, errorReading := decoder.Decode()
if errors.Is(errorReading, io.EOF) {
s.fileIndex = s.fileIndex + 1
return out.String(), nil
} else if errorReading != nil {
return "", fmt.Errorf("bad input '%v': %w", input, errorReading)
}
candidateNode.document = currentIndex
candidateNode.fileIndex = s.fileIndex
inputList := list.New()
inputList.PushBack(candidateNode)
result, errorParsing := s.treeNavigator.GetMatchingNodes(Context{MatchingNodes: inputList}, node)
if errorParsing != nil {
return "", errorParsing
}
err = printer.PrintResults(result.MatchingNodes)
if err != nil {
return "", err
}
currentIndex = currentIndex + 1
}
}