Mercurial > code
comparison C++/Luae.cpp @ 182:15b264d9e833
Add Luae class
author | David Demelier <markand@malikania.fr> |
---|---|
date | Tue, 29 Oct 2013 21:32:20 +0100 |
parents | |
children | 258087829c66 |
comparison
equal
deleted
inserted
replaced
181:08af4f99c104 | 182:15b264d9e833 |
---|---|
1 /* | |
2 * Luae.cpp -- Lua helpers and such | |
3 * | |
4 * Copyright (c) 2011, 2012, 2013 David Demelier <markand@malikania.fr> | |
5 * | |
6 * Permission to use, copy, modify, and/or distribute this software for any | |
7 * purpose with or without fee is hereby granted, provided that the above | |
8 * copyright notice and this permission notice appear in all copies. | |
9 * | |
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
17 */ | |
18 | |
19 #include "Luae.h" | |
20 | |
21 void LuaeClass::createClass(lua_State *L, const LuaObject &cls) | |
22 { | |
23 LUA_STACK_CHECKBEGIN(L); | |
24 | |
25 // Already registered? | |
26 if (luaL_newmetatable(L, cls.name) == 0) | |
27 return; | |
28 | |
29 // Add it's "name" field | |
30 lua_pushstring(L, cls.name); | |
31 lua_setfield(L, -2, LUAE_CLASS_FIELDNAME); | |
32 | |
33 // Create a list of parent for a faster cast | |
34 lua_createtable(L, 0, 0); | |
35 | |
36 int i = 0; | |
37 for (auto p = cls.parent; p != nullptr; p = p->parent) { | |
38 lua_pushstring(L, p->name); | |
39 lua_rawseti(L, -2, ++i); | |
40 } | |
41 lua_setfield(L, -2, LUAE_CLASS_FIELDPARENTS); | |
42 | |
43 // Metamethods | |
44 if (cls.metamethods.size() > 0) | |
45 luaL_setfuncs(L, cls.metamethods.data(), 0); | |
46 | |
47 // Methods | |
48 lua_createtable(L, 0, 0); | |
49 | |
50 if (cls.methods.size() > 0) { | |
51 luaL_setfuncs(L, cls.methods.data(), 0); | |
52 } | |
53 | |
54 /* | |
55 * Add a metatable to this __index table so that if | |
56 * a method is not found it use the parent table recursively | |
57 */ | |
58 if (cls.parent) { | |
59 // 1. Get the parent | |
60 luaL_getmetatable(L, cls.parent->name); | |
61 assert(lua_type(L, -1) != LUA_TNIL); | |
62 | |
63 // 2. Create an anonymous metatable | |
64 lua_createtable(L, 1, 1); | |
65 | |
66 // 3. Get the __index field from this metatable | |
67 lua_getfield(L, -2, "__index"); | |
68 assert(lua_type(L, -1) != LUA_TNIL); | |
69 lua_setfield(L, -2, "__index"); | |
70 lua_setmetatable(L, -3); | |
71 lua_pop(L, 1); | |
72 } | |
73 | |
74 lua_setfield(L, -2, "__index"); | |
75 | |
76 // Pop that metatable | |
77 lua_pop(L, 1); | |
78 | |
79 LUA_STACK_CHECKEQUALS(L); | |
80 } | |
81 | |
82 /* -------------------------------------------------------- | |
83 * Luae public methods | |
84 * -------------------------------------------------------- */ | |
85 | |
86 void Luae::createEnum(lua_State *L, const LuaEnum *enumeration) | |
87 { | |
88 lua_createtable(L, 0, 0); | |
89 | |
90 for (int i = 0; enumeration[i].name != nullptr; ++i) { | |
91 lua_pushinteger(L, enumeration[i].value); | |
92 lua_setfield(L, -2, enumeration[i].name); | |
93 } | |
94 } | |
95 | |
96 void Luae::createLibrary(lua_State *L, const luaL_Reg *functions) | |
97 { | |
98 LUA_STACK_CHECKBEGIN(L); | |
99 | |
100 lua_createtable(L, 0, 0); | |
101 luaL_setfuncs(L, functions, 0); | |
102 | |
103 LUA_STACK_CHECKEND(L, - 1); | |
104 } | |
105 | |
106 template <> | |
107 bool Luae::getField(lua_State *L, int idx, const std::string & name) | |
108 { | |
109 bool value = false; | |
110 | |
111 lua_getfield(L, idx, name.c_str()); | |
112 if (lua_type(L, idx) == LUA_TBOOLEAN) | |
113 value = lua_toboolean(L, -1) == 1; | |
114 lua_pop(L, 1); | |
115 | |
116 return value; | |
117 } | |
118 | |
119 template <> | |
120 double Luae::getField(lua_State *L, int idx, const std::string & name) | |
121 { | |
122 double value = 0; | |
123 | |
124 lua_getfield(L, idx, name.c_str()); | |
125 if (lua_type(L, idx) == LUA_TNUMBER) | |
126 value = lua_tonumber(L, -1); | |
127 lua_pop(L, 1); | |
128 | |
129 return value; | |
130 } | |
131 | |
132 template <> | |
133 int Luae::getField(lua_State *L, int idx, const std::string & name) | |
134 { | |
135 int value = 0; | |
136 | |
137 lua_getfield(L, idx, name.c_str()); | |
138 if (lua_type(L, idx) == LUA_TNUMBER) | |
139 value = lua_tointeger(L, -1); | |
140 lua_pop(L, 1); | |
141 | |
142 return value; | |
143 } | |
144 | |
145 template <> | |
146 std::string Luae::getField(lua_State *L, int idx, const std::string & name) | |
147 { | |
148 std::string value; | |
149 | |
150 lua_getfield(L, idx, name.c_str()); | |
151 if (lua_type(L, idx) == LUA_TSTRING) | |
152 value = lua_tostring(L, -1); | |
153 lua_pop(L, 1); | |
154 | |
155 return value; | |
156 } | |
157 | |
158 void Luae::preload(lua_State *L, const std::string & name, lua_CFunction func) | |
159 { | |
160 LUA_STACK_CHECKBEGIN(L); | |
161 | |
162 lua_getglobal(L, "package"); | |
163 lua_getfield(L, -1, "preload"); | |
164 lua_pushcfunction(L, func); | |
165 lua_setfield(L, -2, name.c_str()); | |
166 lua_pop(L, 2); | |
167 | |
168 LUA_STACK_CHECKEQUALS(L); | |
169 } | |
170 | |
171 void Luae::readTable(lua_State *L, int idx, ReadFunction func) | |
172 { | |
173 lua_pushnil(L); | |
174 | |
175 if (idx < 0) | |
176 --idx; | |
177 | |
178 while (lua_next(L, idx)) { | |
179 func(L, lua_type(L, -2), lua_type(L, -1)); | |
180 lua_pop(L, 1); | |
181 } | |
182 | |
183 lua_pop(L, 1); | |
184 } | |
185 | |
186 int Luae::referenceField(lua_State *L, int idx, int type, const std::string & name) | |
187 { | |
188 int ref = LUA_REFNIL; | |
189 | |
190 lua_getfield(L, idx, name.c_str()); | |
191 | |
192 if (lua_type(L, -1) == type) { | |
193 lua_pushvalue(L, -1); | |
194 ref = luaL_ref(L, LUA_REGISTRYINDEX); | |
195 } | |
196 | |
197 lua_pop(L, 1); | |
198 | |
199 return ref; | |
200 } | |
201 | |
202 void Luae::require(lua_State *L, const std::string & name, lua_CFunction func, bool global) | |
203 { | |
204 LUA_STACK_CHECKBEGIN(L); | |
205 | |
206 luaL_requiref(L, name.c_str(), func, global); | |
207 lua_pop(L, 1); | |
208 | |
209 LUA_STACK_CHECKEQUALS(L); | |
210 } | |
211 | |
212 void * operator new(size_t size, lua_State *L) | |
213 { | |
214 return lua_newuserdata(L, size); | |
215 } | |
216 | |
217 void * operator new(size_t size, lua_State *L, const char *metaname) | |
218 { | |
219 void *object; | |
220 | |
221 object = lua_newuserdata(L, size); | |
222 luaL_setmetatable(L, metaname); | |
223 | |
224 return object; | |
225 } | |
226 | |
227 void operator delete(void *, lua_State *) | |
228 { | |
229 } | |
230 | |
231 void operator delete(void *, lua_State *L, const char *) | |
232 { | |
233 lua_pushnil(L); | |
234 lua_setmetatable(L, -2); | |
235 } |