lovr/src/luax.c

151 lines
3.4 KiB
C

#include "luax.h"
#include "util.h"
#include <stdlib.h>
static int luax_pushobjectname(lua_State* L) {
lua_getfield(L, -1, "name");
return 1;
}
static void luax_pushobjectregistry(lua_State* L) {
lua_getfield(L, LUA_REGISTRYINDEX, "_lovrobjects");
// Create the registry if it doesn't exist yet
if (lua_isnil(L, -1)) {
lua_newtable(L);
lua_replace(L, -2);
// Create the metatable
lua_newtable(L);
// __mode = v
lua_pushstring(L, "v");
lua_setfield(L, -2, "__mode");
// Set the metatable
lua_setmetatable(L, -2);
// Write the table to the registry
lua_pushvalue(L, -1);
lua_setfield(L, LUA_REGISTRYINDEX, "_lovrobjects");
}
}
int luax_preloadmodule(lua_State* L, const char* key, lua_CFunction f) {
lua_getglobal(L, "package");
lua_getfield(L, -1, "preload");
lua_pushcfunction(L, f);
lua_setfield(L, -2, key);
lua_pop(L, 2);
return 0;
}
void luax_registertype(lua_State* L, const char* name, const luaL_Reg* functions) {
// Push metatable
luaL_newmetatable(L, name);
lua_getmetatable(L, -1);
// m.__index = m
lua_pushvalue(L, -1);
lua_setfield(L, -1, "__index");
// m.__gc = gc
lua_pushcfunction(L, luax_releasetype);
lua_setfield(L, -2, "__gc");
// m.name = name
lua_pushstring(L, name);
lua_setfield(L, -2, "name");
// m.__tostring
lua_pushcfunction(L, luax_pushobjectname);
lua_setfield(L, -2, "__tostring");
// Register class functions
if (functions) {
luaL_register(L, NULL, functions);
}
// Pop metatable
lua_pop(L, 1);
}
void luax_extendtype(lua_State* L, const char* base, const char* name, const luaL_Reg* baseFunctions, const luaL_Reg* functions) {
luax_registertype(L, name, functions);
luaL_getmetatable(L, name);
lua_pushstring(L, base);
lua_setfield(L, -2, "super");
if (baseFunctions) {
luaL_register(L, NULL, baseFunctions);
}
lua_pop(L, 1);
}
int luax_releasetype(lua_State* L) {
lovrRelease(*(Ref**) lua_touserdata(L, 1));
return 0;
}
// Find an object, pushing it onto the stack if it's found or leaving the stack unchanged otherwise.
int luax_getobject(lua_State* L, void* object) {
luax_pushobjectregistry(L);
lua_pushlightuserdata(L, object);
lua_gettable(L, -2);
if (lua_isnil(L, -1)) {
lua_pop(L, 2);
return 0;
} else {
lua_remove(L, -2);
return 1;
}
}
// Registers the userdata on the top of the stack in the object registry.
void luax_registerobject(lua_State* L, void* object) {
luax_pushobjectregistry(L);
lua_pushlightuserdata(L, object);
lua_pushvalue(L, -3);
lua_settable(L, -3);
lua_pop(L, 1);
lovrRetain(object);
}
void luax_pushenum(lua_State* L, map_int_t* map, int value) {
const char* key;
map_iter_t iter = map_iter(map);
while ((key = map_next(map, &iter))) {
if (*map_get(map, key) == value) {
lua_pushstring(L, key);
return;
}
}
lua_pushnil(L);
}
void* luax_checkenum(lua_State* L, int index, map_int_t* map, const char* typeName) {
const char* key = luaL_checkstring(L, index);
void* value = map_get(map, key);
if (!value) {
luaL_error(L, "Invalid %s '%s'", typeName, key);
return NULL;
}
return value;
}
void* luax_optenum(lua_State* L, int index, const char* fallback, map_int_t* map, const char* typeName) {
const char* key = luaL_optstring(L, index, fallback);
void* value = map_get(map, key);
if (!value) {
luaL_error(L, "Invalid %s '%s'", typeName, key);
return NULL;
}
return value;
}