CorsixTH engine (the C++ part)
Open source implementation of Theme Hospital
Loading...
Searching...
No Matches
th_lua.h
Go to the documentation of this file.
1/*
2Copyright (c) 2009 Peter "Corsix" Cawley
3
4Permission is hereby granted, free of charge, to any person obtaining a copy of
5this software and associated documentation files (the "Software"), to deal in
6the Software without restriction, including without limitation the rights to
7use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
8of the Software, and to permit persons to whom the Software is furnished to do
9so, subject to the following conditions:
10
11The above copyright notice and this permission notice shall be included in all
12copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20SOFTWARE.
21*/
22
23#ifndef CORSIX_TH_TH_LUA_H_
24#define CORSIX_TH_TH_LUA_H_
25#include "config.h"
26
27#include <cassert>
28#include <cstdio>
29#include <cstring>
30#include <initializer_list>
31#include <memory>
32#include <new>
33#include <type_traits>
34
35#include "lua.hpp"
36
38 public:
39 void operator()(lua_State* L) const { lua_close(L); }
40};
41
43using lua_state_unique_ptr = std::unique_ptr<lua_State, lua_state_deleter>;
44
45int luaopen_th(lua_State* L);
46
47// Print debugging helper functions
48
49void luaT_printvalue(lua_State* L, int idx);
50
52
53void luaT_printrawtable(lua_State* L, int idx);
54
56
59inline void luaT_rotate(lua_State* L, int idx, int n) {
60#if LUA_VERSION_NUM >= 503
61 lua_rotate(L, idx, n);
62#else
63 if (n < 0) {
64 if (idx < 0) {
65 idx = lua_gettop(L) + idx + 1;
66 }
67 n = lua_gettop(L) - idx + 1 + n;
68 }
69
70 for (int i = 0; i < n; i++) {
71 lua_insert(L, idx);
72 }
73#endif
74}
75
76// Compatibility layer for removal of environments in 5.2
77#if LUA_VERSION_NUM >= 502
79#else
81#endif
82
83inline int luaT_upvalueindex(int i) {
84#if LUA_VERSION_NUM >= 502
85 return lua_upvalueindex(i + 1);
86#else
87 return lua_upvalueindex(i);
88#endif
89}
90
92
100template <class Collection>
101inline void luaT_register(lua_State* L, const char* n, Collection& l) {
102#if LUA_VERSION_NUM >= 502
103 lua_createtable(L, 0, static_cast<int>(l.size()));
105 luaL_setfuncs(L, l.data(), 1);
106 lua_pushvalue(L, -1);
107 lua_setglobal(L, n);
108#else
109 luaL_register(L, n, l.data());
110#endif
111}
112
114
119inline void luaT_setfuncs(lua_State* L, const luaL_Reg* R) {
120#if LUA_VERSION_NUM >= 502
122 luaL_setfuncs(L, R, 1);
123#else
124 luaL_register(L, nullptr, R);
125#endif
126}
127
129#if LUA_VERSION_NUM >= 502
130 ++nups;
132 lua_insert(L, -nups);
134#else
136#endif
137}
138
140 luaT_pushcclosure(L, f, 0);
141}
142
143inline int luaT_cpcall(lua_State* L, lua_CFunction f, void* u) {
144#if LUA_VERSION_NUM >= 502
145 lua_checkstack(L, 2);
148 return lua_pcall(L, 1, 0, 0);
149#else
150 return lua_cpcall(L, f, u);
151#endif
152}
153
154// Compatibility for missing mode argument on lua_load in 5.1
155inline int luaT_load(lua_State* L, lua_Reader r, void* d, const char* s,
156 const char* m) {
157#if LUA_VERSION_NUM >= 502
158 return lua_load(L, r, d, s, m);
159#else
160 return lua_load(L, r, d, s);
161#endif
162}
163
164// Compatibility for older versions of lua_resume
165inline int luaT_resume(lua_State* L, lua_State* f, int n, int* nresults) {
166#if LUA_VERSION_NUM >= 504
167 return lua_resume(L, f, n, nresults);
168#elif LUA_VERSION_NUM >= 502
169 int res = lua_resume(L, f, n);
170 *nresults = lua_gettop(L);
171 return res;
172#else
173 int res = lua_resume(L, n);
174 *nresults = lua_gettop(L);
175 return res;
176#endif
177}
178
180
188template <typename T, typename... Ts>
190 return new (lua_newuserdata(L, sizeof(T))) T(args...);
191}
192
194
199const uint8_t* luaT_checkfile(lua_State* L, int idx, size_t* pDataLen);
200
202const char* luaT_checkstring(lua_State* L, int idx, size_t* pLength);
203
206
208
211void luaT_setenvfield(lua_State* L, int index, const char* k);
212
214
217void luaT_getenvfield(lua_State* L, int index, const char* k);
218
219template <class T, typename... Args>
221 bool env = false, Args&&... args) {
222 T* p = luaT_new<T>(L, std::forward<Args>(args)...);
224 lua_setmetatable(L, -2);
225 if (env) {
226 lua_newtable(L);
227 lua_setfenv(L, -2);
228 }
229 return p;
230}
231
232template <typename T>
234
235class render_target;
236template <>
238 static inline const char* name() { return "Surface"; }
239};
240
241class level_map;
242template <>
244 static inline const char* name() { return "Map"; }
245};
246
247class sprite_sheet;
248template <>
250 static inline const char* name() { return "SpriteSheet"; }
251};
252
253class animation;
254template <>
256 static inline const char* name() { return "Animation"; }
257};
258
260template <>
262 static inline const char* name() { return "Animator"; }
263};
264
265class palette;
266template <>
268 static inline const char* name() { return "Palette"; }
269};
270
271class raw_bitmap;
272template <>
274 static inline const char* name() { return "RawBitmap"; }
275};
276
277class font;
278template <>
280 static inline const char* name() { return "Font"; }
281};
282
283class bitmap_font;
284template <>
286 static inline const char* name() { return "BitmapFont"; }
287};
288
289class freetype_font;
290template <>
292 static inline const char* name() { return "FreeTypeFont"; }
293};
294
295struct layers;
296template <>
298 static inline const char* name() { return "Layers"; }
299};
300
301class pathfinder;
302template <>
304 static inline const char* name() { return "Pathfinder"; }
305};
306
307class cursor;
308template <>
310 static inline const char* name() { return "Cursor"; }
311};
312
313class line_sequence;
314template <>
316 static inline const char* name() { return "Line"; }
317};
318
319class music;
320template <>
322 static inline const char* name() { return "Music"; }
323};
324
325class sound_archive;
326template <>
328 static inline const char* name() { return "SoundArchive"; }
329};
330
331class sound_player;
332template <>
334 static inline const char* name() { return "SoundEffects"; }
335};
336
337class movie_player;
338template <>
340 static inline const char* name() { return "Movie"; }
341};
342
343class abstract_window;
344template <>
346 static inline const char* name() { return "WindowBase"; }
347};
348
350template <>
352 static inline const char* name() { return "SpriteRenderList"; }
353};
354
355class string_proxy;
356template <>
358 static inline const char* name() { return "StringProxy"; }
359};
360
361class lfs_ext;
362template <>
364 static inline const char* name() { return "LfsExt"; }
365};
366
367class iso_filesystem;
368template <>
370 static inline const char* name() { return "ISO Filesystem"; }
371};
372
374template <>
376 static inline const char* name() { return "MidiPlayer"; }
377};
378
379template <class T>
380T* luaT_testuserdata(lua_State* L, int idx, int mt_idx, bool required = true) {
381 // Turn mt_idx into an absolute index, as the stack size changes.
382 if (mt_idx > LUA_REGISTRYINDEX && mt_idx < 0) {
383 mt_idx = lua_gettop(L) + mt_idx + 1;
384 }
385
386 void* ud = lua_touserdata(L, idx);
387 if (ud != nullptr && lua_getmetatable(L, idx) != 0) {
388 while (true) {
389 if (lua_equal(L, mt_idx, -1) != 0) {
390 lua_pop(L, 1);
391 return static_cast<T*>(ud);
392 }
393 // Go up one inheritance level, if there is one.
394 if (lua_type(L, -1) != LUA_TTABLE) break;
395 lua_rawgeti(L, -1, 1);
396 lua_replace(L, -2);
397 }
398 lua_pop(L, 1);
399 }
400
401 if (required) {
402 const char* msg =
403 lua_pushfstring(L, "%s expected, got %s", luaT_classinfo<T>::name(),
404 luaL_typename(L, idx));
405 luaL_argerror(L, idx, msg);
406 assert(false); // unreachable
407 }
408 return nullptr;
409}
410
411template <class T>
412T* luaT_testuserdata(lua_State* L, int idx = 1, bool required = true) {
414 if (idx > 1) iMetaIndex = luaT_upvalueindex(idx - 1);
416}
417
418template <class T, int mt>
420 T* p = luaT_testuserdata<T>(L, 1, mt, false);
421 if (p != nullptr) {
422 p->~T();
423 }
424 return 0;
425}
426
427void luaT_execute(lua_State* L, const char* sLuaString);
428void luaT_execute_loadstring(lua_State* L, const char* sLuaString);
429
431void luaT_push(lua_State* L, int i);
432void luaT_push(lua_State* L, const char* s);
433
434template <class T>
435void luaT_execute(lua_State* L, const char* sLuaString, T arg) {
437 luaT_push(L, arg);
438 lua_call(L, 1, LUA_MULTRET);
439}
440
441template <class T1, class T2>
442void luaT_execute(lua_State* L, const char* sLuaString, T1 arg1, T2 arg2) {
444 luaT_push(L, arg1);
445 luaT_push(L, arg2);
446 lua_call(L, 2, LUA_MULTRET);
447}
448
449template <class T1, class T2, class T3>
451 T3 arg3) {
453 luaT_push(L, arg1);
454 luaT_push(L, arg2);
455 luaT_push(L, arg3);
456 lua_call(L, 3, LUA_MULTRET);
457}
458
459template <class T1, class T2, class T3, class T4>
461 T3 arg3, T4 arg4) {
463 luaT_push(L, arg1);
464 luaT_push(L, arg2);
465 luaT_push(L, arg3);
466 luaT_push(L, arg4);
467 lua_call(L, 4, LUA_MULTRET);
468}
469
470void luaT_pushtablebool(lua_State* L, const char* k, bool v);
471
472void preload_lua_package(lua_State* L, const char* name, lua_CFunction fn);
473
474namespace {
475int luaT_get_userdata_classname(lua_State* L, int idx, const char** class_name,
476 void** userdata) {
477 void* p = lua_touserdata(L, idx);
478 *userdata = p;
479 if (p == nullptr) {
480 return 0;
481 }
482 int added_stack = 0;
483 if (lua_getmetatable(L, idx) == 0) {
484 std::printf("Warn: No metatable for userdata\n");
485 return 0;
486 }
487 lua_getfield(L, -1, "__index");
488 added_stack += 2; // metadata and field
489 if (lua_type(L, -1) != LUA_TTABLE) {
491 std::printf("Warn: No __index field method table for userdata\n");
492 return 0;
493 }
494
495 if (lua_getmetatable(L, -1) == 0) {
497 std::printf("Warn: No metatable for method table of userdata\n");
498 return 0;
499 }
500 lua_getfield(L, -1, "__class_name");
501 added_stack += 2; // method metatable and class name field
502 if (lua_type(L, -1) != LUA_TSTRING) {
504 std::printf("Warn: No __class_name field for userdata\n");
505 return 0;
506 }
507 *class_name = lua_tostring(L, -1);
508
509 return added_stack;
510}
511} // namespace
512
513// Find the appropriate derived class of base for a given
514// userdata object.
515//
516// th_lua_internal.h defines our c++ binding class metatables:
517// metatable: { __index = method_table, ... }
518// method_table: { ... }
519// method_table metatable: { __class_name = class_name }
520template <typename B, typename T1, typename T2>
522 const std::initializer_list<const char*>& class_names) {
523 static_assert(std::is_base_of<B, T1>::value, "B must be a base class for T1");
524 static_assert(std::is_base_of<B, T2>::value, "B must be a base class for T2");
525
526 const char* class_name = nullptr;
527 void* p;
528
529 int stack = luaT_get_userdata_classname(L, idx, &class_name, &p);
530 if (class_name == nullptr) {
531 return nullptr;
532 }
533
534 auto it = class_names.begin();
535 if (std::strcmp(class_name, *it) == 0) {
536 lua_pop(L, stack);
537 return static_cast<T1*>(p);
538 }
539 it++;
540 if (std::strcmp(class_name, *it) == 0) {
541 lua_pop(L, stack);
542 return static_cast<T2*>(p);
543 }
544 std::printf("Warn: Unknown class name for usertype %s\n", class_name);
545 lua_pop(L, stack);
546 return nullptr;
547}
548
549#endif // CORSIX_TH_TH_LUA_H_
Definition th_lua_ui.cpp:39
Theme Hospital sprite animation manager.
Definition th_gfx.h:234
Definition th_gfx.h:497
Definition th_gfx_font.h:139
Definition th_gfx_sdl.h:694
Definition th_gfx_font.h:81
Adaptor around the FreeType2 library to a THFont.
Definition th_gfx_font.h:198
Layer for reading Theme Hospital files out of an .iso disk image.
Definition iso_fs.h:43
Definition th_map.h:252
Definition th_lua_lfs_ext.cpp:31
Definition th_gfx_sdl.h:715
Definition th_lua.h:37
void operator()(lua_State *L) const
Definition th_lua.h:39
Definition th_movie.h:299
Definition sdl_audio.cpp:43
8bpp palette class.
Definition th_gfx_sdl.h:68
Finds paths through maps.
Definition th_pathfind.h:243
Stored image.
Definition th_gfx_sdl.h:440
Definition th_gfx_sdl.h:247
Utility class for accessing Theme Hospital's SOUND-0.DAT.
Definition th_sound.h:35
Definition th_sound.h:65
Definition th_gfx.h:598
Sheet of sprites.
Definition th_gfx_sdl.h:504
Definition th_lua_strings.cpp:60
Definition th_lua_midi.cpp:88
uint32_t mt[N]
Definition random.c:61
Layer information (see animation_manager::draw_frame)
Definition th_gfx.h:190
static const char * name()
Definition th_lua.h:346
static const char * name()
Definition th_lua.h:256
static const char * name()
Definition th_lua.h:262
static const char * name()
Definition th_lua.h:286
static const char * name()
Definition th_lua.h:310
static const char * name()
Definition th_lua.h:280
static const char * name()
Definition th_lua.h:292
static const char * name()
Definition th_lua.h:370
static const char * name()
Definition th_lua.h:298
static const char * name()
Definition th_lua.h:244
static const char * name()
Definition th_lua.h:364
static const char * name()
Definition th_lua.h:316
static const char * name()
Definition th_lua.h:340
static const char * name()
Definition th_lua.h:322
static const char * name()
Definition th_lua.h:268
static const char * name()
Definition th_lua.h:304
static const char * name()
Definition th_lua.h:274
static const char * name()
Definition th_lua.h:238
static const char * name()
Definition th_lua.h:328
static const char * name()
Definition th_lua.h:334
static const char * name()
Definition th_lua.h:352
static const char * name()
Definition th_lua.h:250
static const char * name()
Definition th_lua.h:358
static const char * name()
Definition th_lua.h:376
Definition th_lua.h:233
void luaT_rotate(lua_State *L, int idx, int n)
Lua 5.3 lua_rotate backported to 5.1+.
Definition th_lua.h:59
const char * luaT_checkstring(lua_State *L, int idx, size_t *pLength)
Check that a Lua argument is a string or a proxied string.
Definition th_lua_strings.cpp:624
int luaT_upvalueindex(int i)
Definition th_lua.h:83
int luaT_resume(lua_State *L, lua_State *f, int n, int *nresults)
Definition th_lua.h:165
T * luaT_stdnew(lua_State *L, int mt_idx=luaT_environindex, bool env=false, Args &&... args)
Definition th_lua.h:220
void luaT_execute(lua_State *L, const char *sLuaString)
Definition th_lua.cpp:401
int luaT_stdgc(lua_State *L)
Definition th_lua.h:419
const uint8_t * luaT_checkfile(lua_State *L, int idx, size_t *pDataLen)
Check that a Lua argument is a binary data blob.
Definition th_lua.cpp:155
void luaT_pushcclosure(lua_State *L, lua_CFunction f, int nups)
Definition th_lua.h:128
int luaT_load(lua_State *L, lua_Reader r, void *d, const char *s, const char *m)
Definition th_lua.h:155
void luaT_execute_loadstring(lua_State *L, const char *sLuaString)
Definition th_lua.cpp:360
const int luaT_environindex
Definition th_lua.h:80
int luaopen_th(lua_State *L)
Definition th_lua.cpp:320
T * luaT_new(lua_State *L, Ts... args)
Version of operator new which allocates into a Lua userdata.
Definition th_lua.h:189
int luaT_cpcall(lua_State *L, lua_CFunction f, void *u)
Definition th_lua.h:143
void luaT_getenvfield(lua_State *L, int index, const char *k)
Get a field from the environment table of a value.
Definition th_lua.cpp:65
void luaT_printrawtable(lua_State *L, int idx)
Definition th_lua.cpp:455
void luaT_push(lua_State *L, lua_CFunction f)
Definition th_lua.cpp:412
void luaT_setenvfield(lua_State *L, int index, const char *k)
Set a field on the environment table of a value.
Definition th_lua.cpp:56
std::unique_ptr< lua_State, lua_state_deleter > lua_state_unique_ptr
Unique pointer for lua_State.
Definition th_lua.h:43
void preload_lua_package(lua_State *L, const char *name, lua_CFunction fn)
Definition th_lua.cpp:406
void luaT_register(lua_State *L, const char *n, Collection &l)
Compatibility function for Lua 5.1 luaL_register.
Definition th_lua.h:101
T * luaT_testuserdata(lua_State *L, int idx, int mt_idx, bool required=true)
Definition th_lua.h:380
void luaT_printvalue(lua_State *L, int idx)
Definition th_lua.cpp:424
void luaT_pushcclosuretable(lua_State *L, lua_CFunction fn, int n)
Push a C closure as a callable table.
Definition th_lua.cpp:143
void luaT_setfuncs(lua_State *L, const luaL_Reg *R)
Register functions into the table on top of the stack.
Definition th_lua.h:119
void luaT_printstack(lua_State *L)
Definition th_lua.cpp:442
void luaT_pushtablebool(lua_State *L, const char *k, bool v)
Definition th_lua.cpp:418
B * luaT_touserdata_base(lua_State *L, int idx, const std::initializer_list< const char * > &class_names)
Definition th_lua.h:521
void luaT_pushcfunction(lua_State *L, lua_CFunction f)
Definition th_lua.h:139