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" "bufio"
"bytes" "bytes"
"container/list" "container/list"
"errors"
"fmt"
"io"
"strings" "strings"
) )
type StringEvaluator interface { type StringEvaluator interface {
Evaluate(expression string, input string, encoder Encoder, decoder Decoder) (string, error) 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 { type stringEvaluator struct {
treeNavigator DataTreeNavigator treeNavigator DataTreeNavigator
fileIndex int
} }
func NewStringEvaluator() StringEvaluator { 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) { func (s *stringEvaluator) Evaluate(expression string, input string, encoder Encoder, decoder Decoder) (string, error) {
// Use bytes.Buffer for output of string // 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)) reader := bufio.NewReader(strings.NewReader(input))
evaluator := NewStreamEvaluator()
var currentIndex uint if _, err := evaluator.Evaluate("", reader, node, printer, decoder); err != nil {
err = decoder.Init(reader)
if err != nil {
return "", err return "", err
} }
for { return out.String(), nil
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
}
} }

View File

@ -6,6 +6,20 @@ import (
"github.com/mikefarah/yq/v4/test" "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) { func TestStringEvaluator_Evaluate_Nominal(t *testing.T) {
expected_output := `` + expected_output := `` +
`yq` + "\n" + `yq` + "\n" +
@ -24,7 +38,7 @@ func TestStringEvaluator_Evaluate_Nominal(t *testing.T) {
result, err := NewStringEvaluator().Evaluate(expression, input, encoder, decoder) result, err := NewStringEvaluator().Evaluate(expression, input, encoder, decoder)
if err != nil { if err != nil {
t.Error(err) 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 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) { func readDocuments(reader io.Reader, filename string, fileIndex int, decoder Decoder) (*list.List, error) {
err := decoder.Init(reader) err := decoder.Init(reader)
if err != nil { if err != nil {