summaryrefslogtreecommitdiff
path: root/lua.go
blob: 874dac8ee12bfc4f7d44acbd7f68c160f8c90035 (plain)
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
package main

/*
#cgo LDFLAGS: -llua
#include <stdlib.h>
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
*/
import "C"
import (
	"errors"
	"unsafe"
)

type LuaRef C.longlong
type Lua struct {
	l *C.lua_State
}

func (l *Lua) Start () {
	l.l = C.luaL_newstate()
	C.luaL_openlibs(l.l)
}

func (l *Lua) Close () {
	C.lua_close(l.l)
	C.free(unsafe.Pointer(l.l))
}

func (l *Lua) Require (file string) (LuaRef, error) {
	if !l.LoadFile(file) {
		return 0, errors.New("could not open the file")
	}
	if !l.PCall(0, C.LUA_MULTRET) {
		return 0, errors.New("could not execute the file")
	}
	if !l.IsTable(-1) {
		return 0, errors.New("module did not return a table")
	}
	return l.PopToRef(), nil
}


func (l *Lua) PCall (nargs int, nresults int) bool {
	res := C.lua_pcallk(l.l, C.int(nargs), C.int(nresults), 0, 0, nil)
	return res == C.LUA_OK
}

func (l *Lua) LoadFile (file string) bool {
	cfile := C.CString(file)
	defer C.free(unsafe.Pointer(cfile))
	res := C.luaL_loadfilex(l.l, cfile, nil)
	return res == C.LUA_OK
}

func (l *Lua) StackLen () int {
	return int(C.lua_gettop(l.l))
}

func (l *Lua) ToString (index int) string {
	return C.GoString(C.lua_tolstring(l.l, C.int(index), nil))
}

func (l *Lua) ToInt (index int) int {
	return int(C.lua_tonumberx(l.l, C.int(index), nil))
}

func (l *Lua) PopToRef () LuaRef {
	return LuaRef(C.luaL_ref(l.l, C.LUA_REGISTRYINDEX))
}

func (l *Lua) Pop (n int) {
	C.lua_settop(l.l, C.int(-n - 1))
}

func (l *Lua) PushNil () {
	C.lua_pushnil(l.l)
}

func (l *Lua) PushString (str string) {
	cstr := C.CString(str)
	defer C.free(unsafe.Pointer(cstr))
	C.lua_pushstring(l.l, cstr)
}

func (l *Lua) PushTable (table map[string]string) {
	C.lua_createtable(l.l, 0, C.int(len(table)))
	for k, v := range table {
		l.PushString(v)
		C.lua_setfield(l.l, -2, C.CString(k))
	}
}

func (l *Lua) PushFromRef (ref LuaRef) {
	C.lua_rawgeti(l.l, C.LUA_REGISTRYINDEX, C.longlong(ref));
}

func (l *Lua) IsString (index int) bool {
	return C.lua_isstring(l.l, C.int(index)) == 1
}

func (l *Lua) IsNumber (index int) bool {
	return C.lua_isnumber(l.l, C.int(index)) == 1
}

func (l *Lua) IsFunction (index int) bool {
	return C.lua_type(l.l, C.int(index)) == C.LUA_TFUNCTION
}

func (l *Lua) IsTable (index int) bool {
	return C.lua_type(l.l, C.int(index)) == C.LUA_TTABLE
}

func (l *Lua) Next () bool {
	return C.lua_next(l.l, -2) != 0
}

func (l *Lua) PushTableItem (key string) {
	ckey := C.CString(key)
	defer C.free(unsafe.Pointer(ckey))
	C.lua_pushstring(l.l, ckey);
	C.lua_gettable(l.l, -2);
}