1
0
mirror of https://github.com/Llewellynvdm/conky.git synced 2024-06-10 11:12:21 +00:00
conky/3rdparty/toluapp/src/lib/tolua_is.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