Adding a EvaluateAll function to StringEvaluator #1966

This commit is contained in:
Mike Farah 2024-03-07 12:02:40 +11:00
parent 93ed666000
commit b4463e29e8
3 changed files with 47 additions and 36 deletions

View File

@ -4,19 +4,16 @@ import (
"bufio"
"bytes"
"container/list"
"errors"
"fmt"
"io"
"strings"
)
type StringEvaluator interface {
Evaluate(expression string, input string, encoder Encoder, decoder Decoder) (string, error)
EvaluateAll(expression string, input string, encoder Encoder, decoder Decoder) (string, error)
}
type stringEvaluator struct {
treeNavigator DataTreeNavigator
fileIndex int
}
func NewStringEvaluator() StringEvaluator {
@ -25,6 +22,29 @@ func NewStringEvaluator() StringEvaluator {
}
}
func (s *stringEvaluator) EvaluateAll(expression string, input string, encoder Encoder, decoder Decoder) (string, error) {
reader := bufio.NewReader(strings.NewReader(input))
var documents *list.List
var results *list.List
var err error
if documents, err = ReadDocuments(reader, decoder); err != nil {
return "", err
}
evaluator := NewAllAtOnceEvaluator()
if results, err = evaluator.EvaluateCandidateNodes(expression, documents); err != nil {
return "", err
}
out := new(bytes.Buffer)
printer := NewPrinter(encoder, NewSinglePrinterWriter(out))
if err := printer.PrintResults(results); err != nil {
return "", err
}
return out.String(), nil
}
func (s *stringEvaluator) Evaluate(expression string, input string, encoder Encoder, decoder Decoder) (string, error) {
// Use bytes.Buffer for output of string
@ -38,36 +58,9 @@ func (s *stringEvaluator) Evaluate(expression string, input string, encoder Enco
}
reader := bufio.NewReader(strings.NewReader(input))
var currentIndex uint
err = decoder.Init(reader)
if err != nil {
evaluator := NewStreamEvaluator()
if _, err := evaluator.Evaluate("", reader, node, printer, decoder); 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
}
return out.String(), nil
}

View File

@ -6,6 +6,20 @@ import (
"github.com/mikefarah/yq/v4/test"
)
func TestStringEvaluator_MultipleDocumentMerge(t *testing.T) {
yamlString := "a: Hello\n---\na: Goodbye\n"
expected_output := "a: Goodbye\n"
encoder := NewYamlEncoder(ConfiguredYamlPreferences)
decoder := NewYamlDecoder(ConfiguredYamlPreferences)
result, err := NewStringEvaluator().EvaluateAll("select(di==0) * select(di==1)", yamlString, encoder, decoder)
if err != nil {
t.Error(err)
} else {
test.AssertResult(t, expected_output, result)
}
}
func TestStringEvaluator_Evaluate_Nominal(t *testing.T) {
expected_output := `` +
`yq` + "\n" +
@ -24,7 +38,7 @@ func TestStringEvaluator_Evaluate_Nominal(t *testing.T) {
result, err := NewStringEvaluator().Evaluate(expression, input, encoder, decoder)
if err != nil {
t.Error(err)
} else {
test.AssertResult(t, expected_output, result)
}
test.AssertResult(t, expected_output, result)
}

View File

@ -31,6 +31,10 @@ func writeString(writer io.Writer, txt string) error {
return errorWriting
}
func ReadDocuments(reader io.Reader, decoder Decoder) (*list.List, error) {
return readDocuments(reader, "", 0, decoder)
}
func readDocuments(reader io.Reader, filename string, fileIndex int, decoder Decoder) (*list.List, error) {
err := decoder.Init(reader)
if err != nil {