forked from OrgGo/goplot
202 lines
3.3 KiB
Go
202 lines
3.3 KiB
Go
|
package main
|
||
|
|
||
|
import (
|
||
|
"bufio"
|
||
|
"bytes"
|
||
|
"encoding/json"
|
||
|
"errors"
|
||
|
"io"
|
||
|
"log"
|
||
|
"os"
|
||
|
"path/filepath"
|
||
|
"strconv"
|
||
|
"strings"
|
||
|
)
|
||
|
|
||
|
const (
|
||
|
START = iota
|
||
|
PROP
|
||
|
DATA
|
||
|
)
|
||
|
|
||
|
var (
|
||
|
prop_header_str = []byte("===")
|
||
|
data_header_str = []byte("---")
|
||
|
)
|
||
|
|
||
|
type ChartPropType struct {
|
||
|
Name string
|
||
|
Width int
|
||
|
Height int
|
||
|
}
|
||
|
|
||
|
type ChartItemType struct {
|
||
|
key string
|
||
|
values []int
|
||
|
}
|
||
|
|
||
|
func newChartItem(d string) *ChartItemType {
|
||
|
item := &ChartItemType{}
|
||
|
item.values = make([]int, 0, 2)
|
||
|
|
||
|
fields := strings.Split(d, " ")
|
||
|
toValue := false
|
||
|
|
||
|
for _, f := range fields {
|
||
|
if len(f) == 0 {
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
if toValue {
|
||
|
if i, err := strconv.Atoi(f); err != nil {
|
||
|
log.Println(err)
|
||
|
} else {
|
||
|
item.values = append(item.values, i)
|
||
|
}
|
||
|
} else {
|
||
|
item.key = f
|
||
|
toValue = true
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return item
|
||
|
}
|
||
|
|
||
|
type ChartDataType struct {
|
||
|
prop *bytes.Buffer
|
||
|
items []*ChartItemType
|
||
|
}
|
||
|
|
||
|
func newChartData() *ChartDataType {
|
||
|
c := new(ChartDataType)
|
||
|
c.prop = bytes.NewBuffer(make([]byte, 0, 128))
|
||
|
c.items = make([]*ChartItemType, 0, 10)
|
||
|
return c
|
||
|
}
|
||
|
|
||
|
func (c *ChartDataType) appendProp(p []byte) {
|
||
|
c.prop.Write(p)
|
||
|
}
|
||
|
|
||
|
func (c *ChartDataType) appendValue(item *ChartItemType) {
|
||
|
c.items = append(c.items, item)
|
||
|
}
|
||
|
|
||
|
func (c *ChartDataType) Prop() (p ChartPropType, err error) {
|
||
|
b := c.prop.Bytes()
|
||
|
b = bytes.Trim(b, " ")
|
||
|
err = json.Unmarshal(b, &p)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
func (c *ChartDataType) ItemNum() int {
|
||
|
return len(c.items)
|
||
|
}
|
||
|
|
||
|
func (c *ChartDataType) ItemName() []string {
|
||
|
names := make([]string, 0, 5)
|
||
|
for _, it := range c.items {
|
||
|
names = append(names, it.key)
|
||
|
}
|
||
|
return names
|
||
|
}
|
||
|
|
||
|
func (c *ChartDataType) ValueNum() int {
|
||
|
if len(c.items) == 0 {
|
||
|
return 0
|
||
|
}
|
||
|
return len(c.items[0].values)
|
||
|
}
|
||
|
|
||
|
func (c *ChartDataType) ItemValue(i int) []int {
|
||
|
values := make([]int, 0, 5)
|
||
|
for _, it := range c.items {
|
||
|
if i >= len(it.values) {
|
||
|
return nil
|
||
|
}
|
||
|
values = append(values, it.values[i])
|
||
|
}
|
||
|
return values
|
||
|
}
|
||
|
|
||
|
func ParseDataFile(file string) ([]*ChartDataType, error) {
|
||
|
f, err := os.Open(file)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
defer f.Close()
|
||
|
|
||
|
var c *ChartDataType
|
||
|
charts := make([]*ChartDataType, 0, 2)
|
||
|
reader := bufio.NewReader(f)
|
||
|
status := START
|
||
|
|
||
|
for {
|
||
|
line, _, err := reader.ReadLine()
|
||
|
if err != nil {
|
||
|
if err == io.EOF {
|
||
|
break
|
||
|
}
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
if line = bytes.Trim(line, " "); len(line) == 0 {
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
switch status {
|
||
|
case START:
|
||
|
if bytes.Compare(line, prop_header_str) == 0 {
|
||
|
status = PROP
|
||
|
c = newChartData()
|
||
|
} else {
|
||
|
return nil, errors.New("invalid chart file")
|
||
|
}
|
||
|
case PROP:
|
||
|
if bytes.Compare(line, data_header_str) == 0 {
|
||
|
status = DATA
|
||
|
} else {
|
||
|
c.appendProp(line)
|
||
|
}
|
||
|
case DATA:
|
||
|
if bytes.Compare(line, prop_header_str) == 0 {
|
||
|
status = PROP
|
||
|
charts = append(charts, c)
|
||
|
c = newChartData()
|
||
|
} else {
|
||
|
item := newChartItem(string(line))
|
||
|
c.appendValue(item)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
charts = append(charts, c)
|
||
|
return charts, nil
|
||
|
}
|
||
|
|
||
|
func LookupCurrentDir(dir string) ([]*ChartDataType, error) {
|
||
|
var data []*ChartDataType
|
||
|
|
||
|
err := filepath.Walk(dir, func(path string, f os.FileInfo, err error) error {
|
||
|
if f == nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
if f.IsDir() {
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
if ok, err := filepath.Match("*.chart", f.Name()); err != nil {
|
||
|
return err
|
||
|
} else if ok {
|
||
|
if path == f.Name() {
|
||
|
data, err = ParseDataFile(path)
|
||
|
return err
|
||
|
}
|
||
|
}
|
||
|
return nil
|
||
|
})
|
||
|
|
||
|
return data, err
|
||
|
}
|