1 #include "luaxx/state.h"
2 #include "mrt/exception.h"
3 #include <stdlib.h>
4 #include <lauxlib.h>
5 #include <assert.h>
6 #include "mrt/chunk.h"
7
8 using namespace luaxx;
9 /*
10 static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) {
11 if (nsize == 0) {
12 free(ptr);
13 return NULL;
14 } else {
15 return realloc(ptr, nsize);
16 }
17 }
18 */
19
check_error(lua_State * state,const int err)20 static void check_error(lua_State * state, const int err) {
21 switch(err) {
22 case 0:
23 return;
24 case LUA_ERRRUN:
25 case LUA_ERRERR:
26 case LUA_ERRSYNTAX: {
27 std::string error = lua_tostring(state, -1);
28 lua_pop(state, 1);
29 throw_ex(("lua error[%d]: %s", err, error.c_str()));
30 }
31 case LUA_ERRMEM:
32 throw_ex(("lua is out of memory"));
33 default:
34 throw_ex(("unknown lua error[%d]", err));
35 }
36 }
37
38 struct reader_state {
39 const mrt::Chunk &data;
40 size_t pos;
reader_statereader_state41 reader_state(const mrt::Chunk &data) :data(data), pos(0) {}
42 };
43
44
chunk_reader(lua_State * L,void * data,size_t * size)45 static const char * chunk_reader(lua_State *L, void *data, size_t *size) {
46 assert(size != NULL);
47 reader_state * x = (reader_state *) data;
48 if (x->pos < x->data.get_size()) {
49 *size = x->data.get_size();
50 const char *ptr = (const char *)x->data.get_ptr() + x->pos;
51 x->pos += *size;
52 return ptr;
53 }
54 *size = 0;
55 return NULL;
56 }
57
58
load(const std::string & fname,const mrt::Chunk & data)59 void State::load(const std::string &fname, const mrt::Chunk &data) {
60 //throw_ex(("implement me[%s]", fname.c_str()));
61 reader_state x(data);
62 int err = lua_load(state, chunk_reader, &x, fname.c_str());
63 check_error(state, err);
64 }
65
66
loadFile(const std::string & fname)67 void State::loadFile(const std::string &fname) {
68 int err = luaL_loadfile(state, fname.c_str());
69 if (err == LUA_ERRFILE)
70 throw_ex(("file '%s' not found", fname.c_str()));
71 check_error(state, err);
72 }
73
call(const int nargs,const int nresults) const74 void State::call(const int nargs, const int nresults) const {
75 int err = lua_pcall(state, nargs, nresults, 0);
76 //if (err == LUA_ERRRUN);
77 check_error(state, err);
78 }
79
init()80 void State::init() {
81 assert(state == NULL);
82
83 //state = lua_newstate(l_alloc, this);
84 state = lua_open();
85 if (state == NULL)
86 throw_ex(("cannot create lua interpreter"));
87
88 static const luaL_Reg libs[] = {
89 {"", luaopen_base},
90 //{LUA_LOADLIBNAME, luaopen_package},
91 {LUA_TABLIBNAME, luaopen_table},
92 //{LUA_IOLIBNAME, luaopen_io},
93 //{LUA_OSLIBNAME, luaopen_os},
94 {LUA_STRLIBNAME, luaopen_string},
95 {LUA_MATHLIBNAME, luaopen_math},
96 // {LUA_DBLIBNAME, luaopen_debug},
97 {NULL, NULL}
98 };
99
100 for (const luaL_Reg *lib = libs; lib->func; ++lib) {
101 lua_pushcfunction(state, lib->func);
102 lua_pushstring(state, lib->name);
103 int err = lua_pcall(state, 1, 0, 0);
104 check_error(state, err);
105 }
106 }
107
State()108 State::State() : state(NULL) {
109 init();
110 }
111
clear()112 void State::clear() {
113 lua_close(state);
114
115 state = NULL;
116 init();
117 }
118
~State()119 State::~State() {
120 if (state != NULL)
121 lua_close(state);
122 }
123
124
125