_ = subvalue
} else {
setValue(listElem, value)
}
}
} else {
key, value, _ = getKeyValue(lineno, line, false)
if key != "" {
elem = &Elem{}
root[key] = elem
}
if value != "" {
setValue(elem, value)
key = ""
}
}
}
return
}
func ParseFile(filename string) (*Data, error) {
input, err := ioutil.ReadFile(filename)
if err != nil {
return nil, err
}
return Parse(string(input))
}
func ParseDict(input string) map[string]string {
data := make(map[string]string)
for _, line := range strings.Split(input, "\n") {
line = strings.TrimSpace(line)
if strings.HasPrefix(line, "#") {
continue
}
split := strings.SplitN(line, ":", 2)
if len(split) != 2 {
continue
}
key := strings.TrimSpace(split[0])
value := strings.TrimSpace(split[1])
if len(key) == 0 || len(value) == 0 {
continue
}
data[key] = value
}
return data
}
func ParseDictFile(filename string) (map[string]string, error) {
input, err := ioutil.ReadFile(filename)
if err != nil {
return nil, err
}
return ParseDict(string(input)), nil
}
func getTypeName(typ int) (name string) {
switch typ {
case String:
name = "String"
case Bool:
name = "Bool"
case Float:
name = "Float"
case Int:
name = "Int"
case List:
name = "List"
case Map:
name = "Map"
case Null:
name = "Null"
}
return
}
func (data *Data) String() string {
buffer := &bytes.Buffer{}
for key, elem := range data.Root {
fmt.Fprintf(buffer, "%s: ", key)
elem.Display(buffer, " ")
buffer.WriteByte('\n')
}
return buffer.String()
}
func (data *Data) Get(key string, subkeys ...string) (elem *Elem, ok bool) {
elem, ok = data.Root[key]
if !ok {
return
}
for _, key := range subkeys {
if elem.Type != Map {
return elem, false
}
elem, ok = elem.Map[key]
}
return
}
func (data *Data) GetString(key string, subkeys ...string) (value string, ok bool) {
elem, ok := data.Get(key, subkeys...)
if !ok {
return
}
if elem.Type == String {
return elem.String, true
}
return
}
func (data *Data) GetBool(key string, subkeys ...string) (value bool, ok bool) {
elem, ok := data.Get(key, subkeys...)
if !ok {
return
}
if elem.Type == Bool {
return elem.Bool, true
}
return
}
func (data *Data) GetFloat(key string, subkeys ...string) (value float64, ok bool) {
elem, ok := data.Get(key, subkeys...)
if !ok {
return
}
if elem.Type == Float {
return elem.Float, true
}
return
}
func (data *Data) GetInt(key string, subkeys ...string) (value int64, ok bool) {
elem, ok := data.Get(key, subkeys...)
if !ok {
return
}
if elem.Type == Int {
return elem.Int, true
}
return
}
func (data *Data) GetList(key string, subkeys ...string) (value []*Elem, ok bool) {
elem, ok := data.Get(key, subkeys...)
if !ok {
return
}
if elem.Type == List {
return elem.List, true
}
return
}
func (data *Data) GetMap(key string, subkeys ...string) (value map[string]*Elem, ok bool) {
elem, ok := data.Get(key, subkeys...)
if !ok {
return
}
if elem.Type == Map {
return elem.Map, true
}
return
}
func (data *Data) GetStringList(key string, subkeys ...string) (value []string, ok bool) {
elem, ok := data.Get(key, subkeys...)
if !ok {
return
}
if elem.Type != List {
return
}
value = make([]string, len(elem.List))
i := 0
for _, listElem := range elem.List {
if listElem.Type == String {
value[i] = listElem.String
i += 1
}
}
return value, true
}
func (data *Data) Size() int {
return len(data.Root)
}
func (elem *Elem) Display(buffer *bytes.Buffer, indent string) {
switch elem.Type {
case String:
fmt.Fprintf(buffer, "%q", elem.String)
case Bool:
fmt.Fprintf(buffer, "%t", elem.Bool)
case Float:
fmt.Fprintf(buffer, "%f", elem.Float)
case Int:
fmt.Fprintf(buffer, "%d", elem.Int)
case List:
for _, listElem := range elem.List {
fmt.Fprintf(buffer, "\n%s- ", indent)
listElem.Display(buffer, indent+" ")
}
case Map:
for key, mapElem := range elem.Map {
fmt.Fprintf(buffer, "\n%s%s: ", indent, key)
mapElem.Display(buffer, indent+" ")
}
case Null:
fmt.Fprint(buffer, "null")
}
}