mirror of
https://github.com/mikefarah/yq.git
synced 2024-12-19 20:19:04 +00:00
75 lines
1.8 KiB
Go
75 lines
1.8 KiB
Go
package yqlib
|
|
|
|
import (
|
|
"encoding/csv"
|
|
"errors"
|
|
"io"
|
|
|
|
"github.com/dimchansky/utfbom"
|
|
)
|
|
|
|
type csvObjectDecoder struct {
|
|
prefs CsvPreferences
|
|
reader csv.Reader
|
|
finished bool
|
|
}
|
|
|
|
func NewCSVObjectDecoder(prefs CsvPreferences) Decoder {
|
|
return &csvObjectDecoder{prefs: prefs}
|
|
}
|
|
|
|
func (dec *csvObjectDecoder) Init(reader io.Reader) error {
|
|
cleanReader, enc := utfbom.Skip(reader)
|
|
log.Debugf("Detected encoding: %s\n", enc)
|
|
dec.reader = *csv.NewReader(cleanReader)
|
|
dec.reader.Comma = dec.prefs.Separator
|
|
dec.finished = false
|
|
return nil
|
|
}
|
|
|
|
func (dec *csvObjectDecoder) convertToNode(content string) *CandidateNode {
|
|
node, err := parseSnippet(content)
|
|
// if we're not auto-parsing, then we wont put in parsed objects or arrays
|
|
// but we still parse scalars
|
|
if err != nil || (!dec.prefs.AutoParse && node.Kind != ScalarNode) {
|
|
return CreateScalarNode(content, content)
|
|
}
|
|
return node
|
|
}
|
|
|
|
func (dec *csvObjectDecoder) createObject(headerRow []string, contentRow []string) *CandidateNode {
|
|
objectNode := &CandidateNode{Kind: MappingNode, Tag: "!!map"}
|
|
|
|
for i, header := range headerRow {
|
|
objectNode.AddKeyValueChild(CreateScalarNode(header, header), dec.convertToNode(contentRow[i]))
|
|
}
|
|
return objectNode
|
|
}
|
|
|
|
func (dec *csvObjectDecoder) Decode() (*CandidateNode, error) {
|
|
if dec.finished {
|
|
return nil, io.EOF
|
|
}
|
|
headerRow, err := dec.reader.Read()
|
|
log.Debugf(": headerRow%v", headerRow)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
rootArray := &CandidateNode{Kind: SequenceNode, Tag: "!!seq"}
|
|
|
|
contentRow, err := dec.reader.Read()
|
|
|
|
for err == nil && len(contentRow) > 0 {
|
|
log.Debugf("Adding contentRow: %v", contentRow)
|
|
rootArray.AddChild(dec.createObject(headerRow, contentRow))
|
|
contentRow, err = dec.reader.Read()
|
|
log.Debugf("Read next contentRow: %v, %v", contentRow, err)
|
|
}
|
|
if !errors.Is(err, io.EOF) {
|
|
return nil, err
|
|
}
|
|
|
|
return rootArray, nil
|
|
}
|