Kepler core
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

216 lines
3.6 KiB

package misc
import (
"encoding/csv"
"encoding/json"
"errors"
"io"
"os"
"strconv"
"strings"
)
type Record map[string]interface{}
const (
STRING uint8 = iota
INTEGER
FLOAT
DOUBLE
BOOL
DATE
TIME
DATETIME
)
type Key struct {
Name string
Type uint8
Extra string
}
func parse_key_type(s string) uint8 {
switch strings.ToLower(s) {
case "int", "integer":
return INTEGER
case "bool", "boolean":
return BOOL
case "float":
return FLOAT
case "double":
return DOUBLE
case "date":
return DATE
case "time":
return TIME
case "datetime":
return DATETIME
default:
return STRING
}
return STRING
}
func (k *Key) Parse(s string) error {
ss := strings.Split(s, ":")
switch len(ss) {
case 1:
k.Name = ss[0]
k.Type = STRING
case 2:
k.Name = ss[0]
k.Type = parse_key_type(ss[1])
case 3:
k.Name = ss[0]
k.Type = parse_key_type(ss[1])
k.Extra = ss[2]
default:
return errors.New("Wrong format of key!")
}
return nil
}
func (r Record) Assign(v interface{}) error {
if p, e := json.Marshal(r); nil != e {
return e
} else {
return json.Unmarshal(p, v)
}
return nil
}
func (r Record) GetString(k string, defaults ...string) (string, bool) {
if v, ok := r[k]; ok {
if vv, ook := v.(string); ook {
return vv, true
}
}
d := ""
if len(defaults) > 0 {
d = defaults[0]
}
return d, false
}
func (r Record) GetInt(k string, defaults ...int) (int, bool) {
if v, ok := r[k]; ok {
if vv, ook := v.(int); ook {
return vv, true
}
}
d := 0
if len(defaults) > 0 {
d = defaults[0]
}
return d, false
}
func (r Record) GetBool(k string, defaults ...bool) (bool, bool) {
if v, ok := r[k]; ok {
if vv, ook := v.(bool); ook {
return vv, true
}
}
d := false
if len(defaults) > 0 {
d = defaults[0]
}
return d, false
}
func (r Record) GetFloat(k string, defaults ...float32) (float32, bool) {
if v, ok := r[k]; ok {
if vv, ook := v.(float32); ook {
return vv, true
}
}
var d float32 = 0.0
if len(defaults) > 0 {
d = defaults[0]
}
return d, false
}
func (r Record) GetDouble(k string, defaults ...float64) (float64, bool) {
if v, ok := r[k]; ok {
if vv, ook := v.(float64); ook {
return vv, true
}
}
var d float64 = 0
if len(defaults) > 0 {
d = defaults[0]
}
return d, false
}
func CSV2List(in io.Reader) (records []Record, err error) {
reader := csv.NewReader(in)
if recs, e := reader.ReadAll(); nil != e {
return records, e
} else {
var keys []*Key
for i, rec := range recs {
if i == 0 {
for _, k := range rec {
kk := &Key{}
if ee := kk.Parse(k); nil != ee {
return records, ee
} else {
keys = append(keys, kk)
}
}
continue
}
r := make(Record)
for j, k := range keys {
switch k.Type {
case INTEGER:
if n, e := strconv.ParseInt(rec[j], 10, 32); nil != e {
return records, e
} else {
r[k.Name] = n
}
case BOOL:
switch strings.ToLower(rec[j]) {
case "t", "y", "true", "yes":
r[k.Name] = true
default:
r[k.Name] = false
}
case FLOAT:
if f, e := strconv.ParseFloat(rec[j], 32); nil != e {
return records, e
} else {
r[k.Name] = float32(f)
}
case DOUBLE:
if f, e := strconv.ParseFloat(rec[j], 64); nil != e {
return records, e
} else {
r[k.Name] = f
}
case DATE:
case TIME:
case DATETIME:
default:
r[k.Name] = rec[j]
}
}
records = append(records, r)
}
}
return
}
func CSV_File2List(filename string) (records []Record, err error) {
f, e := os.Open(filename)
if nil != e {
err = e
return
}
defer f.Close()
records, err = CSV2List(f)
return
}