diff options
Diffstat (limited to '')
-rw-r--r-- | vendor/github.com/gocarina/gocsv/decode.go | 69 |
1 files changed, 51 insertions, 18 deletions
diff --git a/vendor/github.com/gocarina/gocsv/decode.go b/vendor/github.com/gocarina/gocsv/decode.go index a832e84..537251d 100644 --- a/vendor/github.com/gocarina/gocsv/decode.go +++ b/vendor/github.com/gocarina/gocsv/decode.go @@ -10,13 +10,13 @@ import ( // Decoder . type Decoder interface { - getCSVRows() ([][]string, error) + GetCSVRows() ([][]string, error) } // SimpleDecoder . type SimpleDecoder interface { - getCSVRow() ([]string, error) - getCSVRows() ([][]string, error) + GetCSVRow() ([]string, error) + GetCSVRows() ([][]string, error) } type CSVReader interface { @@ -32,6 +32,11 @@ func newSimpleDecoderFromReader(r io.Reader) SimpleDecoder { return csvDecoder{getCSVReader(r)} } +var ( + ErrEmptyCSVFile = errors.New("empty csv file given") + ErrNoStructTags = errors.New("no csv struct tags found") +) + // NewSimpleDecoderFromCSVReader creates a SimpleDecoder, which may be passed // to the UnmarshalDecoder* family of functions, from a CSV reader. Note that // encoding/csv.Reader implements CSVReader, so you can pass one of those @@ -40,11 +45,11 @@ func NewSimpleDecoderFromCSVReader(r CSVReader) SimpleDecoder { return csvDecoder{r} } -func (c csvDecoder) getCSVRows() ([][]string, error) { +func (c csvDecoder) GetCSVRows() ([][]string, error) { return c.ReadAll() } -func (c csvDecoder) getCSVRow() ([]string, error) { +func (c csvDecoder) GetCSVRow() ([]string, error) { return c.Read() } @@ -137,19 +142,19 @@ func readToWithErrorHandler(decoder Decoder, errHandler ErrorHandler, out interf if err := ensureOutInnerType(outInnerType); err != nil { return err } - csvRows, err := decoder.getCSVRows() // Get the CSV csvRows + csvRows, err := decoder.GetCSVRows() // Get the CSV csvRows if err != nil { return err } if len(csvRows) == 0 { - return errors.New("empty csv file given") + return ErrEmptyCSVFile } if err := ensureOutCapacity(&outValue, len(csvRows)); err != nil { // Ensure the container is big enough to hold the CSV content return err } outInnerStructInfo := getStructInfo(outInnerType) // Get the inner struct info to get CSV annotations if len(outInnerStructInfo.Fields) == 0 { - return errors.New("no csv struct tags found") + return ErrNoStructTags } headers := normalizeHeaders(csvRows[0]) @@ -203,8 +208,11 @@ func readToWithErrorHandler(decoder Decoder, errHandler ErrorHandler, out interf continue } } - - if err := setInnerField(&outInner, outInnerWasPointer, fieldInfo.IndexChain, csvColumnContent, fieldInfo.omitEmpty); err != nil { // Set field of struct + value := csvColumnContent + if value == "" { + value = fieldInfo.defaultValue + } + if err := setInnerField(&outInner, outInnerWasPointer, fieldInfo.IndexChain, value, fieldInfo.omitEmpty); err != nil { // Set field of struct parseError := csv.ParseError{ Line: i + 2, //add 2 to account for the header & 0-indexing of arrays Column: j + 1, @@ -234,7 +242,7 @@ func readEach(decoder SimpleDecoder, c interface{}) error { } defer outValue.Close() - headers, err := decoder.getCSVRow() + headers, err := decoder.GetCSVRow() if err != nil { return err } @@ -246,7 +254,7 @@ func readEach(decoder SimpleDecoder, c interface{}) error { } outInnerStructInfo := getStructInfo(outInnerType) // Get the inner struct info to get CSV annotations if len(outInnerStructInfo.Fields) == 0 { - return errors.New("no csv struct tags found") + return ErrNoStructTags } csvHeadersLabels := make(map[int]*fieldInfo, len(outInnerStructInfo.Fields)) // Used to store the correspondance header <-> position in CSV headerCount := map[string]int{} @@ -272,7 +280,7 @@ func readEach(decoder SimpleDecoder, c interface{}) error { } i := 0 for { - line, err := decoder.getCSVRow() + line, err := decoder.GetCSVRow() if err == io.EOF { break } else if err != nil { @@ -309,12 +317,12 @@ func readEachWithoutHeaders(decoder SimpleDecoder, c interface{}) error { } outInnerStructInfo := getStructInfo(outInnerType) // Get the inner struct info to get CSV annotations if len(outInnerStructInfo.Fields) == 0 { - return errors.New("no csv struct tags found") + return ErrNoStructTags } i := 0 for { - line, err := decoder.getCSVRow() + line, err := decoder.GetCSVRow() if err == io.EOF { break } else if err != nil { @@ -346,19 +354,19 @@ func readToWithoutHeaders(decoder Decoder, out interface{}) error { if err := ensureOutInnerType(outInnerType); err != nil { return err } - csvRows, err := decoder.getCSVRows() // Get the CSV csvRows + csvRows, err := decoder.GetCSVRows() // Get the CSV csvRows if err != nil { return err } if len(csvRows) == 0 { - return errors.New("empty csv file given") + return ErrEmptyCSVFile } if err := ensureOutCapacity(&outValue, len(csvRows)+1); err != nil { // Ensure the container is big enough to hold the CSV content return err } outInnerStructInfo := getStructInfo(outInnerType) // Get the inner struct info to get CSV annotations if len(outInnerStructInfo.Fields) == 0 { - return errors.New("no csv struct tags found") + return ErrNoStructTags } for i, csvRow := range csvRows { @@ -446,6 +454,31 @@ func setInnerField(outInner *reflect.Value, outInnerWasPointer bool, index []int } oi = outInner.Elem() } + + if oi.Kind() == reflect.Slice || oi.Kind() == reflect.Array { + i := index[0] + + // grow slice when needed + if i >= oi.Cap() { + newcap := oi.Cap() + oi.Cap()/2 + if newcap < 4 { + newcap = 4 + } + newoi := reflect.MakeSlice(oi.Type(), oi.Len(), newcap) + reflect.Copy(newoi, oi) + oi.Set(newoi) + } + if i >= oi.Len() { + oi.SetLen(i + 1) + } + + item := oi.Index(i) + if len(index) > 1 { + return setInnerField(&item, false, index[1:], value, omitEmpty) + } + return setField(item, value, omitEmpty) + } + // because pointers can be nil need to recurse one index at a time and perform nil check if len(index) > 1 { nextField := oi.Field(index[0]) |