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