/
object.go
128 lines (107 loc) · 2.27 KB
/
object.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
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
}