-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
108 lines (80 loc) · 2.39 KB
/
main.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
// =================================================================
//
// Copyright (C) 2019 Spatial Current, Inc. - All Rights Reserved
// Released as open source under the MIT License. See LICENSE file.
//
// =================================================================
// dfl.so creates a shared library of Go that can be called by C, C++, or Python
//
package main
import (
"C"
"fmt"
"unsafe"
)
import (
"github.com/spatialcurrent/go-dfl/pkg/dfl"
)
func main() {}
//export Format
func Format(expression *C.char, outputString **C.char) *C.char {
node, _, err := dfl.Parse(C.GoString(expression))
if err != nil {
return C.CString(err.Error())
}
*outputString = C.CString(node.Dfl(dfl.DefaultQuotes, false, 0))
return nil
}
func buildContext(argc C.int, argv **C.char) map[string]interface{} {
length := int(argc)
if length == 0 {
return map[string]interface{}{}
}
// Instead of using [1 << 30] using [(1 << 29) - 1] instead
// as a workaround for 32 bit architectures
// https://github.com/docker/docker-credential-helpers/pull/61
// https://github.com/golang/go/wiki/cgo#turning-c-arrays-into-go-slices
tmpslice := (*[(1 << 29) - 1]*C.char)(unsafe.Pointer(argv))[:length:length]
vars := make([]string, length)
for i, s := range tmpslice {
vars[i] = C.GoString(s)
}
ctx := map[string]interface{}{}
for i := 0; i < len(vars)/2; i++ {
ctx[vars[i*2]] = dfl.TryConvertString(vars[i*2+1])
}
return ctx
}
//export EvaluateBool
func EvaluateBool(exp *C.char, argc C.int, argv **C.char, result *C.int) *C.char {
fmt.Println("argc", argc, "argv", argv)
node, err := dfl.ParseCompile(C.GoString(exp))
if err != nil {
return C.CString(err.Error())
}
vars := map[string]interface{}{}
_, r, err := dfl.EvaluateBool(node, vars, buildContext(argc, argv), dfl.NewFuntionMapWithDefaults(), dfl.DefaultQuotes)
if err != nil {
return C.CString(err.Error())
}
if r {
*result = 1
} else {
*result = 0
}
return nil
}
//export EvaluateString
func EvaluateString(exp *C.char, argc C.int, argv **C.char, result **C.char) *C.char {
node, err := dfl.ParseCompile(C.GoString(exp))
if err != nil {
return C.CString(err.Error())
}
vars := map[string]interface{}{}
_, r, err := node.Evaluate(vars, buildContext(argc, argv), dfl.NewFuntionMapWithDefaults(), dfl.DefaultQuotes)
if err != nil {
return C.CString(err.Error())
}
*result = C.CString(fmt.Sprint(r))
return nil
}