mirror of
https://github.com/Llewellynvdm/conky.git
synced 2025-01-28 17:48:39 +00:00
623 lines
12 KiB
C
623 lines
12 KiB
C
/* tolua: functions to check types.
|
|
** Support code for Lua bindings.
|
|
** Written by Waldemar Celes
|
|
** TeCGraf/PUC-Rio
|
|
** Apr 2003
|
|
** $Id: $
|
|
*/
|
|
|
|
/* This code is free software; you can redistribute it and/or modify it.
|
|
** The software provided hereunder is on an "as is" basis, and
|
|
** the author has no obligation to provide maintenance, support, updates,
|
|
** enhancements, or modifications.
|
|
*/
|
|
|
|
#include "tolua++.h"
|
|
#include "lauxlib.h"
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
/* a fast check if a is b, without parameter validation
|
|
i.e. if b is equal to a or a superclass of a. */
|
|
TOLUA_API int tolua_fast_isa(lua_State *L, int mt_indexa, int mt_indexb, int super_index)
|
|
{
|
|
int result;
|
|
if (lua_rawequal(L, mt_indexa, mt_indexb))
|
|
result = 1;
|
|
else
|
|
{
|
|
if (super_index)
|
|
{
|
|
lua_pushvalue(L, super_index);
|
|
}
|
|
else
|
|
{
|
|
lua_pushliteral(L, "tolua_super");
|
|
lua_rawget(L, LUA_REGISTRYINDEX); /* stack: super */
|
|
}
|
|
lua_pushvalue(L, mt_indexa); /* stack: super mta */
|
|
lua_rawget(L, -2); /* stack: super super[mta] */
|
|
lua_pushvalue(L, mt_indexb); /* stack: super super[mta] mtb */
|
|
lua_rawget(L, LUA_REGISTRYINDEX); /* stack: super super[mta] typenameB */
|
|
lua_rawget(L, -2); /* stack: super super[mta] bool */
|
|
result = lua_toboolean(L, -1);
|
|
lua_pop(L, 3);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/* Push and returns the corresponding object typename */
|
|
TOLUA_API const char *tolua_typename(lua_State *L, int lo)
|
|
{
|
|
int tag = lua_type(L, lo);
|
|
if (tag == LUA_TNONE)
|
|
lua_pushstring(L, "[no object]");
|
|
else if (tag != LUA_TUSERDATA && tag != LUA_TTABLE)
|
|
lua_pushstring(L, lua_typename(L, tag));
|
|
else if (tag == LUA_TUSERDATA)
|
|
{
|
|
if (!lua_getmetatable(L, lo))
|
|
lua_pushstring(L, lua_typename(L, tag));
|
|
else
|
|
{
|
|
lua_rawget(L, LUA_REGISTRYINDEX);
|
|
if (!lua_isstring(L, -1))
|
|
{
|
|
lua_pop(L, 1);
|
|
lua_pushstring(L, "[undefined]");
|
|
}
|
|
}
|
|
}
|
|
else /* is table */
|
|
{
|
|
lua_pushvalue(L, lo);
|
|
lua_rawget(L, LUA_REGISTRYINDEX);
|
|
if (!lua_isstring(L, -1))
|
|
{
|
|
lua_pop(L, 1);
|
|
lua_pushstring(L, "table");
|
|
}
|
|
else
|
|
{
|
|
lua_pushstring(L, "class ");
|
|
lua_insert(L, -2);
|
|
lua_concat(L, 2);
|
|
}
|
|
}
|
|
return lua_tostring(L, -1);
|
|
}
|
|
|
|
TOLUA_API void tolua_error(lua_State *L, const char *msg, tolua_Error *err)
|
|
{
|
|
if (msg[0] == '#')
|
|
{
|
|
const char *expected = err->type;
|
|
const char *provided = tolua_typename(L, err->index);
|
|
if (msg[1] == 'f')
|
|
{
|
|
int narg = err->index;
|
|
if (err->array)
|
|
luaL_error(L, "%s\n argument #%d is array of '%s'; array of '%s' expected.\n",
|
|
msg + 2, narg, provided, expected);
|
|
else
|
|
luaL_error(L, "%s\n argument #%d is '%s'; '%s' expected.\n",
|
|
msg + 2, narg, provided, expected);
|
|
}
|
|
else if (msg[1] == 'v')
|
|
{
|
|
if (err->array)
|
|
luaL_error(L, "%s\n value is array of '%s'; array of '%s' expected.\n",
|
|
msg + 2, provided, expected);
|
|
else
|
|
luaL_error(L, "%s\n value is '%s'; '%s' expected.\n",
|
|
msg + 2, provided, expected);
|
|
}
|
|
}
|
|
else
|
|
luaL_error(L, msg);
|
|
}
|
|
|
|
/* the equivalent of lua_is* for usertable */
|
|
static int lua_isusertable(lua_State *L, int lo, const char *type)
|
|
{
|
|
int r = 0;
|
|
if (lo < 0)
|
|
lo = lua_gettop(L) + lo + 1;
|
|
lua_pushvalue(L, lo);
|
|
lua_rawget(L, LUA_REGISTRYINDEX); /* get registry[t] */
|
|
if (lua_isstring(L, -1))
|
|
{
|
|
r = strcmp(lua_tostring(L, -1), type) == 0;
|
|
if (!r)
|
|
{
|
|
/* try const */
|
|
lua_pushstring(L, "const ");
|
|
lua_insert(L, -2);
|
|
lua_concat(L, 2);
|
|
r = lua_isstring(L, -1) && strcmp(lua_tostring(L, -1), type) == 0;
|
|
}
|
|
}
|
|
lua_pop(L, 1);
|
|
return r;
|
|
}
|
|
|
|
int push_table_instance(lua_State *L, int lo)
|
|
{
|
|
|
|
if (lua_istable(L, lo))
|
|
{
|
|
|
|
lua_pushstring(L, ".c_instance");
|
|
lua_gettable(L, lo);
|
|
if (lua_isuserdata(L, -1))
|
|
{
|
|
|
|
lua_replace(L, lo);
|
|
return 1;
|
|
}
|
|
else
|
|
{
|
|
|
|
lua_pop(L, 1);
|
|
return 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* the equivalent of lua_is* for usertype */
|
|
static int lua_isusertype(lua_State *L, int lo, const char *type)
|
|
{
|
|
if (!lua_isuserdata(L, lo))
|
|
{
|
|
if (!push_table_instance(L, lo))
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
{
|
|
/* check if it is of the same type */
|
|
int r;
|
|
const char *tn;
|
|
if (lua_getmetatable(L, lo)) /* if metatable? */
|
|
{
|
|
lua_rawget(L, LUA_REGISTRYINDEX); /* get registry[mt] */
|
|
tn = lua_tostring(L, -1);
|
|
r = tn && (strcmp(tn, type) == 0);
|
|
lua_pop(L, 1);
|
|
if (r)
|
|
return 1;
|
|
else
|
|
{
|
|
/* check if it is a specialized class */
|
|
lua_pushstring(L, "tolua_super");
|
|
lua_rawget(L, LUA_REGISTRYINDEX); /* get super */
|
|
lua_getmetatable(L, lo);
|
|
lua_rawget(L, -2); /* get super[mt] */
|
|
if (lua_istable(L, -1))
|
|
{
|
|
int b;
|
|
lua_pushstring(L, type);
|
|
lua_rawget(L, -2); /* get super[mt][type] */
|
|
b = lua_toboolean(L, -1);
|
|
lua_pop(L, 3);
|
|
if (b)
|
|
return 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
TOLUA_API int tolua_isnoobj(lua_State *L, int lo, tolua_Error *err)
|
|
{
|
|
if (lua_gettop(L) < abs(lo))
|
|
return 1;
|
|
err->index = lo;
|
|
err->array = 0;
|
|
err->type = "[no object]";
|
|
return 0;
|
|
}
|
|
|
|
TOLUA_API int tolua_isboolean(lua_State *L, int lo, int def, tolua_Error *err)
|
|
{
|
|
if (def && lua_gettop(L) < abs(lo))
|
|
return 1;
|
|
if (lua_isnil(L, lo) || lua_isboolean(L, lo))
|
|
return 1;
|
|
err->index = lo;
|
|
err->array = 0;
|
|
err->type = "boolean";
|
|
return 0;
|
|
}
|
|
|
|
TOLUA_API int tolua_isnumber(lua_State *L, int lo, int def, tolua_Error *err)
|
|
{
|
|
if (def && lua_gettop(L) < abs(lo))
|
|
return 1;
|
|
if (lua_isnumber(L, lo))
|
|
return 1;
|
|
err->index = lo;
|
|
err->array = 0;
|
|
err->type = "number";
|
|
return 0;
|
|
}
|
|
|
|
TOLUA_API int tolua_isstring(lua_State *L, int lo, int def, tolua_Error *err)
|
|
{
|
|
if (def && lua_gettop(L) < abs(lo))
|
|
return 1;
|
|
if (lua_isnil(L, lo) || lua_isstring(L, lo))
|
|
return 1;
|
|
err->index = lo;
|
|
err->array = 0;
|
|
err->type = "string";
|
|
return 0;
|
|
}
|
|
|
|
TOLUA_API int tolua_istable(lua_State *L, int lo, int def, tolua_Error *err)
|
|
{
|
|
if (def && lua_gettop(L) < abs(lo))
|
|
return 1;
|
|
if (lua_istable(L, lo))
|
|
return 1;
|
|
err->index = lo;
|
|
err->array = 0;
|
|
err->type = "table";
|
|
return 0;
|
|
}
|
|
|
|
TOLUA_API int tolua_isusertable(lua_State *L, int lo, const char *type, int def, tolua_Error *err)
|
|
{
|
|
if (def && lua_gettop(L) < abs(lo))
|
|
return 1;
|
|
if (lua_isusertable(L, lo, type))
|
|
return 1;
|
|
err->index = lo;
|
|
err->array = 0;
|
|
err->type = type;
|
|
return 0;
|
|
}
|
|
|
|
TOLUA_API int tolua_isuserdata(lua_State *L, int lo, int def, tolua_Error *err)
|
|
{
|
|
if (def && lua_gettop(L) < abs(lo))
|
|
return 1;
|
|
if (lua_isnil(L, lo) || lua_isuserdata(L, lo))
|
|
return 1;
|
|
err->index = lo;
|
|
err->array = 0;
|
|
err->type = "userdata";
|
|
return 0;
|
|
}
|
|
|
|
TOLUA_API int tolua_isvaluenil(lua_State *L, int lo, tolua_Error *err)
|
|
{
|
|
|
|
if (lua_gettop(L) < abs(lo))
|
|
return 0; /* somebody else should chack this */
|
|
if (!lua_isnil(L, lo))
|
|
return 0;
|
|
|
|
err->index = lo;
|
|
err->array = 0;
|
|
err->type = "value";
|
|
return 1;
|
|
}
|
|
|
|
TOLUA_API int tolua_isvalue(lua_State *L, int lo, int def, tolua_Error *err)
|
|
{
|
|
if (def || abs(lo) <= lua_gettop(L)) /* any valid index */
|
|
return 1;
|
|
err->index = lo;
|
|
err->array = 0;
|
|
err->type = "value";
|
|
return 0;
|
|
}
|
|
|
|
TOLUA_API int tolua_isusertype(lua_State *L, int lo, const char *type, int def, tolua_Error *err)
|
|
{
|
|
if (def && lua_gettop(L) < abs(lo))
|
|
return 1;
|
|
if (lua_isnil(L, lo) || lua_isusertype(L, lo, type))
|
|
return 1;
|
|
err->index = lo;
|
|
err->array = 0;
|
|
err->type = type;
|
|
return 0;
|
|
}
|
|
|
|
TOLUA_API int tolua_isvaluearray(lua_State *L, int lo, int dim, int def, tolua_Error *err)
|
|
{
|
|
(void)dim;
|
|
if (!tolua_istable(L, lo, def, err))
|
|
return 0;
|
|
else
|
|
return 1;
|
|
}
|
|
|
|
TOLUA_API int tolua_isbooleanarray(lua_State *L, int lo, int dim, int def, tolua_Error *err)
|
|
{
|
|
if (!tolua_istable(L, lo, def, err))
|
|
return 0;
|
|
else
|
|
{
|
|
int i;
|
|
for (i = 1; i <= dim; ++i)
|
|
{
|
|
lua_pushnumber(L, i);
|
|
lua_gettable(L, lo);
|
|
if (!(lua_isnil(L, -1) || lua_isboolean(L, -1)) &&
|
|
!(def && lua_isnil(L, -1)))
|
|
{
|
|
err->index = lo;
|
|
err->array = 1;
|
|
err->type = "boolean";
|
|
return 0;
|
|
}
|
|
lua_pop(L, 1);
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
TOLUA_API int tolua_isnumberarray(lua_State *L, int lo, int dim, int def, tolua_Error *err)
|
|
{
|
|
if (!tolua_istable(L, lo, def, err))
|
|
return 0;
|
|
else
|
|
{
|
|
int i;
|
|
for (i = 1; i <= dim; ++i)
|
|
{
|
|
lua_pushnumber(L, i);
|
|
lua_gettable(L, lo);
|
|
if (!lua_isnumber(L, -1) &&
|
|
!(def && lua_isnil(L, -1)))
|
|
{
|
|
err->index = lo;
|
|
err->array = 1;
|
|
err->type = "number";
|
|
return 0;
|
|
}
|
|
lua_pop(L, 1);
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
TOLUA_API int tolua_isstringarray(lua_State *L, int lo, int dim, int def, tolua_Error *err)
|
|
{
|
|
if (!tolua_istable(L, lo, def, err))
|
|
return 0;
|
|
else
|
|
{
|
|
int i;
|
|
for (i = 1; i <= dim; ++i)
|
|
{
|
|
lua_pushnumber(L, i);
|
|
lua_gettable(L, lo);
|
|
if (!(lua_isnil(L, -1) || lua_isstring(L, -1)) &&
|
|
!(def && lua_isnil(L, -1)))
|
|
{
|
|
err->index = lo;
|
|
err->array = 1;
|
|
err->type = "string";
|
|
return 0;
|
|
}
|
|
lua_pop(L, 1);
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
TOLUA_API int tolua_istablearray(lua_State *L, int lo, int dim, int def, tolua_Error *err)
|
|
{
|
|
if (!tolua_istable(L, lo, def, err))
|
|
return 0;
|
|
else
|
|
{
|
|
int i;
|
|
for (i = 1; i <= dim; ++i)
|
|
{
|
|
lua_pushnumber(L, i);
|
|
lua_gettable(L, lo);
|
|
if (!lua_istable(L, -1) &&
|
|
!(def && lua_isnil(L, -1)))
|
|
{
|
|
err->index = lo;
|
|
err->array = 1;
|
|
err->type = "table";
|
|
return 0;
|
|
}
|
|
lua_pop(L, 1);
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
TOLUA_API int tolua_isuserdataarray(lua_State *L, int lo, int dim, int def, tolua_Error *err)
|
|
{
|
|
if (!tolua_istable(L, lo, def, err))
|
|
return 0;
|
|
else
|
|
{
|
|
int i;
|
|
for (i = 1; i <= dim; ++i)
|
|
{
|
|
lua_pushnumber(L, i);
|
|
lua_gettable(L, lo);
|
|
if (!(lua_isnil(L, -1) || lua_isuserdata(L, -1)) &&
|
|
!(def && lua_isnil(L, -1)))
|
|
{
|
|
err->index = lo;
|
|
err->array = 1;
|
|
err->type = "userdata";
|
|
return 0;
|
|
}
|
|
lua_pop(L, 1);
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
TOLUA_API int tolua_isusertypearray(lua_State *L, int lo, const char *type, int dim, int def, tolua_Error *err)
|
|
{
|
|
if (!tolua_istable(L, lo, def, err))
|
|
return 0;
|
|
else
|
|
{
|
|
int i;
|
|
for (i = 1; i <= dim; ++i)
|
|
{
|
|
lua_pushnumber(L, i);
|
|
lua_gettable(L, lo);
|
|
if (!(lua_isnil(L, -1) || lua_isuserdata(L, -1)) &&
|
|
!(def && lua_isnil(L, -1)))
|
|
{
|
|
err->index = lo;
|
|
err->type = type;
|
|
err->array = 1;
|
|
return 0;
|
|
}
|
|
lua_pop(L, 1);
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
#if 0
|
|
int tolua_isbooleanfield
|
|
(lua_State* L, int lo, int i, int def, tolua_Error* err)
|
|
{
|
|
lua_pushnumber(L,i);
|
|
lua_gettable(L,lo);
|
|
if (!(lua_isnil(L,-1) || lua_isboolean(L,-1)) &&
|
|
!(def && lua_isnil(L,-1))
|
|
)
|
|
{
|
|
err->index = lo;
|
|
err->array = 1;
|
|
err->type = "boolean";
|
|
return 0;
|
|
}
|
|
lua_pop(L,1);
|
|
return 1;
|
|
}
|
|
|
|
int tolua_isnumberfield
|
|
(lua_State* L, int lo, int i, int def, tolua_Error* err)
|
|
{
|
|
lua_pushnumber(L,i);
|
|
lua_gettable(L,lo);
|
|
if (!lua_isnumber(L,-1) &&
|
|
!(def && lua_isnil(L,-1))
|
|
)
|
|
{
|
|
err->index = lo;
|
|
err->array = 1;
|
|
err->type = "number";
|
|
return 0;
|
|
}
|
|
lua_pop(L,1);
|
|
return 1;
|
|
}
|
|
|
|
int tolua_isstringfield
|
|
(lua_State* L, int lo, int i, int def, tolua_Error* err)
|
|
{
|
|
lua_pushnumber(L,i);
|
|
lua_gettable(L,lo);
|
|
if (!(lua_isnil(L,-1) || lua_isstring(L,-1)) &&
|
|
!(def && lua_isnil(L,-1))
|
|
)
|
|
{
|
|
err->index = lo;
|
|
err->array = 1;
|
|
err->type = "string";
|
|
return 0;
|
|
}
|
|
lua_pop(L,1);
|
|
return 1;
|
|
}
|
|
|
|
int tolua_istablefield
|
|
(lua_State* L, int lo, int i, int def, tolua_Error* err)
|
|
{
|
|
lua_pushnumber(L,i+1);
|
|
lua_gettable(L,lo);
|
|
if (! lua_istable(L,-1) &&
|
|
!(def && lua_isnil(L,-1))
|
|
)
|
|
{
|
|
err->index = lo;
|
|
err->array = 1;
|
|
err->type = "table";
|
|
return 0;
|
|
}
|
|
lua_pop(L,1);
|
|
}
|
|
|
|
int tolua_isusertablefield
|
|
(lua_State* L, int lo, const char* type, int i, int def, tolua_Error* err)
|
|
{
|
|
lua_pushnumber(L,i);
|
|
lua_gettable(L,lo);
|
|
if (! lua_isusertable(L,-1,type) &&
|
|
!(def && lua_isnil(L,-1))
|
|
)
|
|
{
|
|
err->index = lo;
|
|
err->array = 1;
|
|
err->type = type;
|
|
return 0;
|
|
}
|
|
lua_pop(L,1);
|
|
return 1;
|
|
}
|
|
|
|
int tolua_isuserdatafield
|
|
(lua_State* L, int lo, int i, int def, tolua_Error* err)
|
|
{
|
|
lua_pushnumber(L,i);
|
|
lua_gettable(L,lo);
|
|
if (!(lua_isnil(L,-1) || lua_isuserdata(L,-1)) &&
|
|
!(def && lua_isnil(L,-1))
|
|
)
|
|
{
|
|
err->index = lo;
|
|
err->array = 1;
|
|
err->type = "userdata";
|
|
return 0;
|
|
}
|
|
lua_pop(L,1);
|
|
return 1;
|
|
}
|
|
|
|
int tolua_isusertypefield
|
|
(lua_State* L, int lo, const char* type, int i, int def, tolua_Error* err)
|
|
{
|
|
lua_pushnumber(L,i);
|
|
lua_gettable(L,lo);
|
|
if (!(lua_isnil(L,-1) || lua_isusertype(L,-1,type)) &&
|
|
!(def && lua_isnil(L,-1))
|
|
)
|
|
{
|
|
err->index = lo;
|
|
err->type = type;
|
|
err->array = 1;
|
|
return 0;
|
|
}
|
|
lua_pop(L,1);
|
|
return 1;
|
|
}
|
|
|
|
#endif
|