package jdr
|
|
|
|
import(
|
|
"log"
|
|
"errors"
|
|
"strings"
|
|
"strconv"
|
|
"regexp"
|
|
)
|
|
|
|
var regexp_d = regexp.MustCompile(`^[1-9][0-9]*d([468]|1[02]|20|100)$`)
|
|
|
|
type VariableType interface {
|
|
Name() string
|
|
Validate(s string) bool
|
|
}
|
|
|
|
type VariableType_badType struct {}
|
|
|
|
func (*VariableType_badType) Name() string {
|
|
return "unknown type"
|
|
}
|
|
|
|
func (*VariableType_badType) Validate(s string) bool {
|
|
return false
|
|
}
|
|
|
|
type VariableType_bool struct {}
|
|
|
|
func (*VariableType_bool) Name() string {
|
|
return "bool"
|
|
}
|
|
|
|
func (*VariableType_bool) ToBool(value string) (bool, error) {
|
|
switch strings.ToLower(value) {
|
|
case "true":
|
|
return true, nil
|
|
case "false":
|
|
return false, nil
|
|
default:
|
|
return false, errors.New("unknown bool value")
|
|
}
|
|
}
|
|
|
|
func (self *VariableType_bool) Validate(value string) bool {
|
|
_, err := self.ToBool(value)
|
|
return err == nil
|
|
}
|
|
|
|
type VariableType_int struct {}
|
|
|
|
func (*VariableType_int) Name() string {
|
|
return "int"
|
|
}
|
|
|
|
func (self *VariableType_int) ToInt(value string) (int64, error) {
|
|
return strconv.ParseInt(value, 10, 64)
|
|
}
|
|
|
|
func (self *VariableType_int) Validate(value string) bool {
|
|
_, err := self.ToInt(value)
|
|
return err == nil
|
|
}
|
|
|
|
type VariableType_float struct {}
|
|
|
|
func (*VariableType_float) Name() string {
|
|
return "float"
|
|
}
|
|
|
|
func (*VariableType_float) ToFloat(value string) (float64, error) {
|
|
return strconv.ParseFloat(value, 64)
|
|
}
|
|
|
|
func (self *VariableType_float) Validate(value string) bool {
|
|
_, err := self.ToFloat(value)
|
|
return err == nil
|
|
}
|
|
|
|
type VariableType_string struct {}
|
|
|
|
func (*VariableType_string) Name() string {
|
|
return "string"
|
|
}
|
|
|
|
func (*VariableType_string) Validate(s string) bool {
|
|
return true
|
|
}
|
|
|
|
type VariableType_d struct {}
|
|
|
|
func (*VariableType_d) Name() string {
|
|
return "d"
|
|
}
|
|
|
|
func (*VariableType_d) Validate(s string) bool {
|
|
return regexp_d.MatchString(s)
|
|
}
|
|
|
|
func makeVariableType(s string) VariableType {
|
|
switch(strings.ToLower(s)) {
|
|
case "bool":
|
|
return &VariableType_bool{}
|
|
case "int":
|
|
return &VariableType_int{}
|
|
case "float":
|
|
return &VariableType_float{}
|
|
case "string":
|
|
return &VariableType_string{}
|
|
case "d":
|
|
return &VariableType_d{}
|
|
default:
|
|
log.Println("Unknown type:", s)
|
|
return &VariableType_badType{}
|
|
}
|
|
}
|
|
|
|
type CustomEnum struct {
|
|
name string
|
|
BaseType VariableType
|
|
Values []string
|
|
}
|
|
|
|
func (self *CustomEnum) Name() string {
|
|
return self.name
|
|
}
|
|
|
|
func (self *CustomEnum) Validate(s string) bool {
|
|
if !self.BaseType.Validate(s) {
|
|
return false
|
|
}
|
|
|
|
for i := 0; i < len(self.Values); i++ {
|
|
if self.Values[i] == s {
|
|
return true
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
type CustomStruct struct {
|
|
name string
|
|
Variables []Variable
|
|
}
|
|
|
|
func (self *CustomStruct) Name() string {
|
|
return self.name
|
|
}
|
|
|
|
func (self *CustomStruct) Validate(s string) bool {
|
|
//FIXME
|
|
log.Println("Custom struct Validate is not (yet) implemented")
|
|
return false
|
|
}
|
|
|
|
func parseCustomEnum(root xmlNode) (*CustomEnum, error) {
|
|
customEnum := CustomEnum {}
|
|
|
|
nameOk := false;
|
|
typeOk := false;
|
|
for i := 0; i < len(root.Attrs); i++ {
|
|
attrName := root.Attrs[i].Name.Local
|
|
attrVal := root.Attrs[i].Value
|
|
|
|
switch attrName {
|
|
case "name":
|
|
nameOk = true
|
|
customEnum.name = attrVal
|
|
case "base-type":
|
|
typeOk = true
|
|
customEnum.BaseType = makeVariableType(attrVal)
|
|
switch customEnum.BaseType.(type) {
|
|
case *VariableType_badType:
|
|
typeOk = false
|
|
}
|
|
}
|
|
}
|
|
|
|
if !nameOk {
|
|
return nil, errors.New("Unnamed custom enum")
|
|
}
|
|
if !typeOk {
|
|
return nil, errors.New("Bad base type for " + customEnum.Name())
|
|
}
|
|
|
|
for i := 0; i < len(root.Nodes); i++ {
|
|
node := root.Nodes[i]
|
|
|
|
switch node.XMLName.Local {
|
|
case "value":
|
|
value := string(node.Content)
|
|
if customEnum.BaseType.Validate(value) {
|
|
customEnum.Values = append(customEnum.Values, value)
|
|
} else {
|
|
log.Println("Cannot validate value enum \"" + value + "\" with type \"" +
|
|
customEnum.BaseType.Name() + "\". Discarded")
|
|
}
|
|
}
|
|
}
|
|
|
|
return &customEnum, nil
|
|
}
|
|
|
|
func parseCustomStruct(root xmlNode) (*CustomStruct, error) {
|
|
customType := CustomStruct{}
|
|
|
|
nameOk := false
|
|
for i := 0; i < len(root.Attrs); i++ {
|
|
attrName := root.Attrs[i].Name.Local
|
|
attrVal := root.Attrs[i].Value
|
|
|
|
switch attrName {
|
|
case "name":
|
|
nameOk = true
|
|
customType.name = attrVal
|
|
}
|
|
}
|
|
if !nameOk {
|
|
return nil, errors.New("Unnamed custom type")
|
|
}
|
|
|
|
return &customType, nil
|
|
}
|
|
|
|
func parseCustomTypes(root xmlNode) ([]VariableType, error) {
|
|
types := []VariableType{}
|
|
|
|
for i := 0; i < len(root.Nodes); i++ {
|
|
node := root.Nodes[i]
|
|
|
|
switch node.XMLName.Local {
|
|
case "enum":
|
|
customEnum, err := parseCustomEnum(node)
|
|
if err != nil {
|
|
return []VariableType{}, err
|
|
}
|
|
types = append(types, customEnum)
|
|
case "type":
|
|
customType, err := parseCustomStruct(node)
|
|
if err != nil {
|
|
return []VariableType{}, err
|
|
}
|
|
types = append(types, customType)
|
|
default:
|
|
return []VariableType{}, errors.New("Unknown CustomType: " + root.Nodes[i].XMLName.Local)
|
|
}
|
|
}
|
|
|
|
return types, nil
|
|
}
|