//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 void persistuserdata(PersistInfo *pi) { /* perms reftbl ... udata */ lua_checkstack(pi->L, 2); if(persistspecialobject(pi, 0)) { /* perms reftbl ... udata */ return; } else { /* Use literal persistence */ size_t length = uvalue(getobject(pi->L, -1))->len; pi->writer(pi->L, &length, sizeof(size_t), pi->ud); pi->writer(pi->L, lua_touserdata(pi->L, -1), length, pi->ud); if(!lua_getmetatable(pi->L, -1)) { /* perms reftbl ... udata */ lua_pushnil(pi->L); /* perms reftbl ... udata mt/nil */ } persist(pi); lua_pop(pi->L, 1); /* perms reftbl ... udata */ } }
void dt_lua_register_format_typeid(lua_State* L, dt_imageio_module_format_t* module, luaA_Type type_id) { dt_lua_register_type_callback_list_typeid(L,type_id,format_index,NULL,format_fields_name); lua_pushcfunction(L,write_image); dt_lua_register_type_callback_stack_typeid(L,type_id,"write_image"); luaL_getmetatable(L,luaA_type_name(type_id)); lua_pushlightuserdata(L,module); lua_setfield(L,-2,"__associated_object"); lua_pushstring(L,"format"); lua_setfield(L,-2,"__module_type"); lua_pop(L,1); // pop the metatable // add to the table dt_lua_push_darktable_lib(L); dt_lua_goto_subtable(L,"modules"); dt_lua_goto_subtable(L,"format"); lua_getmetatable(L,-1); lua_getfield(L,-1,"__luaA_Type"); luaA_Type format_table_type = luaL_checkint(L,-1); dt_lua_register_type_callback_typeid(L,format_table_type,get_format_params,NULL,module->plugin_name,NULL); lua_pop(L,3); };
/* Map inheritance * It sets 'name' as derived from 'base' by setting 'base' as metatable of 'name' */ static void mapinheritance (lua_State* L, const char* name, const char* base) { /* set metatable inheritance */ luaL_getmetatable(L,name); if (base && *base) luaL_getmetatable(L,base); else { if (lua_getmetatable(L, -1)) { /* already has a mt, we don't overwrite it */ lua_pop(L, 2); return; }; luaL_getmetatable(L,"tolua_commonclass"); }; set_ubox(L); lua_setmetatable(L,-2); lua_pop(L,1); }
/* Take ownership */ static int tolua_bnd_takeownership (lua_State* L) { lua_CFunction func = 0; if (lua_isuserdata(L,1)) { if (lua_getmetatable(L,1)) /* if metatable? */ { void* u; lua_pushstring(L,".collector"); lua_rawget(L,-2); func = lua_tocfunction(L,-1); /* it may be NULL; it is ok */ lua_pop(L,2); u = *((void**)lua_touserdata(L,1)); /* force garbage collection to avoid C to reuse a to-be-collected address */ lua_setgcthreshold(L,0); tolua_clone(L,u,func); } } lua_pushboolean(L,func!=0); return 1; }
void Script_initState(ScriptState* state, TabManager* tabs, Buffer* buffer) { lua_State* L = luaL_newstate(); state->L = L; luaL_openlibs(L); lua_pushstring(L, "buffer"); // push a random string lua_getmetatable(L, -1); // get metatable of strings lua_remove(L, -2); // remove random string lua_pushcfunction(L, Script_string___index); // push custom index fn lua_setfield(L, -2, "__index"); // set it in metatable lua_pop(L, 1); // pop metatable lua_pushstring(L, "Buffer_functions"); luaL_newlib(L, Buffer_functions); lua_settable(L, LUA_REGISTRYINDEX); Script_pushObject(L, tabs, "TabManager", TabManager_functions); lua_setglobal(L, "tabs"); Script_Buffer_new(L, buffer); lua_setglobal(L, "buffer"); }
/* Take ownership */ static int tolua_bnd_takeownership (lua_State* L) { int success = 0; if (lua_isuserdata(L,1)) { if (lua_getmetatable(L,1)) /* if metatable? */ { lua_pop(L,1); /* clear metatable off stack */ /* force garbage collection to avoid C to reuse a to-be-collected address */ #ifdef LUA_VERSION_NUM lua_gc(L, LUA_GCCOLLECT, 0); #else lua_setgcthreshold(L,0); #endif success = tolua_register_gc(L,1); } } lua_pushboolean(L,success!=0); return 1; }
void MetatableLuaTable::callInstanceMethod(const std::string& name) { LuaStateMutexType::scoped_lock lock(_luaVmState.getMutex()); cgtAssert(false, "Method not verified, use with care!"); // recursively push this metatable onto stack, so that we can refer to it later _parent->pushField(_fieldName); // push the function onto the stack lua_getfield(_luaVmState.rawState(), -1, name.c_str()); // push the metatable onto the stack again (now non-recusively) if (!lua_getmetatable(_luaVmState.rawState(), -2)) cgtAssert(false, "This should not happen, Lua stack is corrupted!"); // call the function _luaVmState.callLuaFunc(1, 0); // clean up the stack lua_pop(_luaVmState.rawState(), 1); _parent->popRecursive(); }
static int luaT_mt__newindex(lua_State *L) { if(!lua_getmetatable(L, 1)) luaL_error(L, "critical internal indexing error: no metatable found"); if(!lua_istable(L, -1)) luaL_error(L, "critical internal indexing error: not a metatable"); /* test for __newindex__ method first */ lua_getfield(L, -1, "__newindex__"); if(!lua_isnil(L, -1)) { int result; if(!lua_isfunction(L, -1)) luaL_error(L, "critical internal indexing error: __newindex__ is not a function"); lua_pushvalue(L, 1); lua_pushvalue(L, 2); lua_pushvalue(L, 3); lua_call(L, 3, 1); /* DEBUG: risque: faut vraiment retourner qqch */ result = lua_toboolean(L, -1); lua_pop(L, 1); if(result) return 0; } else lua_pop(L, 1); /* remove nil __newindex__ on the stack */ lua_pop(L, 1); /* pop the metatable */ if(lua_istable(L, 1)) lua_rawset(L, 1); else luaL_error(L, "the class %s cannot be indexed", luaT_typename(L, 1)); return 0; }
/* 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); }
/** Decrement a object reference in its store table. * \param L The Lua VM state. * \param tud The table index on the stack. * \param oud The object index on the stack. * \return A pointer to the object. */ void luaA_object_decref(lua_State *L, int tud, void *pointer) { if(!pointer) return; /* First, refcount-- */ /* Get the metatable */ lua_getmetatable(L, tud); /* Push the pointer (key) */ lua_pushlightuserdata(L, pointer); /* Get the number of references */ lua_rawget(L, -2); /* Get the number of references and decrement it */ int count = lua_tonumber(L, -1) - 1; lua_pop(L, 1); /* Push the pointer (key) */ lua_pushlightuserdata(L, pointer); /* Hasn't the ref reached 0? */ if(count) lua_pushinteger(L, count); else /* Yup, delete it, set nil as value */ lua_pushnil(L); /* Set meta[pointer] = count/nil */ lua_rawset(L, -3); /* Pop metatable */ lua_pop(L, 1); /* Wait, no more ref? */ if(!count) { /* Yes? So remove it from table */ lua_pushlightuserdata(L, pointer); /* Push nil as value */ lua_pushnil(L); /* table[pointer] = nil */ lua_rawset(L, tud < 0 ? tud - 2 : tud); } }
static int program_clone(lua_State *L) { shader_type *p = (shader_type*)lua_touserdata(L, 1); shader_type *np = (shader_type*)lua_newuserdata(L, sizeof(shader_type)); // 2 auxiliar_setclass(L, "gl{program}", -1); np->clone = TRUE; np->shader = p->shader; np->p_tick = p->p_tick; np->p_color = p->p_color; np->p_mapcoord = p->p_mapcoord; np->p_texsize = p->p_texsize; np->p_texcoord = p->p_texcoord; np->reset_uniforms = NULL; lua_getmetatable(L, 1); // 3 lua_newtable(L); // 4 // Iterate old table and copy to new table lua_pushnil(L); while (lua_next(L, 3) != 0) { lua_pushvalue(L, -2); lua_pushvalue(L, -2); lua_rawset(L, 4); lua_pop(L, 1); } // Capture a reference to the parent so it is not GC'ed before us lua_pushstring(L, "_parent_clone"); lua_pushvalue(L, 1); lua_rawset(L, 4); lua_setmetatable(L, 2); lua_pop(L, 1); printf("Cloned shader %d\n", p->shader); return 1; }
int luabridge::m_newindexer(lua_State* L) { lua_getmetatable(L, 1); do { // Look for the key in the __propset metafield rawgetfield(L, -1, "__propset"); if(!lua_isnil(L, -1)) { lua_pushvalue(L, 2); lua_rawget(L, -2); // If we got a non-nil result, call it if(!lua_isnil(L, -1)) { assert(lua_isfunction(L, -1)); lua_pushvalue(L, 1); lua_pushvalue(L, 3); lua_call(L, 2, 0); return 0; } lua_pop(L, 1); } lua_pop(L, 1); // Look for a __parent metafield; if it doesn't exist, error; // otherwise, repeat the lookup on it. rawgetfield(L, -1, "__parent"); if(lua_isnil(L, -1)) { return luaL_error(L, "attempt to set %s, which isn't a property", lua_tostring(L, 2)); } lua_remove(L, -2); } while(true); // Control never gets here return 0; }
/* static int class_gc_event (lua_State* L) { void* u = *((void**)lua_touserdata(L,1)); fprintf(stderr, "collecting: looking at %p\n", u); lua_pushstring(L,"tolua_gc"); lua_rawget(L,LUA_REGISTRYINDEX); lua_pushlightuserdata(L,u); lua_rawget(L,-2); if (lua_isfunction(L,-1)) { lua_pushvalue(L,1); lua_call(L,1,0); lua_pushlightuserdata(L,u); lua_pushnil(L); lua_rawset(L,-3); } lua_pop(L,2); return 0; } */ TOLUA_API int class_gc_event (lua_State* L) { void* u = *((void**)lua_touserdata(L,1)); int top; /*fprintf(stderr, "collecting: looking at %p\n", u);*/ /* lua_pushstring(L,"tolua_gc"); lua_rawget(L,LUA_REGISTRYINDEX); */ lua_pushvalue(L, lua_upvalueindex(1)); lua_pushlightuserdata(L,u); lua_rawget(L,-2); /* stack: gc umt */ lua_getmetatable(L,1); /* stack: gc umt mt */ /*fprintf(stderr, "checking type\n");*/ top = lua_gettop(L); if (tolua_fast_isa(L,top,top-1, lua_upvalueindex(2))) /* make sure we collect correct type */ { /*fprintf(stderr, "Found type!\n");*/ /* get gc function */ lua_pushliteral(L,".collector"); lua_rawget(L,-2); /* stack: gc umt mt collector */ if (lua_isfunction(L,-1)) { /*fprintf(stderr, "Found .collector!\n");*/ } else { lua_pop(L,1); /*fprintf(stderr, "Using default cleanup\n");*/ lua_pushcfunction(L,tolua_default_collect); } lua_pushvalue(L,1); /* stack: gc umt mt collector u */ lua_call(L,1,0); lua_pushlightuserdata(L,u); /* stack: gc umt mt u */ lua_pushnil(L); /* stack: gc umt mt u nil */ lua_rawset(L,-5); /* stack: gc umt mt */ } lua_pop(L,3); return 0; }
static void persisttable(PersistInfo *pi) { /* perms reftbl ... tbl */ lua_checkstack(pi->L, 3); if(persistspecialobject(pi, 1)) { /* perms reftbl ... tbl */ return; } /* perms reftbl ... tbl */ /* First, persist the metatable (if any) */ if(!lua_getmetatable(pi->L, -1)) { lua_pushnil(pi->L); } /* perms reftbl ... tbl mt/nil */ persist(pi); lua_pop(pi->L, 1); /* perms reftbl ... tbl */ /* Now, persist all k/v pairs */ lua_pushnil(pi->L); /* perms reftbl ... tbl nil */ while(lua_next(pi->L, -2)) { /* perms reftbl ... tbl k v */ lua_pushvalue(pi->L, -2); /* perms reftbl ... tbl k v k */ persist(pi); lua_pop(pi->L, 1); /* perms reftbl ... tbl k v */ persist(pi); lua_pop(pi->L, 1); /* perms reftbl ... tbl k */ } /* perms reftbl ... tbl */ /* Terminate list */ lua_pushnil(pi->L); /* perms reftbl ... tbl nil */ persist(pi); lua_pop(pi->L, 1); /* perms reftbl ... tbl */ }
TOLUA_API void tolua_module(lua_State *L, const char *name, int hasvar) { if (name) { /* tolua module */ lua_pushstring(L, name); lua_rawget(L, -2); if (!lua_istable(L, -1)) /* check if module already exists */ { lua_pop(L, 1); lua_newtable(L); lua_pushstring(L, name); lua_pushvalue(L, -2); lua_rawset(L, -4); /* assing module into module */ } } else { /* global table */ #if LUA_VERSION_NUM > 501 lua_pushglobaltable(L); #else lua_pushvalue(L, LUA_GLOBALSINDEX); #endif } if (hasvar) { if (!tolua_ismodulemetatable(L)) /* check if it already has a module metatable */ { /* create metatable to get/set C/C++ variable */ lua_newtable(L); tolua_moduleevents(L); if (lua_getmetatable(L, -2)) lua_setmetatable(L, -2); /* set old metatable as metatable of metatable */ lua_setmetatable(L, -2); } } lua_pop(L, 1); /* pop module */ }
static int l_vector_index(lua_State *L) { const vector3d *v = LuaVector::CheckFromLua(L, 1); if (lua_type(L, 2) == LUA_TSTRING) { const char *attr = luaL_checkstring(L, 2); if (!strcmp(attr, "x")) { lua_pushnumber(L, v->x); return 1; } else if (!strcmp(attr, "y")) { lua_pushnumber(L, v->y); return 1; } else if (!strcmp(attr, "z")) { lua_pushnumber(L, v->z); return 1; } } lua_getmetatable(L, 1); lua_pushvalue(L, 2); lua_rawget(L, -2); lua_remove(L, -2); return 1; }
//----------------------------------------------------------------// bool MOAILuaObject::PushRefTable ( MOAILuaState& state ) { MOAILuaClass* luaClass = this->GetLuaClass (); if ( !luaClass ) { lua_pushnil ( state ); return false; } if ( luaClass->IsSingleton ()) { luaClass->PushRefTable ( state ); return true; } if ( this->PushLuaUserdata ( state )) { int result = lua_getmetatable ( state, -1 ); if ( result ) { lua_replace ( state, -2 ); return true; } } return false; }
bool ex_lua_isbuiltin ( lua_State *_l, int _idx ) { bool r; // local tp = typeof(_object) if ( lua_getmetatable(_l,_idx) == 0 ) return false; // if type(tp) ~= "table" then return false end if ( lua_istable( _l, -1 ) == 0 ) { lua_pop(_l,1); // pops tp return false; } // local r = rawget(tp, "__isbuiltin") lua_pushstring(_l,"__isbuiltin"); lua_rawget ( _l, -2 ); // return r r = lua_toboolean(_l,-1); lua_pop(_l,2); // pops tp, r return r; }
static int lqtL_indexfunc (lua_State *L) { int i = 1; if (lua_isuserdata(L, 1) && !lua_islightuserdata(L, 1)) { lua_getmetatable(L, 1); lua_pushliteral(L, "__get"); lua_rawget(L, -2); if (lua_istable(L, -1)) { lua_pushvalue(L, 2); lua_gettable(L, -2); if (lua_isfunction(L, -1)) { lua_CFunction getter = lua_tocfunction(L, -1); if (!getter) return luaL_error(L, "Invalid getter %s", lua_tostring(L, 2)); return getter(L); } } lua_settop(L, 2); lua_getfenv(L, 1); // (1) lua_pushvalue(L, 2); // (2) lua_gettable(L, -2); // (2) if (!lua_isnil(L, -1)) { lua_remove(L, -2); return 1; } lua_pop(L, 2); // (0) } lua_pushnil(L); // (+1) while (!lua_isnone(L, lua_upvalueindex(i))) { // (+1) lua_pop(L, 1); // (+0) lua_pushvalue(L, 2); // (+1) if (i==1) { lua_rawget(L, lua_upvalueindex(i)); // (+1) } else { lua_gettable(L, lua_upvalueindex(i)); // (+1) } if (!lua_isnil(L, -1)) break; i++; } return 1; // (+1) }
luaA_Type dt_lua_init_wrapped_singleton(lua_State *L, lua_CFunction pusher, lua_CFunction getter, const char *unique_name, void *data) { luaA_Type result = dt_lua_init_singleton(L, unique_name, data); lua_getmetatable(L, -1); lua_pushcfunction(L, wrapped_index); lua_setfield(L, -2, "__index"); lua_pushcfunction(L, wrapped_newindex); lua_setfield(L, -2, "__newindex"); lua_pushcfunction(L, wrapped_pairs); lua_setfield(L, -2, "__pairs"); lua_pushcfunction(L, wrapped_ipairs); lua_setfield(L, -2, "__ipairs"); lua_pushcfunction(L, wrapped_tostring); lua_setfield(L, -2, "__tostring"); lua_pushcfunction(L, pusher); lua_setfield(L, -2, "__pusher"); lua_pushcfunction(L, getter); lua_setfield(L, -2, "__getter"); lua_pop(L, 1); return result; }
static int Lreader___index(lua_State* L) { mz_zip_archive *za = luaL_checkudata(L, 1, LMZ_ZIP_READER); int type = lua_type(L, 2); if (type == LUA_TSTRING) { if (lua_getmetatable(L, 1)) { lua_pushvalue(L, 2); lua_rawget(L, -2); return 1; } return 0; } else if (type == LUA_TNUMBER) { mz_uint file_index = (mz_uint)luaL_checkinteger(L, 2) - 1; char filename[MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE]; if (!mz_zip_reader_get_filename(za, file_index, filename, MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE)) return lmz_zip_pusherror(L, za, NULL); lua_pushstring(L, filename); return 1; } return 0; }
/* does a deep copy of a table */ static int table_deepcopy_r(struct lua_State *L) { size_t s; /* 1: table to copy, 2: new table */ s = lua_objlen(L, -1); lua_createtable(L, 0, s); /* 3: iterator */ lua_pushnil(L); while(lua_next(L, -3)) { /* 4: value */ if(lua_istable(L, -1)) { table_deepcopy_r(L); /* 5: new table */ lua_pushvalue(L, -3); /* 6: key */ lua_pushvalue(L, -2); /* 7: value */ lua_settable(L, -6); /* pops 6 and 7 */ lua_pop(L, 1); /* pops 5 */ } else { lua_pushvalue(L, -2); /* 5: key */ lua_pushvalue(L, -2); /* 6: value */ lua_settable(L, -5); /* pops 5 and 6 */ } /* pops 4 */ lua_pop(L, 1); } /* transfer the meta table */ if(lua_getmetatable(L, -2)) lua_setmetatable(L, -2); return 1; }
int UGGetClassGroup(lua_State *L) { if(lua_getmetatable(L, -1) != 0) { lua_pushstring(L, "class_name_node"); lua_rawget(L, -2); const ug::bridge::ClassNameNode* classNameNode = (const ug::bridge::ClassNameNode*) lua_touserdata(L, -1); lua_pop(L, 2); if(classNameNode) { const bridge::Registry ® = bridge::GetUGRegistry(); const bridge::IExportedClass *c = reg.get_class(classNameNode->name()); lua_pushstring(L, c->group().c_str()); return 1; } else UG_THROW("In UGGetClassGroup: Something wrong with ClassNameNode."); } lua_pushstring(L, ""); return 1; }
static int queue__index(lua_State *L) { luaTHRD_checkudata(L, 1, "threads.Queue"); lua_getmetatable(L, 1); if(lua_isstring(L, 2)) { lua_pushstring(L, "__get"); lua_rawget(L, -2); lua_pushvalue(L, 2); lua_rawget(L, -2); if(lua_isfunction(L, -1)) { lua_pushvalue(L, 1); lua_call(L, 1, 1); return 1; } else { lua_pop(L, 2); } } lua_insert(L, -2); lua_rawget(L, -2); return 1; }
int mlua_index_with_properties (lua_State *L, const struct luaL_Reg *properties, bool use_cache) { char const * key; const struct luaL_Reg *reg; key = lua_tostring (L, 2); if (key == NULL) return 0; reg = mlua_find_method (properties, key); if (reg) { return mlua_get_property (L, reg, use_cache); } lua_getmetatable (L, 1); lua_replace (L, 1); lua_gettable (L, 1); return 1; }
static int __class_newindex ( lua_State *_l ) { // check if the metatable have the key // local mt = getmetatable(_t) if ( lua_getmetatable(_l,1) == 0 ) { return luaL_error ( _l, "can't find the metatable of _t" ); } // v = rawget(mt,_k) lua_pushvalue(_l,2); lua_rawget(_l,-2); // if v ~= nil then if ( lua_isnil(_l,-1) == 0 ) { // rawset(_t,_k,_v) lua_pushvalue(_l,2); // push _k lua_pushvalue(_l,3); // push _v lua_rawset (_l,1); return 0; } lua_pop(_l,1); // pops v return luaL_error ( _l, "can't find the key %s", lua_tostring(_l,2) ); }
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; }
inline std::string associated_type_name(lua_State* L, int index, type t) { switch (t) { case type::poly: return "anything"; case type::userdata: { if (lua_getmetatable(L, index) == 0) { break; } lua_pushlstring(L, "__name", 6); lua_rawget(L, -2); size_t sz; const char* name = lua_tolstring(L, -1, &sz); std::string tn(name, static_cast<std::string::size_type>(sz)); lua_pop(L, 2); return name; } default: break; } return lua_typename(L, static_cast<int>(t)); }
/* 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 -- */