I am a fool and should have found a better way to break this into many commits shame... shame on the poor choices I have madepull/16/head
| @ -1,9 +0,0 @@ | |||
| package config | |||
| type BooleanValue struct { | |||
| Name string | |||
| Value bool | |||
| } | |||
| func (this BooleanValue) GetType() ConfigType { return BOOLEAN } | |||
| func (this BooleanValue) GetValue() interface{} { return this.Value } | |||
| @ -1,39 +0,0 @@ | |||
| package config | |||
| type ConfigType int | |||
| const ( | |||
| SECTION ConfigType = iota | |||
| INTEGER | |||
| BOOLEAN | |||
| FLOAT | |||
| STRING | |||
| NULL | |||
| ) | |||
| var configTypes = [...]string{ | |||
| SECTION: "SECTION", | |||
| BOOLEAN: "BOOLEAN", | |||
| INTEGER: "INTEGER", | |||
| FLOAT: "FLOAT", | |||
| STRING: "STRING", | |||
| NULL: "NULL", | |||
| } | |||
| func (this ConfigType) String() string { | |||
| s := "" | |||
| if 0 <= this && this < ConfigType(len(configTypes)) { | |||
| s = configTypes[this] | |||
| } | |||
| if s == "" { | |||
| s = "UNKNOWN" | |||
| } | |||
| return s | |||
| } | |||
| type ConfigValue interface { | |||
| GetType() ConfigType | |||
| GetValue() interface{} | |||
| } | |||
| @ -1,9 +0,0 @@ | |||
| package config | |||
| type FloatValue struct { | |||
| Name string | |||
| Value float64 | |||
| } | |||
| func (this FloatValue) GetType() ConfigType { return INTEGER } | |||
| func (this FloatValue) GetValue() interface{} { return this.Value } | |||
| @ -1,9 +0,0 @@ | |||
| package config | |||
| type IntegerValue struct { | |||
| Name string | |||
| Value int64 | |||
| } | |||
| func (this IntegerValue) GetType() ConfigType { return INTEGER } | |||
| func (this IntegerValue) GetValue() interface{} { return this.Value } | |||
| @ -1,9 +0,0 @@ | |||
| package config | |||
| type NullValue struct { | |||
| Name string | |||
| Value interface{} | |||
| } | |||
| func (this NullValue) GetType() ConfigType { return NULL } | |||
| func (this NullValue) GetValue() interface{} { return nil } | |||
| @ -1,132 +0,0 @@ | |||
| package config | |||
| import ( | |||
| "encoding/json" | |||
| "errors" | |||
| "fmt" | |||
| "strings" | |||
| ) | |||
| type SectionValue struct { | |||
| Name string | |||
| Value map[string]ConfigValue | |||
| Comments []string | |||
| Includes []string | |||
| } | |||
| func NewNamedSection(name string) *SectionValue { | |||
| return &SectionValue{ | |||
| Name: name, | |||
| Value: make(map[string]ConfigValue), | |||
| Comments: make([]string, 0), | |||
| Includes: make([]string, 0), | |||
| } | |||
| } | |||
| func NewAnonymousSection() *SectionValue { | |||
| return &SectionValue{ | |||
| Value: make(map[string]ConfigValue), | |||
| Comments: make([]string, 0), | |||
| Includes: make([]string, 0), | |||
| } | |||
| } | |||
| func (this SectionValue) GetType() ConfigType { return SECTION } | |||
| func (this SectionValue) GetValue() interface{} { return this.Value } | |||
| func (this *SectionValue) AddComment(comment string) { | |||
| this.Comments = append(this.Comments, comment) | |||
| } | |||
| func (this *SectionValue) AddInclude(include string) { | |||
| this.Includes = append(this.Includes, include) | |||
| } | |||
| func (this *SectionValue) Set(name string, value ConfigValue) { | |||
| this.Value[name] = value | |||
| } | |||
| func (this *SectionValue) Get(name string) ConfigValue { | |||
| return this.Value[name] | |||
| } | |||
| func (this *SectionValue) GetSection(name string) SectionValue { | |||
| value := this.Value[name] | |||
| return value.(SectionValue) | |||
| } | |||
| func (this *SectionValue) GetString(name string) StringValue { | |||
| value := this.Value[name] | |||
| return value.(StringValue) | |||
| } | |||
| func (this *SectionValue) GetInteger(name string) IntegerValue { | |||
| value := this.Value[name] | |||
| return value.(IntegerValue) | |||
| } | |||
| func (this *SectionValue) GetFloat(name string) FloatValue { | |||
| value := this.Value[name] | |||
| return value.(FloatValue) | |||
| } | |||
| func (this *SectionValue) Contains(name string) bool { | |||
| _, ok := this.Value[name] | |||
| return ok | |||
| } | |||
| func (this *SectionValue) Resolve(setting string) (ConfigValue, error) { | |||
| parts := strings.Split(setting, ".") | |||
| var reference ConfigValue | |||
| reference = this | |||
| visited := []string{} | |||
| for { | |||
| if len(parts) == 0 { | |||
| break | |||
| } | |||
| if reference.GetType() != SECTION { | |||
| name := strings.Join(visited, ".") | |||
| return nil, errors.New(fmt.Sprintf("'%s' is a %s not a SECTION", name, reference.GetType())) | |||
| } | |||
| part := parts[0] | |||
| parts = parts[1:] | |||
| section := reference.(*SectionValue) | |||
| if section.Contains(part) == false { | |||
| name := strings.Join(visited, ".") | |||
| if len(name) > 0 { | |||
| return nil, errors.New(fmt.Sprintf("'%s' does not have setting '%s'", name, part)) | |||
| } else { | |||
| return nil, errors.New(fmt.Sprintf("setting '%s' does not exist", part)) | |||
| } | |||
| } | |||
| reference = section.Get(part) | |||
| visited = append(visited, part) | |||
| } | |||
| return reference, nil | |||
| } | |||
| func (this *SectionValue) ToJSON() ([]byte, error) { | |||
| data, err := this.ToMap() | |||
| if err != nil { | |||
| return nil, err | |||
| } | |||
| return json.Marshal(data) | |||
| } | |||
| func (this *SectionValue) ToMap() (map[string]interface{}, error) { | |||
| settings := make(map[string]interface{}) | |||
| for name, value := range this.Value { | |||
| if value.GetType() == SECTION { | |||
| data, err := value.(*SectionValue).ToMap() | |||
| if err != nil { | |||
| return nil, err | |||
| } | |||
| settings[name] = data | |||
| } else { | |||
| settings[name] = value.GetValue() | |||
| } | |||
| } | |||
| return settings, nil | |||
| } | |||
| @ -1,9 +0,0 @@ | |||
| package config | |||
| type StringValue struct { | |||
| Name string | |||
| Value string | |||
| } | |||
| func (this StringValue) GetType() ConfigType { return STRING } | |||
| func (this StringValue) GetValue() interface{} { return this.Value } | |||
| @ -0,0 +1,88 @@ | |||
| package forge | |||
| import ( | |||
| "errors" | |||
| "fmt" | |||
| "math" | |||
| "strconv" | |||
| ) | |||
| func asBoolean(value interface{}) (bool, error) { | |||
| switch val := value.(type) { | |||
| case bool: | |||
| return val, nil | |||
| case float64: | |||
| return val != 0, nil | |||
| case int64: | |||
| return val != 0, nil | |||
| case nil: | |||
| return false, nil | |||
| case string: | |||
| return val != "", nil | |||
| } | |||
| msg := fmt.Sprintf("Could not convert value %s to type BOOLEAN", value) | |||
| return false, errors.New(msg) | |||
| } | |||
| func asFloat(value interface{}) (float64, error) { | |||
| switch val := value.(type) { | |||
| case bool: | |||
| if val { | |||
| return float64(1), nil | |||
| } else { | |||
| return float64(0), nil | |||
| } | |||
| case float64: | |||
| return val, nil | |||
| case int64: | |||
| return float64(val), nil | |||
| case string: | |||
| return strconv.ParseFloat(val, 64) | |||
| } | |||
| msg := fmt.Sprintf("Could not convert value %s to type FLOAT", value) | |||
| return 0, errors.New(msg) | |||
| } | |||
| func asInteger(value interface{}) (int64, error) { | |||
| switch val := value.(type) { | |||
| case bool: | |||
| if val { | |||
| return int64(1), nil | |||
| } else { | |||
| return int64(0), nil | |||
| } | |||
| case float64: | |||
| return int64(math.Trunc(val)), nil | |||
| case int64: | |||
| return val, nil | |||
| case string: | |||
| return strconv.ParseInt(val, 10, 64) | |||
| } | |||
| msg := fmt.Sprintf("Could not convert value %s to type INTEGER", value) | |||
| return 0, errors.New(msg) | |||
| } | |||
| func asString(value interface{}) (string, error) { | |||
| switch val := value.(type) { | |||
| case bool: | |||
| if val { | |||
| return "True", nil | |||
| } else { | |||
| return "False", nil | |||
| } | |||
| case float64: | |||
| return strconv.FormatFloat(val, 10, -1, 64), nil | |||
| case int64: | |||
| return strconv.FormatInt(val, 10), nil | |||
| case nil: | |||
| return "Null", nil | |||
| case string: | |||
| return val, nil | |||
| } | |||
| msg := fmt.Sprintf("Could not convert value %s to type STRING", value) | |||
| return "", errors.New(msg) | |||
| } | |||
| @ -0,0 +1,89 @@ | |||
| package forge | |||
| import ( | |||
| "errors" | |||
| "fmt" | |||
| ) | |||
| type Primative struct { | |||
| valueType ValueType | |||
| value interface{} | |||
| } | |||
| func NewPrimative(valueType ValueType, value interface{}) *Primative { | |||
| return &Primative{ | |||
| valueType: valueType, | |||
| value: value, | |||
| } | |||
| } | |||
| func NewBoolean(value bool) *Primative { | |||
| return NewPrimative(BOOLEAN, value) | |||
| } | |||
| func NewFloat(value float64) *Primative { | |||
| return NewPrimative(FLOAT, value) | |||
| } | |||
| func NewInteger(value int64) *Primative { | |||
| return NewPrimative(INTEGER, value) | |||
| } | |||
| func NewNull() *Primative { | |||
| return NewPrimative(NULL, nil) | |||
| } | |||
| func NewString(value string) *Primative { | |||
| return NewPrimative(STRING, value) | |||
| } | |||
| func (this *Primative) GetType() ValueType { | |||
| return this.valueType | |||
| } | |||
| func (this *Primative) GetValue() interface{} { | |||
| return this.value | |||
| } | |||
| func (this *Primative) UpdateValue(value interface{}) error { | |||
| // Valid types | |||
| switch value.(type) { | |||
| case bool: | |||
| this.valueType = BOOLEAN | |||
| case float64: | |||
| this.valueType = FLOAT | |||
| case int64: | |||
| this.valueType = INTEGER | |||
| case nil: | |||
| this.valueType = NULL | |||
| case string: | |||
| this.valueType = STRING | |||
| default: | |||
| msg := fmt.Sprintf("Unsupported type, %s must be of (bool, float64, int64, nil, string)", value) | |||
| return errors.New(msg) | |||
| } | |||
| this.value = value | |||
| return nil | |||
| } | |||
| func (this *Primative) AsBoolean() (bool, error) { | |||
| return asBoolean(this.value) | |||
| } | |||
| func (this *Primative) AsFloat() (float64, error) { | |||
| return asFloat(this.value) | |||
| } | |||
| func (this *Primative) AsInteger() (int64, error) { | |||
| return asInteger(this.value) | |||
| } | |||
| func (this *Primative) AsString() (string, error) { | |||
| return asString(this.value) | |||
| } | |||
| func (this *Primative) String() string { | |||
| str, _ := this.AsString() | |||
| return str | |||
| } | |||
| @ -0,0 +1,244 @@ | |||
| package forge | |||
| import ( | |||
| "encoding/json" | |||
| "errors" | |||
| "fmt" | |||
| "strings" | |||
| ) | |||
| type Section struct { | |||
| parent *Section | |||
| values map[string]Value | |||
| } | |||
| func NewSection() *Section { | |||
| return &Section{ | |||
| values: make(map[string]Value), | |||
| } | |||
| } | |||
| func NewChildSection(parent *Section) *Section { | |||
| return &Section{ | |||
| parent: parent, | |||
| values: make(map[string]Value), | |||
| } | |||
| } | |||
| func (this *Section) GetType() ValueType { | |||
| return SECTION | |||
| } | |||
| func (this *Section) GetValue() interface{} { | |||
| return this.values | |||
| } | |||
| func (this *Section) UpdateValue(value interface{}) error { | |||
| switch value.(type) { | |||
| case map[string]Value: | |||
| this.values = value.(map[string]Value) | |||
| return nil | |||
| } | |||
| msg := fmt.Sprintf("Unsupported type, %s must be of type `map[string]Value`", value) | |||
| return errors.New(msg) | |||
| } | |||
| func (this *Section) AddSection(name string) *Section { | |||
| section := NewChildSection(this) | |||
| this.values[name] = section | |||
| return section | |||
| } | |||
| func (this *Section) Exists(name string) bool { | |||
| _, err := this.Get(name) | |||
| return err == nil | |||
| } | |||
| func (this *Section) Get(name string) (Value, error) { | |||
| value, ok := this.values[name] | |||
| var err error | |||
| if ok == false { | |||
| err = errors.New("Value does not exist") | |||
| } | |||
| return value, err | |||
| } | |||
| func (this *Section) GetBoolean(name string) (bool, error) { | |||
| value, err := this.Get(name) | |||
| if err != nil { | |||
| return false, err | |||
| } | |||
| switch value.(type) { | |||
| case *Primative: | |||
| return value.(*Primative).AsBoolean() | |||
| case *Section: | |||
| return true, nil | |||
| } | |||
| return false, errors.New("Could not convert unknown value to boolean") | |||
| } | |||
| func (this *Section) GetFloat(name string) (float64, error) { | |||
| value, err := this.Get(name) | |||
| if err != nil { | |||
| return float64(0), err | |||
| } | |||
| switch value.(type) { | |||
| case *Primative: | |||
| return value.(*Primative).AsFloat() | |||
| } | |||
| return float64(0), errors.New("Could not convert non-primative value to float") | |||
| } | |||
| func (this *Section) GetInteger(name string) (int64, error) { | |||
| value, err := this.Get(name) | |||
| if err != nil { | |||
| return int64(0), err | |||
| } | |||
| switch value.(type) { | |||
| case *Primative: | |||
| return value.(*Primative).AsInteger() | |||
| } | |||
| return int64(0), errors.New("Could not convert non-primative value to integer") | |||
| } | |||
| func (this *Section) GetSection(name string) (*Section, error) { | |||
| value, err := this.Get(name) | |||
| if err != nil { | |||
| return nil, err | |||
| } | |||
| if value.GetType() == SECTION { | |||
| return value.(*Section), nil | |||
| } | |||
| return nil, errors.New("Could not fetch value as section") | |||
| } | |||
| func (this *Section) GetString(name string) (string, error) { | |||
| value, err := this.Get(name) | |||
| if err != nil { | |||
| return "", err | |||
| } | |||
| switch value.(type) { | |||
| case *Primative: | |||
| return value.(*Primative).AsString() | |||
| } | |||
| return "", errors.New("Could not convert non-primative value to string") | |||
| } | |||
| func (this *Section) GetParent() *Section { | |||
| return this.parent | |||
| } | |||
| func (this *Section) HasParent() bool { | |||
| return this.parent != nil | |||
| } | |||
| func (this *Section) Set(name string, value Value) { | |||
| this.values[name] = value | |||
| } | |||
| func (this *Section) SetBoolean(name string, value bool) { | |||
| current, err := this.Get(name) | |||
| // Exists just update the value/type | |||
| if err == nil { | |||
| current.UpdateValue(value) | |||
| } else { | |||
| this.values[name] = NewBoolean(value) | |||
| } | |||
| } | |||
| func (this *Section) SetFloat(name string, value float64) { | |||
| current, err := this.Get(name) | |||
| // Exists just update the value/type | |||
| if err == nil { | |||
| current.UpdateValue(value) | |||
| } else { | |||
| this.values[name] = NewFloat(value) | |||
| } | |||
| } | |||
| func (this *Section) SetInteger(name string, value int64) { | |||
| current, err := this.Get(name) | |||
| // Exists just update the value/type | |||
| if err == nil { | |||
| current.UpdateValue(value) | |||
| } else { | |||
| this.values[name] = NewInteger(value) | |||
| } | |||
| } | |||
| func (this *Section) SetNull(name string) { | |||
| current, err := this.Get(name) | |||
| // Already is a Null, nothing to do | |||
| if err == nil && current.GetType() == NULL { | |||
| return | |||
| } | |||
| this.Set(name, NewNull()) | |||
| } | |||
| func (this *Section) SetString(name string, value string) { | |||
| current, err := this.Get(name) | |||
| // Exists just update the value/type | |||
| if err == nil { | |||
| current.UpdateValue(value) | |||
| } else { | |||
| this.Set(name, NewString(value)) | |||
| } | |||
| } | |||
| func (this *Section) Resolve(name string) (Value, error) { | |||
| // Used only in error state return value | |||
| var value Value | |||
| parts := strings.Split(name, ".") | |||
| if len(parts) == 0 { | |||
| return value, errors.New("No name provided") | |||
| } | |||
| var current Value | |||
| current = this | |||
| for _, part := range parts { | |||
| if current.GetType() != SECTION { | |||
| return value, errors.New("Trying to resolve value from non-section") | |||
| } | |||
| next_current, err := current.(*Section).Get(part) | |||
| if err != nil { | |||
| return value, errors.New("Could not find value in section") | |||
| } | |||
| current = next_current | |||
| } | |||
| return current, nil | |||
| } | |||
| func (this *Section) ToJSON() ([]byte, error) { | |||
| data := this.ToMap() | |||
| return json.Marshal(data) | |||
| } | |||
| func (this *Section) ToMap() map[string]interface{} { | |||
| output := make(map[string]interface{}) | |||
| for key, value := range this.values { | |||
| if value.GetType() == SECTION { | |||
| output[key] = value.(*Section).ToMap() | |||
| } else { | |||
| output[key] = value.GetValue() | |||
| } | |||
| } | |||
| return output | |||
| } | |||
| @ -1,54 +0,0 @@ | |||
| package token | |||
| type TokenID int | |||
| const ( | |||
| ILLEGAL TokenID = iota | |||
| EOF | |||
| LBRACKET | |||
| RBRACKET | |||
| EQUAL | |||
| SEMICOLON | |||
| PERIOD | |||
| IDENTIFIER | |||
| BOOLEAN | |||
| INTEGER | |||
| FLOAT | |||
| STRING | |||
| NULL | |||
| COMMENT | |||
| INCLUDE | |||
| ) | |||
| var tokenNames = [...]string{ | |||
| ILLEGAL: "ILLEGAL", | |||
| EOF: "EOF", | |||
| LBRACKET: "LBRACKET", | |||
| RBRACKET: "RBRACKET", | |||
| EQUAL: "EQUAL", | |||
| SEMICOLON: "SEMICOLON", | |||
| PERIOD: "PERIOD", | |||
| IDENTIFIER: "IDENTIFIER", | |||
| BOOLEAN: "BOOLEAN", | |||
| INTEGER: "INTEGER", | |||
| FLOAT: "FLOAT", | |||
| STRING: "STRING", | |||
| NULL: "NULL", | |||
| COMMENT: "COMMENT", | |||
| INCLUDE: "INCLUDE", | |||
| } | |||
| func (this TokenID) String() string { | |||
| s := "" | |||
| if 0 <= this && this < TokenID(len(tokenNames)) { | |||
| s = tokenNames[this] | |||
| } | |||
| if s == "" { | |||
| s = "UNKNOWN" | |||
| } | |||
| return s | |||
| } | |||
| @ -0,0 +1,48 @@ | |||
| package forge | |||
| type ValueType int | |||
| const ( | |||
| UNKNOWN ValueType = iota | |||
| // Primative values | |||
| BOOLEAN | |||
| FLOAT | |||
| INTEGER | |||
| NULL | |||
| STRING | |||
| // Complex values | |||
| REFERENCE | |||
| SECTION | |||
| ) | |||
| var valueTypes = [...]string{ | |||
| BOOLEAN: "BOOLEAN", | |||
| FLOAT: "FLOAT", | |||
| INTEGER: "INTEGER", | |||
| NULL: "NULL", | |||
| STRING: "STRING", | |||
| REFERENCE: "REFERENCE", | |||
| SECTION: "SECTION", | |||
| } | |||
| func (this ValueType) String() string { | |||
| str := "" | |||
| if 0 <= this && this < ValueType(len(valueTypes)) { | |||
| str = valueTypes[this] | |||
| } | |||
| if str == "" { | |||
| str = "UNKNOWN" | |||
| } | |||
| return str | |||
| } | |||
| type Value interface { | |||
| GetType() ValueType | |||
| GetValue() interface{} | |||
| UpdateValue(interface{}) error | |||
| } | |||