//Lua Wrappers //Metamethods Instance* Instance::checkInstance(lua_State* L, int index){ if(lua_isuserdata(L, index)){ std::vector<std::string> existing = OpenBlox::BaseGame::getInstanceFactory()->getRegisteredMetatables(); unsigned size = existing.size(); void* udata = lua_touserdata(L, index); int meta = lua_getmetatable(L, index); if(meta != 0){ for(unsigned i = 0; i<size; i++){ std::string name = std::string("luaL_Instance_") + existing[i]; luaL_getmetatable(L, name.c_str()); if(lua_rawequal(L, -1, -2)){ lua_pop(L, 2); return *(Instance**)udata; } lua_pop(L, 1); } } return NULL; } return NULL; }
static int cdlua_rawchecktype(lua_State *L, int param, const char* type) { if (lua_isuserdata(L, param)) /* value is a userdata? */ { if (lua_getmetatable(L, param)) /* does it have a metatable? */ { luaL_getmetatable(L, type); /* get correct metatable */ if (lua_rawequal(L, -1, -2)) /* does it have the correct mt? */ { lua_pop(L, 2); /* remove both metatables */ return 1; } else { lua_pop(L, 2); /* remove both metatables */ return -1; /* test for other metatables */ } } } return 0; /* do not continue */ }
int luaT_lua_isequal(lua_State *L) { if(lua_isuserdata(L, 1) && lua_isuserdata(L, 2)) { void **u1, **u2; luaL_argcheck(L, luaT_id(L, 1), 1, "Torch object expected"); luaL_argcheck(L, luaT_id(L, 2), 2, "Torch object expected"); u1 = lua_touserdata(L, 1); u2 = lua_touserdata(L, 2); if(*u1 == *u2) lua_pushboolean(L, 1); else lua_pushboolean(L, 0); } else if(lua_istable(L, 1) && lua_istable(L, 2)) lua_pushboolean(L, lua_rawequal(L, 1, 2)); else lua_pushboolean(L, 0); return 1; }
/* Attach/detach handler to/from compiler pipeline. */ static int j_attach(lua_State *L) { int pipesz; luaL_checktype(L, 1, LUA_TFUNCTION); pipesz = lua_objlen(L, COMPIPE); if (lua_isnoneornil(L, 2)) { /* Detach if no priority given. */ int i; for (i = 1; i <= pipesz; i += 2) { lua_rawgeti(L, COMPIPE, i); if (lua_rawequal(L, 1, -1)) { /* Found: delete from pipeline. */ for (; i+2 <= pipesz; i++) { /* Shift down. */ lua_rawgeti(L, COMPIPE, i+2); lua_rawseti(L, COMPIPE, i); } /* Clear last two elements. */ lua_pushnil(L); lua_rawseti(L, COMPIPE, i); lua_pushnil(L); lua_rawseti(L, COMPIPE, i+1); return 0; } lua_pop(L, 1); } return 0; /* Not found: ignore detach request. */ } else { /* Attach if priority given. */ int prio = luaL_checkint(L, 2); int pos, i; for (pos = 2; pos <= pipesz; pos += 2) { lua_rawgeti(L, COMPIPE, pos); if (prio > (int)lua_tointeger(L, -1)) break; /* Insertion point found. */ lua_pop(L, 1); } for (i = pipesz+2; i > pos; i--) { /* Shift up. */ lua_rawgeti(L, COMPIPE, i-2); lua_rawseti(L, COMPIPE, i); } /* Set handler and priority. */ lua_pushvalue(L, 1); lua_rawseti(L, COMPIPE, i-1); lua_pushvalue(L, 2); lua_rawseti(L, COMPIPE, i); return 0; } }
/* ** search for 'objidx' in table at index -1. ** return 1 + string at top if find a good name. */ static int findfield (lua_State *L, int objidx, int level) { if (level == 0 || !lua_istable(L, -1)) return 0; /* not found */ lua_pushnil(L); /* start 'next' loop */ while (lua_next(L, -2)) { /* for each pair in table */ if (lua_type(L, -2) == LUA_TSTRING) { /* ignore non-string keys */ if (lua_rawequal(L, objidx, -1)) { /* found object? */ lua_pop(L, 1); /* remove value (but keep name) */ return 1; } else if (findfield(L, objidx, level - 1)) { /* try recursively */ lua_remove(L, -2); /* remove table (but keep name) */ lua_pushliteral(L, "."); lua_insert(L, -2); /* place '.' between the two names */ lua_concat(L, 3); return 1; } } lua_pop(L, 1); /* remove value */ } return 0; /* not found */ }
/* Get __index field of metatable of object on top of stack. */ static int lua_rl_getmetaindex(lua_State *L) { if (!lua_getmetatable(L, -1)) { lua_pop(L, 1); return 0; } /* prefer __metatable if it exists */ lua_pushstring(L, "__metatable"); lua_rawget(L, -2); if(lua_istable(L, -1)) { lua_remove(L, -2); return 1; } else lua_pop(L, 1); lua_pushstring(L, "__index"); lua_rawget(L, -2); lua_replace(L, -2); if (lua_isnil(L, -1) || lua_rawequal(L, -1, -2)) { lua_pop(L, 2); return 0; } lua_replace(L, -2); return 1; } /* 1: obj -- val, 0: obj -- */
static filemap_t *fmap_getself( lua_State *L ) { int argc = lua_gettop( L ); filemap_t *fmap = NULL; void *udata = NULL; if( argc && ( udata = lua_touserdata( L, 1 ) ) ) { // validate metatable if( lua_getmetatable( L, 1 ) ) { lua_pushliteral( L, FILEMAP_LUA ); lua_rawget( L, LUA_REGISTRYINDEX ); if( lua_rawequal( L, -1, -2 ) ){ fmap = (filemap_t*)udata; } } } lua_settop( L, argc ); return fmap; }
static FUNC_UNUSED void * obj_simple_udata_luacheck(lua_State *L, int _index, obj_type *type) { void *ud; /* make sure it's a userdata value. */ ud = lua_touserdata(L, _index); if(ud != NULL) { /* check object type by comparing metatables. */ if(lua_getmetatable(L, _index)) { lua_pushlightuserdata(L, type); lua_rawget(L, LUA_REGISTRYINDEX); /* type's metatable. */ if(lua_rawequal(L, -1, -2)) { lua_pop(L, 2); /* pop both metatables. */ return ud; } } } else if(!lua_isnoneornil(L, _index)) { /* handle cdata. */ /* get private table. */ lua_pushlightuserdata(L, obj_udata_private_key); lua_rawget(L, LUA_REGISTRYINDEX); /* private table. */ /* get cdata type check function from private table. */ lua_pushlightuserdata(L, type); lua_rawget(L, -2); /* check for function. */ if(!lua_isnil(L, -1)) { /* pass cdata value to type checking function. */ lua_pushvalue(L, _index); lua_call(L, 1, 1); if(!lua_isnil(L, -1)) { /* valid type get pointer from cdata. */ lua_pop(L, 2); return (void *)lua_topointer(L, _index); } } } luaL_typerror(L, _index, type->name); /* is not a userdata value. */ return NULL; }
void PushClassData(const char *type, int index) { index = AbsoluteIndex(index); bool hastab = lua_getmetatable(LuaState, index) != 0; int mt = lua_gettop(LuaState); if (hastab) { lua_getfield(LuaState, LUA_REGISTRYINDEX, type); int field = lua_gettop(LuaState); if (lua_rawequal(LuaState, -1, -2)) { // get mt[table] lua_pushvalue(LuaState, index); lua_gettable(LuaState, mt); } lua_remove(LuaState, field); } lua_remove(LuaState, mt); }
// Starting with 5.1 the auxlib version of checkudata throws an exception if the type isn't right // Instead, we want to run our own version that checks the type and just returns null for failure void *checkudata(lua_State *L, int ud, const char *tname) { void *p = lua_touserdata(L, ud); if (p != NULL) { /* value is a userdata? */ if (lua_getmetatable(L, ud)) { int isEqual; /* does it have a metatable? */ lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get correct metatable */ isEqual = lua_rawequal(L, -1, -2); lua_pop(L, 2); /* remove both metatables */ if (isEqual) /* does it have the correct mt? */ return p; } } return NULL; }
/** * \brief Like luaL_checkudata, with additional debug logs. * * This function is for debugging purposes only. * * \param L a lua state * \param ud index of the userdata to check in the stack * \param tname key of the metatable of this userdata in the registry */ void* sglua_checkudata_debug(lua_State* L, int ud, const char* tname) { XBT_DEBUG("Checking the userdata: ud = %d", ud); sglua_stack_dump(L, "my_checkudata: "); void* p = lua_touserdata(L, ud); lua_getfield(L, LUA_REGISTRYINDEX, tname); const void* correct_mt = lua_topointer(L, -1); int has_mt = lua_getmetatable(L, ud); XBT_DEBUG("Checking the userdata: has metatable ? %d", has_mt); const void* actual_mt = nullptr; if (has_mt) { actual_mt = lua_topointer(L, -1); lua_pop(L, 1); } XBT_DEBUG("Checking the task's metatable: expected %p, found %p", correct_mt, actual_mt); sglua_stack_dump(L, "my_checkudata: "); if (p == nullptr || !lua_getmetatable(L, ud) || !lua_rawequal(L, -1, -2)) XBT_ERROR("Error: Userdata is nullptr, couldn't find metatable or top of stack does not equal element below it."); lua_pop(L, 2); return p; }
/* 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; }
// lua_checkudata causes a lua_error if not to checked type // This function is basically lua_checkudata with out the error. bool LuaState::IsType(lua_State* state, int arg, const char* type_name) { if(NULL == lua_touserdata(state, arg)) { return false; } // does it have a metatable? if(lua_getmetatable(state, arg)) { // get correct metatable lua_getfield(state, LUA_REGISTRYINDEX, type_name); // Do metatables match? if(lua_rawequal(state, -1, -2)) { // Remove metatables lua_pop(state, 2); return true; } } return false; }
static FILE *check_file(lua_State *L, int idx, const char *argname) { #if LUA_VERSION_NUM <= 501 FILE **pf; if (idx > 0) pf = luaL_checkudata(L, idx, LUA_FILEHANDLE); else { idx = absindex(L, idx); pf = lua_touserdata(L, idx); luaL_getmetatable(L, LUA_FILEHANDLE); if (!pf || !lua_getmetatable(L, idx) || !lua_rawequal(L, -1, -2)) luaL_error(L, "bad %s option (%s expected, got %s)", argname, LUA_FILEHANDLE, luaL_typename(L, idx)); lua_pop(L, 2); } if (!*pf) return luaL_error(L, "attempt to use a closed file"), NULL; return *pf; #else luaL_Stream* p; idx = absindex(L, idx); p = (luaL_Stream *)luaL_checkudata(L, idx, LUA_FILEHANDLE); if (!p || !p->f) return luaL_error(L, "attempt to use a closed file"), NULL; return p->f; #endif }
/* Release ownership */ static int tolua_bnd_releaseownership (lua_State* L) { int done = 0; if (lua_isuserdata(L,1)) { void* u = *((void**)lua_touserdata(L,1)); /* force garbage collection to avoid releasing a to-be-collected address */ lua_setgcthreshold(L,0); lua_pushstring(L,"tolua_gc"); lua_rawget(L,LUA_REGISTRYINDEX); lua_pushlightuserdata(L,u); lua_rawget(L,-2); lua_getmetatable(L,1); if (lua_rawequal(L,-1,1)) /* check that we are releasing the correct type */ { lua_pushlightuserdata(L,u); lua_pushnil(L); lua_rawset(L,-4); done = 1; } } lua_pushboolean(L,done!=0); return 1; }
Ihandle* iuplua_checkihandle_OLD(lua_State *L, int pos) { Ihandle* ih = NULL; if (lua_getmetatable(L, pos)) /* t2 = metatable(stack(pos)) */ { /* TODO: luaL_getmetatable(L, "iupHandle"); */ lua_pushstring(L, "iupHandle"); lua_gettable(L, LUA_REGISTRYINDEX); /* t = registry["iupHandle"] */ if (lua_rawequal(L, -2, -1)) /* check (t2==t)? */ ih = *(Ihandle**)lua_touserdata(L, pos); lua_pop(L, 2); /* Pop registry["iupHandle"] and the metatable */ } if (!ih) { const char *msg = lua_pushfstring(L, "iupHandle expected, got %s", luaL_typename(L, pos)); luaL_argerror(L, pos, msg); } return ih; }
void *luaT_toudata(lua_State *L, int ud, const char *tname) { void **p = lua_touserdata(L, ud); if(p != NULL) /* value is a userdata? */ { if(!luaT_pushmetatable(L, tname)) luaL_error(L, "Torch internal problem: cannot find metatable for type <%s>", tname); /* initialize the table we want to get the metatable on */ /* note that we have to be careful with indices, as we just inserted stuff */ lua_pushvalue(L, (ud < 0 ? ud - 1 : ud)); while(lua_getmetatable(L, -1)) /* get the next metatable */ { lua_remove(L, -2); /* remove the previous metatable [or object, if first time] */ if(lua_rawequal(L, -1, -2)) { lua_pop(L, 2); /* remove the two metatables */ return *p; } } lua_pop(L, 2); /* remove the two metatables */ } return NULL; }
ElunaObject* Eluna::CHECKTYPE(lua_State* luastate, int narg, const char* tname, bool error) { bool valid = false; ElunaObject** ptrHold = NULL; if (!tname) { valid = true; ptrHold = static_cast<ElunaObject**>(lua_touserdata(luastate, narg)); } else { if (lua_getmetatable(luastate, narg)) { luaL_getmetatable(luastate, tname); if (lua_rawequal(luastate, -1, -2) == 1) { valid = true; ptrHold = static_cast<ElunaObject**>(lua_touserdata(luastate, narg)); } lua_pop(luastate, 2); } } if (!valid || !ptrHold) { if (error) { char buff[256]; snprintf(buff, 256, "bad argument : %s expected, got %s", tname ? tname : "userdata", luaL_typename(luastate, narg)); luaL_argerror(luastate, narg, buff); } return NULL; } return *ptrHold; }
static FUNC_UNUSED int obj_udata_is_compatible(lua_State *L, obj_udata *ud, void **obj, base_caster_t *caster, obj_type *type) { obj_base *base; obj_type *ud_type; lua_pushlightuserdata(L, type); lua_rawget(L, LUA_REGISTRYINDEX); /* type's metatable. */ if(lua_rawequal(L, -1, -2)) { *obj = ud->obj; /* same type no casting needed. */ return 1; } else { /* Different types see if we can cast to the required type. */ lua_rawgeti(L, -2, type->id); base = lua_touserdata(L, -1); lua_pop(L, 1); /* pop obj_base or nil */ if(base != NULL) { *caster = base->bcaster; /* get the obj_type for this userdata. */ lua_pushliteral(L, ".type"); lua_rawget(L, -3); /* type's metatable. */ ud_type = lua_touserdata(L, -1); lua_pop(L, 1); /* pop obj_type or nil */ if(base == NULL) { luaL_error(L, "bad userdata, missing type info."); return 0; } /* check if userdata is a simple object. */ if(ud_type->flags & OBJ_TYPE_SIMPLE) { *obj = ud; } else { *obj = ud->obj; } return 1; } } return 0; }
static struct timer_list* lua_checktimer(lua_State *L, int index) { struct timer_list *timer = 0; luaL_checktype(L, index, LUA_TTABLE); if (!lua_getmetatable(L, index)) luaL_typerror(L, index, CRON_TIMER_METATABLE); lua_getfield(L, LUA_REGISTRYINDEX, CRON_TIMER_METATABLE); /* get correct metatable */ if( !lua_rawequal(L, -1, -2) ) luaL_typerror(L, index, CRON_TIMER_METATABLE); lua_pop(L, 2); lua_pushstring(L, "timer"); lua_rawget(L, index); if( lua_isnil(L, -1) ) luaL_typerror(L, index, CRON_TIMER_METATABLE); timer = (struct timer_list*)lua_touserdata(L, -1); lua_pop(L, 1); return timer; }
int luabridge::indexer(lua_State* L) { lua_getmetatable(L, 1); do { // Look for the key in the metatable lua_pushvalue(L, 2); lua_rawget(L, -2); // Did we get a non-nil result? If so, return it if(!lua_isnil(L, -1)) return 1; ///pop the nil lua_pop(L, 1); //search the metatable of the object's metatable. if(lua_getmetatable(L, -1) && !lua_isnil(L, -1)) { //to prevent calling this indexer method again, make sure the found metatable is not equal to the table's metatable. if(!lua_rawequal(L, -1, -2)) { //store our current argument cnt so we can determine if any arguments were pushed ptrdiff_t base = lua_gettop(L), top; //push the method name being called lua_pushvalue(L, 2); //try to retrieve the key and allow any events to be called. lua_gettable(L, -2); //if there were any arguments, return those. top = lua_gettop(L); //check for multiple arguments. if(top > (base + 1)) return (top - base); //check if the returned object is nil else if(top == (base + 1) && !lua_isnil(L, -1)) return 1; else if(top == (base + 1) && lua_isnil(L, -1)) lua_pop(L, 1); //otherwise, proceed w/ other checks. } //pop the metatable's metatable. lua_pop(L, 1); } // Look for the key in the __propget metafield rawgetfield(L, -1, "__propget"); if(!lua_isnil(L, -1)) { lua_pushvalue(L, 2); lua_rawget(L, -2); // If we got a non-nil result, call it and return its value if(!lua_isnil(L, -1)) { assert(lua_isfunction(L, -1)); lua_pushvalue(L, 1); lua_call(L, 1, 1); return 1; } lua_pop(L, 1); } lua_pop(L, 1); // Look for the key in the __const metafield rawgetfield(L, -1, "__const"); if(!lua_isnil(L, -1)) { lua_pushvalue(L, 2); lua_rawget(L, -2); if(!lua_isnil(L, -1)) return 1; lua_pop(L, 1); } lua_pop(L, 1); // Look for a __parent metafield; if it doesn't exist, return nil; // otherwise, repeat the lookup on it. rawgetfield(L, -1, "__parent"); if(lua_isnil(L, -1)) return 1; lua_remove(L, -2); } while(true); // Control never gets here return 0; }
bool LuaState::RawEqual(int index1, int index2) const { return lua_rawequal(m_state, index1, index2); }
JNIEXPORT jint JNICALL Java_m_lua_Lua_rawequal (JNIEnv* env, jobject thiz, jlong nativeObj, jint idx1, jint idx2) { return (jint) lua_rawequal((lua_State*) nativeObj, idx1, idx2); }
inline bool luaX_to_udata_impl(lua_State* L, const char* name) { luaL_getmetatable(L, name); bool result = lua_rawequal(L, -1, -2); lua_pop(L, 1); return result; }
/* Class index function * If the object is a userdata (ie, an object), it searches the field in * the alternative table stored in the corresponding "ubox" table. */ static int class_index_event (lua_State* L) { int t = lua_type(L,1); if (t == LUA_TUSERDATA) { /* Access alternative table */ #ifdef LUA_VERSION_NUM /* new macro on version 5.1 */ lua_getfenv(L,1); if (!lua_rawequal(L, -1, TOLUA_NOPEER)) { lua_pushvalue(L, 2); /* key */ lua_gettable(L, -2); /* on lua 5.1, we trade the "tolua_peers" lookup for a gettable call */ if (!lua_isnil(L, -1)) return 1; }; #else lua_pushstring(L,"tolua_peers"); lua_rawget(L,LUA_REGISTRYINDEX); /* stack: obj key ubox */ lua_pushvalue(L,1); lua_rawget(L,-2); /* stack: obj key ubox ubox[u] */ if (lua_istable(L,-1)) { lua_pushvalue(L,2); /* key */ lua_rawget(L,-2); /* stack: obj key ubox ubox[u] value */ if (!lua_isnil(L,-1)) return 1; } #endif lua_settop(L,2); /* stack: obj key */ /* Try metatables */ lua_pushvalue(L,1); /* stack: obj key obj */ while (lua_getmetatable(L,-1)) { /* stack: obj key obj mt */ lua_remove(L,-2); /* stack: obj key mt */ if (lua_isnumber(L,2)) /* check if key is a numeric value */ { /* try operator[] */ lua_pushstring(L,".geti"); lua_rawget(L,-2); /* stack: obj key mt func */ if (lua_isfunction(L,-1)) { lua_pushvalue(L,1); lua_pushvalue(L,2); lua_call(L,2,1); return 1; } } else { lua_pushvalue(L,2); /* stack: obj key mt key */ lua_rawget(L,-2); /* stack: obj key mt value */ if (!lua_isnil(L,-1)) return 1; else lua_pop(L,1); /* try C/C++ variable */ lua_pushstring(L,".get"); lua_rawget(L,-2); /* stack: obj key mt tget */ if (lua_istable(L,-1)) { lua_pushvalue(L,2); lua_rawget(L,-2); /* stack: obj key mt value */ if (lua_iscfunction(L,-1)) { lua_pushvalue(L,1); lua_pushvalue(L,2); lua_call(L,2,1); return 1; } else if (lua_istable(L,-1)) { /* deal with array: create table to be returned and cache it in ubox */ void* u = *((void**)lua_touserdata(L,1)); lua_newtable(L); /* stack: obj key mt value table */ lua_pushstring(L,".self"); lua_pushlightuserdata(L,u); lua_rawset(L,-3); /* store usertype in ".self" */ lua_insert(L,-2); /* stack: obj key mt table value */ lua_setmetatable(L,-2); /* set stored value as metatable */ lua_pushvalue(L,-1); /* stack: obj key met table table */ lua_pushvalue(L,2); /* stack: obj key mt table table key */ lua_insert(L,-2); /* stack: obj key mt table key table */ storeatubox(L,1); /* stack: obj key mt table */ return 1; } } } lua_settop(L,3); } lua_pushnil(L); return 1; } else if (t== LUA_TTABLE) { module_index_event(L); return 1; } lua_pushnil(L); return 1; }
static int lhiredis_unwrap_reply(lua_State * L) { int type = 0; luaL_checkany(L, 1); luaL_checkstack(L, 3, "not enough stack to push reply"); if (!lua_istable(L, 1)) { if (lua_isnil(L, 1) && !lua_isnoneornil(L, 2)) { lua_pushvalue(L, 1); lua_pushvalue(L, 2); return 2; } lua_pushvalue(L, 1); return 1; } if (!lua_getmetatable(L, 1)) { lua_pushvalue(L, 1); return 1; } luaL_getmetatable(L, LUAHIREDIS_CONST_MT); if (!lua_rawequal(L, -1, -2)) { lua_pop(L, 2); /* both metatables */ lua_pushvalue(L, 1); return 1; } lua_pop(L, 2); /* both metatables */ lua_getfield(L, 1, "type"); if (lua_type(L, -1) != LUA_TNUMBER) { lua_pop(L, 1); /* t.type */ lua_pushvalue(L, 1); return 1; } type = lua_tonumber(L, -1); lua_pop(L, 1); /* t.type */ if (type == REDIS_REPLY_STATUS) { lua_getfield(L, 1, "name"); if (!lua_isstring(L, -1)) { /* We promised to users that this wouldn't be nil */ return luaL_error(L, "lua-hiredis internal error: bad const-object"); } lua_pushinteger(L, REDIS_REPLY_STATUS); return 2; } else if (type == REDIS_REPLY_ERROR) { lua_pushnil(L); lua_getfield(L, 1, "name"); if (!lua_isstring(L, -1)) { /* We promised to users that this wouldn't be nil */ return luaL_error(L, "lua-hiredis internal error: bad const-object"); } return 2; } /* Note that NIL is not unwrapped */ lua_pushvalue(L, 1); return 1; }
static void lua_to_image(lua_State * L, image * a, image_dict * d) { int i, t; const char *s; s = lua_tostring(L,-2); t = lua_type(L, -1); if (lua_key_eq(s,width)) { if (t == LUA_TNIL) { set_wd_running(a); } else if (t == LUA_TNUMBER) { img_width(a) = (int) lua_roundnumber(L, -1); } else if (t == LUA_TSTRING) { img_width(a) = dimen_to_number(L, lua_tostring(L, -1)); } else { luaL_error(L, "image.width needs integer or nil value or dimension string"); } } else if (lua_key_eq(s,height)) { if (t == LUA_TNIL) { set_ht_running(a); } else if (t == LUA_TNUMBER) { img_height(a) = (int) lua_roundnumber(L, -1); } else if (t == LUA_TSTRING) { img_height(a) = dimen_to_number(L, lua_tostring(L, -1)); } else { luaL_error(L, "image.height needs integer or nil value or dimension string"); } } else if (lua_key_eq(s,depth)) { if (t == LUA_TNIL) { set_dp_running(a); } else if (t == LUA_TNUMBER) { img_depth(a) = (int) lua_roundnumber(L, -1); } else if (t == LUA_TSTRING) { img_depth(a) = dimen_to_number(L, lua_tostring(L, -1)); } else { luaL_error(L, "image.depth needs integer or nil value or dimension string"); } } else if (lua_key_eq(s,transform)) { if (t == LUA_TNUMBER) { img_transform(a) = (int) lua_tointeger(L, -1); } else { luaL_error(L, "image.transform needs integer value"); } } else if (lua_key_eq(s,filename)) { if (img_state(d) >= DICT_FILESCANNED) { luaL_error(L, "image.filename is now read-only"); } else if (img_type(d) == IMG_TYPE_PDFSTREAM) { luaL_error(L, "image.filename can't be used with image.stream"); } else if (t == LUA_TSTRING) { xfree(img_filename(d)); img_filename(d) = xstrdup(lua_tostring(L, -1)); } else { luaL_error(L, "image.filename needs string value"); } } else if (lua_key_eq(s,visiblefilename)) { if (img_state(d) >= DICT_FILESCANNED) { luaL_error(L, "image.visiblefilename is now read-only"); } else if (img_type(d) == IMG_TYPE_PDFSTREAM) { luaL_error(L, "image.visiblefilename can't be used with image.stream"); } else if (t == LUA_TSTRING) { xfree(img_visiblefilename(d)); img_visiblefilename(d) = xstrdup(lua_tostring(L, -1)); } else { luaL_error(L, "image.visiblefilename needs string value"); } } else if (lua_key_eq(s,attr)) { if (img_state(d) >= DICT_FILESCANNED) { luaL_error(L, "image.attr is now read-only"); } else if (t == LUA_TSTRING) { xfree(img_attr(d)); img_attr(d) = xstrdup(lua_tostring(L, -1)); } else if (t == LUA_TNIL) { xfree(img_attr(d)); } else { luaL_error(L, "image.attr needs string or nil value"); } } else if (lua_key_eq(s,page)) { if (img_state(d) >= DICT_FILESCANNED) { luaL_error(L, "image.page is now read-only"); } else if (t == LUA_TSTRING) { xfree(img_pagename(d)); img_pagename(d) = xstrdup(lua_tostring(L, -1)); img_pagenum(d) = 0; } else if (t == LUA_TNUMBER) { img_pagenum(d) = (int) lua_tointeger(L, -1); xfree(img_pagename(d)); } else { luaL_error(L, "image.page needs integer or string value"); } } else if (lua_key_eq(s,colorspace)) { if (img_state(d) >= DICT_FILESCANNED) { luaL_error(L, "image.colorspace is now read-only"); } else if (t == LUA_TNIL) { img_colorspace(d) = 0; } else if (t == LUA_TNUMBER) { img_colorspace(d) = (int) lua_tointeger(L, -1); } else { luaL_error(L, "image.colorspace needs integer or nil value"); } } else if (lua_key_eq(s,pagebox)) { if (img_state(d) >= DICT_FILESCANNED) { luaL_error(L, "image.pagebox is now read-only"); } else if (t == LUA_TNIL) { img_pagebox(d) = PDF_BOX_SPEC_MEDIA; } else if (t == LUA_TNUMBER) { i = lua_tointeger(L,-1); if (i < 0 || i >= img_pageboxes_max) { img_pagebox(d) = PDF_BOX_SPEC_MEDIA; } else { img_pagebox(d) = i; } } else if (t == LUA_TSTRING) { img_pagebox(d) = PDF_BOX_SPEC_MEDIA; for (i = 0; i < img_pageboxes_max; i++) { lua_rawgeti(L, LUA_REGISTRYINDEX, img_pageboxes[i]); if (lua_rawequal(L,-1,-2)) { img_pagebox(d) = i; lua_pop(L, 1); break; } else { lua_pop(L, 1); } } } else { luaL_error(L, "image.pagebox needs string, number or nil value"); } } else if (lua_key_eq(s,keepopen)) { if (img_state(d) >= DICT_FILESCANNED) { luaL_error(L, "image.keepopen is now read-only"); } else if (t != LUA_TBOOLEAN) { luaL_error(L, "image.bbox needs boolean value"); } else { img_keepopen(d) = lua_toboolean(L, -1); } } else if (lua_key_eq(s,bbox)) { if (img_state(d) >= DICT_FILESCANNED) { luaL_error(L, "image.bbox is now read-only"); } else if (t != LUA_TTABLE) { luaL_error(L, "image.bbox needs table value"); } else if (lua_rawlen(L, -1) != 4) { luaL_error(L, "image.bbox table must have exactly 4 elements"); } else { for (i = 1; i <= 4; i++) { /* v k t ... */ lua_pushinteger(L, i); /* idx v k t ... */ lua_gettable(L, -2); /* int v k t ... */ t = lua_type(L, -1); if (t == LUA_TNUMBER) { img_bbox(d)[i - 1] = (int) lua_roundnumber(L, -1); } else if (t == LUA_TSTRING) { img_bbox(d)[i - 1] = dimen_to_number(L, lua_tostring(L, -1)); } else { luaL_error(L, "image.bbox table needs integer value or dimension string elements"); } lua_pop(L, 1); /* v k t ... */ } img_set_bbox(d); } } else if (lua_key_eq(s,stream)) { if (img_filename(d) != NULL) { luaL_error(L, "image.stream can't be used with image.filename"); } else if (img_state(d) >= DICT_FILESCANNED) { luaL_error(L, "image.stream is now read-only"); } else { if (img_pdfstream_ptr(d) == NULL) { new_img_pdfstream_struct(d); } xfree(img_pdfstream_stream(d)); img_pdfstream_stream(d) = xstrdup(lua_tostring(L, -1)); img_type(d) = IMG_TYPE_PDFSTREAM; } } else { luaL_error(L, "image.%s can not be set", s); } }
/* * Take the Lua stack item at index i and convert it into an * ActionScript value. */ AS3_Val get_as3_value_from_lua_stack_type(lua_State * L, int i, int type) { /* WARNING: Panic alert! Use L*_FN checkers here! */ LCALL(L, stack); AS3_Val value; switch (type) { case LUA_TSTRING: /* strings */ { size_t length = 0; const char * str = lua_tolstring(L, i, &length); if (str == NULL) /* NOTE: This is unreachable. Assert instead */ { length = 6; str = "(null)"; } /* NOTE: Alchemy .5a truncates embedded zeroes in string * regardless to the passed length */ value = AS3_StringN(str, length); } break; case LUA_TBOOLEAN: /* booleans */ value = lua_toboolean(L, i) ? AS3_True() : AS3_False(); break; case LUA_TNUMBER: /* numbers */ value = AS3_Number(lua_tonumber(L, i)); break; case LUA_TNONE: /* fall through */ case LUA_TNIL: /* nil */ value = AS3_Null(); break; case LUA_TUSERDATA: /* userdata */ { void * userdata = lua_touserdata(L, i); lua_getfield(L, LUA_REGISTRYINDEX, AS3LUA_METATABLE); if (userdata == NULL || !lua_getmetatable(L, i)) { lua_pop(L, 1); /* Pop AS3LUA_METATABLE */ value = as3_value_from_foreign_userdata(L, i); } else if (!lua_rawequal(L, -2, -1)) { lua_pop(L, 2); /* Pop AS3LUA_METATABLE and userdata metatable */ value = as3_value_from_foreign_userdata(L, i); } else { lua_pop(L, 2); /* Pop AS3LUA_METATABLE and userdata metatable */ AS3LuaUserData * userdata = (AS3LuaUserData *)lua_touserdata(L, i); value = userdata->value; /* * We just created one more reference to the AS3 value, * as it still lives inside Lua. * (And will probably be collected by GC.) */ AS3_Acquire(value); } } break; case LUA_TFUNCTION: /* function */ value = setup_callback(L, i); break; case LUA_TLIGHTUSERDATA: /* TODO: blackbox this type */ case LUA_TTABLE: /* TODO: deal with this type */ case LUA_TTHREAD: /* TODO: blackbox this type */ value = AS3_String(lua_typename(L, type)); break; default: /* unreachable */ fatal_error("unknown Lua type"); break; } #ifdef DO_SPAM SPAM(("get_as3_value_from_lua_stack(): end")); AS3_Trace( AS3_Call( getQualifiedClassName_method, NULL, AS3_Array("AS3ValType", value) ) ); #endif /* DO_SPAM */ LCHECK_FN(L, stack, 0, fatal_error); return value; }
static int luaB_rawequal (lua_State *L) { luaL_checkany(L, 1); luaL_checkany(L, 2); lua_pushboolean(L, lua_rawequal(L, 1, 2)); return 1; }
void* luabridge::checkclass(lua_State* L, int idx, const char* tname, bool exact) { // If idx is relative to the top of the stack, convert it into an index // relative to the bottom of the stack, so we can push our own stuff if(idx < 0) idx += lua_gettop(L) + 1; int top = lua_gettop(L); // Check that the thing on the stack is indeed a userdata if(!lua_isuserdata(L, idx)) luaL_typerror(L, idx, tname); // Lookup the given name in the registry luaL_getmetatable(L, tname); // Lookup the metatable of the given userdata lua_getmetatable(L, idx); // If exact match required, simply test for identity. if(exact) { // Ignore "const" for exact tests (which are used for destructors). if(!strncmp(tname, "const ", 6)) tname += 6; if(lua_rawequal(L, -1, -2)) return lua_touserdata(L, idx); else { // Generate an informative error message rawgetfield(L, -1, "__type"); char buffer[256]; snprintf(buffer, 256, "%s expected, got %s", tname, lua_tostring(L, -1)); // luaL_argerror does not return luaL_argerror(L, idx, buffer); return 0; } } // Navigate up the chain of parents if necessary while(!lua_rawequal(L, -1, -2)) { // Check for equality to the const metatable rawgetfield(L, -1, "__const"); if(!lua_isnil(L, -1)) { if(lua_rawequal(L, -1, -3)) break; } lua_pop(L, 1); // Look for the metatable's parent field rawgetfield(L, -1, "__parent"); // No parent field? We've failed; generate appropriate error if(lua_isnil(L, -1)) { // Lookup the __type field of the original metatable, so we can // generate an informative error message lua_getmetatable(L, idx); rawgetfield(L, -1, "__type"); char buffer[256]; snprintf(buffer, 256, "%s expected, got %s", tname, lua_tostring(L, -1)); // luaL_argerror does not return luaL_argerror(L, idx, buffer); return 0; } // Remove the old metatable from the stack lua_remove(L, -2); } lua_settop(L, top); // Found a matching metatable; return the userdata return lua_touserdata(L, idx); }