2020-09-08 15:58:35 -04:00
|
|
|
package d2txt
|
2020-01-26 00:39:13 -05:00
|
|
|
|
|
|
|
import (
|
2020-07-07 08:56:31 -04:00
|
|
|
"bytes"
|
|
|
|
"encoding/csv"
|
|
|
|
"io"
|
2020-01-26 00:39:13 -05:00
|
|
|
"log"
|
|
|
|
"strconv"
|
|
|
|
"strings"
|
|
|
|
)
|
|
|
|
|
|
|
|
// DataDictionary represents a data file (Excel)
|
|
|
|
type DataDictionary struct {
|
2020-07-07 08:56:31 -04:00
|
|
|
lookup map[string]int
|
|
|
|
r *csv.Reader
|
|
|
|
record []string
|
|
|
|
Err error
|
2020-01-26 00:39:13 -05:00
|
|
|
}
|
|
|
|
|
2020-07-01 00:06:06 -04:00
|
|
|
// LoadDataDictionary loads the contents of a spreadsheet style txt file
|
2020-07-07 08:56:31 -04:00
|
|
|
func LoadDataDictionary(buf []byte) *DataDictionary {
|
|
|
|
cr := csv.NewReader(bytes.NewReader(buf))
|
|
|
|
cr.Comma = '\t'
|
|
|
|
cr.ReuseRecord = true
|
2020-07-01 00:06:06 -04:00
|
|
|
|
2020-07-07 08:56:31 -04:00
|
|
|
fieldNames, err := cr.Read()
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
2020-01-26 00:39:13 -05:00
|
|
|
}
|
2020-07-01 00:06:06 -04:00
|
|
|
|
2020-07-07 08:56:31 -04:00
|
|
|
data := &DataDictionary{
|
|
|
|
lookup: make(map[string]int, len(fieldNames)),
|
|
|
|
r: cr,
|
|
|
|
}
|
2020-07-01 00:06:06 -04:00
|
|
|
|
2020-07-07 08:56:31 -04:00
|
|
|
for i, name := range fieldNames {
|
|
|
|
data.lookup[name] = i
|
|
|
|
}
|
2020-07-01 00:06:06 -04:00
|
|
|
|
2020-07-07 08:56:31 -04:00
|
|
|
return data
|
|
|
|
}
|
2020-07-01 00:06:06 -04:00
|
|
|
|
2020-07-07 08:56:31 -04:00
|
|
|
// Next reads the next row, skips Expansion lines or
|
2020-07-08 09:16:56 -04:00
|
|
|
// returns false when the end of a file is reached or an error occurred
|
2020-07-07 08:56:31 -04:00
|
|
|
func (d *DataDictionary) Next() bool {
|
|
|
|
var err error
|
|
|
|
d.record, err = d.r.Read()
|
2020-07-08 09:16:56 -04:00
|
|
|
|
2020-07-07 08:56:31 -04:00
|
|
|
if err == io.EOF {
|
|
|
|
return false
|
|
|
|
} else if err != nil {
|
|
|
|
d.Err = err
|
|
|
|
return false
|
2020-01-26 00:39:13 -05:00
|
|
|
}
|
2020-07-01 00:06:06 -04:00
|
|
|
|
2020-07-07 08:56:31 -04:00
|
|
|
if d.record[0] == "Expansion" {
|
|
|
|
return d.Next()
|
|
|
|
}
|
2020-07-08 09:16:56 -04:00
|
|
|
|
2020-07-07 08:56:31 -04:00
|
|
|
return true
|
2020-01-26 00:39:13 -05:00
|
|
|
}
|
|
|
|
|
2020-07-07 08:56:31 -04:00
|
|
|
// String gets a string from the given column
|
|
|
|
func (d *DataDictionary) String(field string) string {
|
|
|
|
return d.record[d.lookup[field]]
|
2020-01-26 00:39:13 -05:00
|
|
|
}
|
|
|
|
|
2020-07-07 08:56:31 -04:00
|
|
|
// Number gets a number for the given column
|
|
|
|
func (d *DataDictionary) Number(field string) int {
|
|
|
|
n, err := strconv.Atoi(d.String(field))
|
2020-01-26 00:39:13 -05:00
|
|
|
if err != nil {
|
2020-07-07 08:56:31 -04:00
|
|
|
return 0
|
2020-01-26 00:39:13 -05:00
|
|
|
}
|
2020-07-08 09:16:56 -04:00
|
|
|
|
2020-07-07 08:56:31 -04:00
|
|
|
return n
|
2020-01-26 00:39:13 -05:00
|
|
|
}
|
2020-06-29 12:37:11 -04:00
|
|
|
|
2020-07-07 08:56:31 -04:00
|
|
|
// List splits a delimited list from the given column
|
|
|
|
func (d *DataDictionary) List(field string) []string {
|
|
|
|
str := d.String(field)
|
|
|
|
return strings.Split(str, ",")
|
2020-06-29 12:37:11 -04:00
|
|
|
}
|
|
|
|
|
2020-07-07 08:56:31 -04:00
|
|
|
// Bool gets a bool value for the given column
|
|
|
|
func (d *DataDictionary) Bool(field string) bool {
|
|
|
|
n := d.Number(field)
|
2020-06-29 12:37:11 -04:00
|
|
|
if n > 1 {
|
2020-07-30 16:17:26 -04:00
|
|
|
log.Panic("Bool on non-bool field ", field)
|
2020-06-29 12:37:11 -04:00
|
|
|
}
|
2020-07-08 09:16:56 -04:00
|
|
|
|
2020-06-29 12:37:11 -04:00
|
|
|
return n == 1
|
|
|
|
}
|