2016-04-13 16:17:57 +09:00

129 lines
2.3 KiB
Go

package hcl
import (
"fmt"
"strings"
)
//go:generate stringer -type=ValueType
// ValueType is an enum represnting the type of a value in
// a LiteralNode.
type ValueType byte
const (
ValueTypeUnknown ValueType = iota
ValueTypeFloat
ValueTypeInt
ValueTypeString
ValueTypeBool
ValueTypeNil
ValueTypeList
ValueTypeObject
)
// Object represents any element of HCL: an object itself, a list,
// a literal, etc.
type Object struct {
Key string
Type ValueType
Value interface{}
Next *Object
}
// GoString is an implementation of the GoStringer interface.
func (o *Object) GoString() string {
return fmt.Sprintf("*%#v", *o)
}
// Get gets all the objects that match the given key.
//
// It returns the resulting objects as a single Object structure with
// the linked list populated.
func (o *Object) Get(k string, insensitive bool) *Object {
if o.Type != ValueTypeObject {
return nil
}
for _, o := range o.Elem(true) {
if o.Key != k {
if !insensitive || !strings.EqualFold(o.Key, k) {
continue
}
}
return o
}
return nil
}
// Elem returns all the elements that are part of this object.
func (o *Object) Elem(expand bool) []*Object {
if !expand {
result := make([]*Object, 0, 1)
current := o
for current != nil {
obj := *current
obj.Next = nil
result = append(result, &obj)
current = current.Next
}
return result
}
if o.Value == nil {
return nil
}
switch o.Type {
case ValueTypeList:
return o.Value.([]*Object)
case ValueTypeObject:
result := make([]*Object, 0, 5)
for _, obj := range o.Elem(false) {
result = append(result, obj.Value.([]*Object)...)
}
return result
default:
return []*Object{o}
}
}
// Len returns the number of objects in this object structure.
func (o *Object) Len() (i int) {
current := o
for current != nil {
i += 1
current = current.Next
}
return
}
// ObjectList is a list of objects.
type ObjectList []*Object
// Flat returns a flattened list structure of the objects.
func (l ObjectList) Flat() []*Object {
m := make(map[string]*Object)
result := make([]*Object, 0, len(l))
for _, obj := range l {
prev, ok := m[obj.Key]
if !ok {
m[obj.Key] = obj
result = append(result, obj)
continue
}
for prev.Next != nil {
prev = prev.Next
}
prev.Next = obj
}
return result
}