forked from mitchellh/go-libucl
-
Notifications
You must be signed in to change notification settings - Fork 0
/
object.go
179 lines (145 loc) · 4.02 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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
package libucl
import "unsafe"
// #include "go-libucl.h"
import "C"
// Object represents a single object within a configuration.
type Object struct {
object *C.ucl_object_t
}
// ObjectIter is an interator for objects.
type ObjectIter struct {
expand bool
object *C.ucl_object_t
iter C.ucl_object_iter_t
}
// ObjectType is an enum of the type that an Object represents.
type ObjectType int
const (
ObjectTypeObject ObjectType = iota
ObjectTypeArray
ObjectTypeInt
ObjectTypeFloat
ObjectTypeString
ObjectTypeBoolean
ObjectTypeTime
ObjectTypeUserData
ObjectTypeNull
)
// Emitter is a type of built-in emitter that can be used to convert
// an object to another config format.
type Emitter int
const (
EmitJSON Emitter = iota
EmitJSONCompact
EmitConfig
EmitYAML
)
// Free the memory associated with the object. This must be called when
// you're done using it.
func (o *Object) Close() error {
C.ucl_object_unref(o.object)
return nil
}
// Emit converts this object to another format and returns it.
func (o *Object) Emit(t Emitter) (string, error) {
result := C.ucl_object_emit(o.object, uint32(t))
if result == nil {
return "", nil
}
return C.GoString(C._go_uchar_to_char(result)), nil
}
// Delete removes the given key from the object. The key will automatically
// be dereferenced once when this is called.
func (o *Object) Delete(key string) {
ckey := C.CString(key)
defer C.free(unsafe.Pointer(ckey))
C.ucl_object_delete_key(o.object, ckey)
}
func (o *Object) Get(key string) *Object {
ckey := C.CString(key)
defer C.free(unsafe.Pointer(ckey))
obj := C.ucl_object_find_keyl(o.object, ckey, C.size_t(len(key)))
if obj == nil {
return nil
}
result := &Object{object: obj}
result.Ref()
return result
}
// Iterate over the objects in this object.
//
// The iterator must be closed when it is finished.
//
// The iterator does not need to be fully consumed.
func (o *Object) Iterate(expand bool) *ObjectIter {
// Increase the ref count
C.ucl_object_ref(o.object)
return &ObjectIter{
expand: expand,
object: o.object,
iter: nil,
}
}
// Returns the key of this value/object as a string, or the empty
// string if the object doesn't have a key.
func (o *Object) Key() string {
return C.GoString(C.ucl_object_key(o.object))
}
// Len returns the length of the object, or how many elements are part
// of this object.
//
// For objects, this is the number of key/value pairs.
// For arrays, this is the number of elements.
func (o *Object) Len() uint {
// This is weird. If the object is an object and it has a "next",
// then it is actually an array of objects, and to get the count
// we actually need to iterate and count.
if o.Type() == ObjectTypeObject && o.object.next != nil {
iter := o.Iterate(false)
defer iter.Close()
var count uint = 0
for obj := iter.Next(); obj != nil; obj = iter.Next() {
obj.Close()
count += 1
}
return count
}
return uint(o.object.len)
}
// Increments the ref count associated with this. You have to call
// close an additional time to free the memory.
func (o *Object) Ref() error {
C.ucl_object_ref(o.object)
return nil
}
// Returns the type that this object represents.
func (o *Object) Type() ObjectType {
return ObjectType(C.ucl_object_type(o.object))
}
//------------------------------------------------------------------------
// Conversion Functions
//------------------------------------------------------------------------
func (o *Object) ToBool() bool {
return bool(C.ucl_object_toboolean(o.object))
}
func (o *Object) ToInt() int64 {
return int64(C.ucl_object_toint(o.object))
}
func (o *Object) ToFloat() float64 {
return float64(C.ucl_object_todouble(o.object))
}
func (o *Object) ToString() string {
return C.GoString(C.ucl_object_tostring(o.object))
}
func (o *ObjectIter) Close() {
C.ucl_object_unref(o.object)
}
func (o *ObjectIter) Next() *Object {
obj := C.ucl_iterate_object(o.object, &o.iter, C._Bool(o.expand))
if obj == nil {
return nil
}
// Increase the ref count so we have to free it
C.ucl_object_ref(obj)
return &Object{object: obj}
}