static int db_setuservalue (lua_State *L) { if (lua_type(L, 1) == LUA_TLIGHTUSERDATA) luaL_argerror(L, 1, "full userdata expected, got light userdata"); luaL_checktype(L, 1, LUA_TUSERDATA); if (!lua_isnoneornil(L, 2)) luaL_checktype(L, 2, LUA_TTABLE); lua_settop(L, 2); lua_setuservalue(L, 1); return 1; }
LUABIND_API object_rep* push_new_instance(lua_State* L, class_rep* cls) { void* storage = lua_newuserdata(L, sizeof(object_rep)); object_rep* result = new (storage) object_rep(0, cls); cls->get_table(L); lua_setuservalue(L, -2); lua_rawgeti(L, LUA_REGISTRYINDEX, cls->metatable_ref()); lua_setmetatable(L, -2); return result; }
// in: nothing // out: { first = 1, count = 0, limit = -1} static void fifo_new( lua_State* L) { keeper_fifo* fifo; STACK_GROW( L, 2); fifo = (keeper_fifo*) lua_newuserdata( L, sizeof( keeper_fifo)); fifo->first = 1; fifo->count = 0; fifo->limit = -1; lua_newtable( L); lua_setuservalue( L, -2); }
static int lsettext(lua_State *L) { struct sprite *s = self(L); if (s->type != TYPE_LABEL) { return luaL_error(L, "Only label can set text"); } lua_settop(L,2); s->data.text = luaL_checkstring(L,2); lua_setuservalue(L, 1); return 0; }
static nl_RNG *newrng (lua_State *L) { /* create rng object */ nl_RNG *r = (nl_RNG *) lua_newuserdata(L, sizeof(nl_RNG)); nl_getmetatable(L, RNG_MT); lua_setmetatable(L, -2); /* set user value */ luaL_newlibtable(L, rng_lib); lua_pushvalue(L, -2); /* rng object */ nl_register(L, rng_lib, 1); lua_setuservalue(L, -2); return r; }
static int imageReader(lua_State *L){ const char *filename = luaL_checkstring(L, 1); gdcm::ImageReader reader; reader.SetFileName( filename ); if ( !reader.Read() ) { lua_pushnil(L); return 1; } gdcm::Image & image = reader.GetImage(); const unsigned int* dimension = image.GetDimensions(); const double* spacing = image.GetSpacing(); const double intercept = image.GetIntercept(); const unsigned int dims = image.GetNumberOfDimensions(); const gdcm::PixelFormat pf = image.GetPixelFormat(); const int stype = pf.GetScalarType(); const unsigned long length = image.GetBufferLength(); // userdatum storing the (GDCM) image data char *udata = (char *)lua_newuserdata(L, (size_t)length); luaL_getmetatable(L, "caap.gdcm.image"); lua_setmetatable(L, -2); // store only the image buffer image.GetBuffer(udata); // create upvalue lua_newtable(L); lua_pushvalue(L, 1); lua_setfield(L, -2, "filename"); lua_pushinteger(L, length); lua_setfield(L, -2, "length"); lua_pushinteger(L, dimension[0]); lua_setfield(L, -2, "dimX"); lua_pushinteger(L, dimension[1]); lua_setfield(L, -2, "dimY"); lua_pushinteger(L, dims); lua_setfield(L, -2, "dimensions"); getIntercept(L, filename); lua_pushnumber(L, spacing[0]); lua_setfield(L, -2, "deltaX"); lua_pushnumber(L, spacing[1]); lua_setfield(L, -2, "deltaY"); lua_pushinteger(L, stype); lua_setfield(L, -2, "type"); // lua_pushinteger(L, pixel2mat(stype)); // lua_setfield(L, -2, "cvtype"); lua_pushfstring(L, "GDCM-Image{file: %s, dims(%d) [x: %d, y: %d], spacing [x: %f, y: %f], pixel: %s}", filename, dims, dimension[0], dimension[1], spacing[0], spacing[1], pixel2str(stype)); lua_setfield(L, -2, "asstring"); lua_setuservalue(L, -2); return 1; }
/* Lazily creates the uservalue if it doesn't exist. */ static void lupb_getuservalue(lua_State *L, int index) { lua_getuservalue(L, index); if (lua_isnil(L, -1)) { /* Lazily create and set userval. */ lua_pop(L, 1); /* nil. */ lua_pushvalue(L, index); /* userdata copy. */ lua_newtable(L); lua_setuservalue(L, -2); lua_pop(L, 1); /* userdata copy. */ lua_getuservalue(L, index); } assert(!lua_isnil(L, -1)); }
LUABIND_API object_rep* push_new_instance(lua_State* L, class_rep* cls) { void* storage = lua_newuserdata(L, sizeof(object_rep)); object_rep* result = new (storage) object_rep(0, cls); cls->get_table(L); // sets class_rep table as environement of userdata // Pops previous table (userdata remains on stack) lua_setuservalue(L,-2); //Pushes onto the stack registry[metatable_key] lua_rawgeti(L, LUA_REGISTRYINDEX, cls->metatable_ref()); lua_setmetatable(L, -2); // Pops previous table return result; }
/* Create and return a new proc object */ static struct proc *newproc(lua_State *L) { struct proc *proc = lua_newuserdata(L, sizeof *proc); proc->done = 1; proc->pid = 0; luaL_getmetatable(L, SP_PROC_META); lua_setmetatable(L, -2); lua_newtable(L); #if !defined(LUA_VERSION_NUM) || LUA_VERSION_NUM < 502 lua_setfenv(L, -2); #else lua_setuservalue(L, -2); #endif return proc; }
void* push_cdata(lua_State* L, int ct_usr, const struct ctype* ct) { struct cdata* cd; size_t sz = ct->is_reference ? sizeof(void*) : ctype_size(L, ct); ct_usr = lua_absindex(L, ct_usr); /* This is to stop valgrind from complaining. Bitfields are accessed in 8 * byte chunks so that the code doesn't have to deal with different access * patterns, but this means that occasionally it will read past the end of * the struct. As its not setting the bits past the end (only reading and * then writing the bits back) and the read is aligned its a non-issue, * but valgrind complains nonetheless. */ if (ct->has_bitfield) { sz = ALIGN_UP(sz, 7); } cd = (struct cdata*) lua_newuserdata(L, sizeof(struct cdata) + sz); *(struct ctype*) &cd->type = *ct; memset(cd+1, 0, sz); /* TODO: handle cases where lua_newuserdata returns a pointer that is not * aligned */ #if 0 assert((uintptr_t) (cd + 1) % 8 == 0); #endif #if LUA_VERSION_NUM == 501 if (!ct_usr || lua_isnil(L, ct_usr)) { push_upval(L, &niluv_key); lua_setfenv(L, -2); } #endif if (ct_usr && !lua_isnil(L, ct_usr)) { lua_pushvalue(L, ct_usr); lua_setuservalue(L, -2); } push_upval(L, &cdata_mt_key); lua_setmetatable(L, -2); if (!ct->is_defined && ct_usr && !lua_isnil(L, ct_usr)) { update_on_definition(L, ct_usr, -1); } return cd+1; }
/* l_obj[".c_instance"] = c_obj */ return 0; }; #ifdef LUA_VERSION_NUM /* lua 5.1 */ static int tolua_bnd_setpeer(lua_State* L) { /* stack: userdata, table */ if (!lua_isuserdata(L, -2)) { lua_pushstring(L, "Invalid argument #1 to setpeer: userdata expected."); lua_error(L); }; if (lua_isnil(L, -1)) { lua_pop(L, 1); lua_pushvalue(L, TOLUA_NOPEER); }; lua_setuservalue(L, -2); return 0; };
int luaT_setfenv52(lua_State *L, int iIndex) { int iType = lua_type(L, iIndex); switch(iType) { case LUA_TUSERDATA: lua_setuservalue(L, iIndex); return 1; case LUA_TFUNCTION: if(lua_iscfunction(L, iIndex)) { // Our convention: upvalue at #1 is environment if(lua_setupvalue(L, iIndex, 1) == nullptr) { lua_pop(L, 1); return 0; } return 1; } else { // Language convention: upvalue called _ENV is environment, which // might be shared with other functions. const char* sUpName = nullptr; for(int i = 1; (sUpName = lua_getupvalue(L, iIndex, i)) ; ++i) { lua_pop(L, 1); // lua_getupvalue puts the value on the stack, but we just want to replace it if(std::strcmp(sUpName, "_ENV") == 0) { luaL_loadstring(L, "local upv = ... return function() return upv end"); lua_insert(L, -2); lua_call(L, 1, 1); lua_upvaluejoin(L, iIndex, i, -1, 1); lua_pop(L, 1); return 1; } } lua_pop(L, 1); return 0; } default: return 0; } }
static TTree *newgrammar (lua_State *L, int arg) { int treesize; int frule = lua_gettop(L) + 2; /* position of first rule's key */ int n = collectrules(L, arg, &treesize); TTree *g = newtree(L, treesize); luaL_argcheck(L, n <= MAXRULES, arg, "grammar has too many rules"); g->tag = TGrammar; g->u.n = n; lua_newtable(L); /* create 'ktable' */ lua_setuservalue(L, -2); buildgrammar(L, g, frule, n); lua_getuservalue(L, -1); /* get 'ktable' for new tree */ finalfix(L, frule - 1, g, sib1(g)); initialrulename(L, g, frule); verifygrammar(L, g); lua_pop(L, 1); /* remove 'ktable' */ lua_insert(L, -(n * 2 + 2)); /* move new table to proper position */ lua_pop(L, n * 2 + 1); /* remove position table + rule pairs */ return g; /* new table at the top of the stack */ }
static int sfuserdata_create(lua_State *l) { lua_settop(l, 3); //[usf] assert(lua_type(l, 1) == LUA_TUSERDATA); luaL_checktype(l, 2, LUA_TSTRING); luaL_checktype(l, 3, LUA_TFUNCTION); struct sfuserdata *ud = //[usfu] (struct sfuserdata *)lua_newuserdata(l, sizeof(struct sfuserdata)); assert(ud != NULL); ud->funcState = NULL; ud->funcref = -1; lua_pushcfunction(l, sfuserdata_setmt); //[usfuf] lua_insert(l, 4); //[usffu] lua_call(l, 1, 1); //[usfu] lua_newtable(l); //[usfut] lua_pushvalue(l, 2); //[usfuts] lua_setfield(l, -2, "name"); //[usfut] lua_pushvalue(l, 1); //[usfutu] lua_setfield(l, -2, "dbud"); //[usfut] ud->funcState = lua_newthread(l); //[usfutT] lua_setfield(l, -2, "thread"); //[usfut] lua_setuservalue(l, -2); //[usfu] lua_pushvalue(l, 3); //[usfuf] ud->funcref = luaL_ref(l, LUA_REGISTRYINDEX); //[usfu] struct dbuserdata *uddb = (struct dbuserdata *)lua_touserdata(l, 1); assert(uddb != NULL); assert(uddb->db != NULL); sqlite3_create_function(uddb->db, lua_tostring(l, 2), -1, SQLITE_ANY, ud, sfuserdata_caller, NULL, NULL); return 1; }
luaA_Type dt_lua_init_singleton(lua_State *L, const char *unique_name, void *data) { char tmp_name[1024]; snprintf(tmp_name, sizeof(tmp_name), "dt_lua_singleton_%s", unique_name); luaA_Type type_id = luaA_type_add(L, tmp_name, sizeof(void *)); init_metatable(L, type_id); void **udata = lua_newuserdata(L, sizeof(void *)); lua_newtable(L); lua_setuservalue(L, -2); if(!data) { memset(udata, 0, sizeof(void *)); } else { *udata = data; luaL_getsubtable(L, LUA_REGISTRYINDEX, "dt_lua_gpointer_values"); lua_pushlightuserdata(L, data); lua_pushvalue(L,-3); lua_settable(L,-3); lua_pop(L,1); } lua_pushvalue(L, -1); luaL_setmetatable(L, tmp_name); lua_setfield(L, -3, "__singleton"); if(luaL_getmetafield(L, -1, "__init")) { lua_pushvalue(L, -2); // the new alocated object lua_pushlightuserdata(L, (void *)data); // forced to cast.. lua_call(L, 2, 0); } lua_remove(L, -2); return type_id; }
static int lua__map_new(lua_State *L) { imap *map = NULL; int divide = 1; ipos pos = {0.0, 0.0}; isize size; int top = lua_gettop(L); luaL_checktype(L, 1, LUA_TTABLE); divide = luaL_optint(L, 2, 1); if (lua_type(L, 3) == LUA_TTABLE) { lua_rawgeti(L, 3, 1); pos.x = luaL_optnumber(L, -1, 0); lua_rawgeti(L, 3, 2); pos.y = luaL_optnumber(L, -1, 0); } lua_settop(L, top); lua_rawgeti(L, 1, 1); size.w = luaL_checknumber(L, -1); lua_rawgeti(L, 1, 2); size.h = luaL_checknumber(L, -1); map = imapmake(&pos, &size, divide); if (map == NULL) { return 0; } LUA_BIND_META(L, imap, map, AOI_MAP); /* bind a fenv table onto map, to save units */ lua_newtable(L); lua_setuservalue(L, -2); DLOG("new map,map=%p\n", map); return 1; }
static int full_pushfunc(lua_State *L, luaA_Type type_id, const void *cin) { size_t type_size = luaA_typesize(L, type_id); void *udata = lua_newuserdata(L, type_size); lua_newtable(L); lua_setuservalue(L, -2); if(cin) { memcpy(udata, cin, type_size); } else { memset(udata, 0, type_size); } luaL_setmetatable(L, luaA_typename(L, type_id)); if(luaL_getmetafield(L, -1, "__init")) { lua_pushvalue(L, -2); // the new alocated object lua_pushlightuserdata(L, (void *)cin); // forced to cast.. lua_call(L, 2, 0); } return 1; }
/* l_obj[".c_instance"] = c_obj */ return 0; } #ifdef LUA_VERSION_NUM /* lua 5.1 */ static int tolua_bnd_setpeer(lua_State *L) { /* stack: userdata, table */ if (!lua_isuserdata(L, -2)) { lua_pushstring(L, "Invalid argument #1 to setpeer: userdata expected."); lua_error(L); } if (lua_isnil(L, -1)) { lua_pop(L, 1); lua_pushvalue(L, TOLUA_NOPEER); } #if LUA_VERSION_NUM > 501 lua_setuservalue(L, -2); #else lua_setfenv(L, -2); #endif return 0; }
static int queryuserdata_create(lua_State *l) { //the dbud, queryobj, params, assoc lua_settop(l, 4); //[uttb] assert(lua_type(l, 1) == LUA_TUSERDATA); luaL_checktype(l, 2, LUA_TTABLE); luaL_checktype(l, 3, LUA_TTABLE); luaL_checktype(l, 4, LUA_TBOOLEAN); struct dbuserdata *uddb = (struct dbuserdata *)lua_touserdata(l, 1); assert(uddb != NULL); assert(uddb->db != NULL); struct queryuserdata *ud = //[uttbu] (struct queryuserdata *)lua_newuserdata(l, sizeof(struct queryuserdata)); assert(ud != NULL); ud->stmt = NULL; if(lua_toboolean(l, 4)) { ud->assockey = 1; ud->intkey = 0; } else { ud->assockey = 0; ud->intkey = 1; } lua_remove(l, 4); //[uttu] lua_pushcfunction(l, queryuserdata_setmt); //[uttuf] lua_insert(l, 4); //[uttfu] lua_call(l, 1, 1); //[uttu] lua_getfield(l, 2, "_fullquery"); //[uttus] int rc = sqlite3_prepare_v2(uddb->db, lua_tostring(l, 5), -1, &ud->stmt, NULL); if(rc != SQLITE_OK) { return luaL_error(l, "Failed to parse SQL '%s': %s", lua_tostring(l, 5), sqlite3_errmsg(uddb->db)); } lua_pop(l, 1); //[uttu] lua_pushvalue(l, 2); //[uttut] lua_setuservalue(l, -2); //[uttu] lua_remove(l, 2); //[utu]; //the db is held by the query (the user value) lua_remove(l, 1); //[tu] lua_insert(l, 1); //[ut] //Bind the parameters lua_getfield(l, -1, "n"); //[utn] assert(lua_type(l, -1) == LUA_TNUMBER); int n = lua_tointeger(l, -1); lua_pop(l, 1); //[ut] while(n > 0) { lua_rawgeti(l, -1, n); //[ut?] switch(lua_type(l, -1)) { case LUA_TNIL: sqlite3_bind_null(ud->stmt, n); break; case LUA_TSTRING: sqlite3_bind_text(ud->stmt, n, lua_tostring(l, -1), -1, SQLITE_TRANSIENT); break; case LUA_TNUMBER: sqlite3_bind_double(ud->stmt, n, lua_tonumber(l, -1)); break; default: return luaL_error(l, "Unable to bind parameter type"); } --n; lua_pop(l, 1); //[ut] } lua_pop(l, 1); //[u] return 1; }
TOLUA_API void lua_setfenv (lua_State* L, int index) { lua_setuservalue(L, index); }
//in: linda_ud key [[val] ...] //out: true or nil int keepercall_set( lua_State* L) { bool_t should_wake_writers = FALSE; STACK_GROW( L, 6); // retrieve fifos associated with the linda push_table( L, 1); // ud key [val [, ...]] fifos lua_replace( L, 1); // fifos key [val [, ...]] // make sure we have a value on the stack if( lua_gettop( L) == 2) // fifos key { keeper_fifo* fifo; lua_pushvalue( L, -1); // fifos key key lua_rawget( L, 1); // fifos key fifo|nil // empty the fifo for the specified key: replace uservalue with a virgin table, reset counters, but leave limit unchanged! fifo = (keeper_fifo*) lua_touserdata( L, -1); if( fifo != NULL) // might be NULL if we set a nonexistent key to nil { // fifos key fifo if( fifo->limit < 0) // fifo limit value is the default (unlimited): we can totally remove it { lua_pop( L, 1); // fifos key lua_pushnil( L); // fifos key nil lua_rawset( L, -3); // fifos } else { // we create room if the fifo was full but it is no longer the case should_wake_writers = (fifo->limit > 0) && (fifo->count >= fifo->limit); lua_remove( L, -2); // fifos fifo lua_newtable( L); // fifos fifo {} lua_setuservalue( L, -2); // fifos fifo fifo->first = 1; fifo->count = 0; } } } else // set/replace contents stored at the specified key? { int count = lua_gettop( L) - 2; // number of items we want to store keeper_fifo* fifo; // fifos key [val [, ...]] lua_pushvalue( L, 2); // fifos key [val [, ...]] key lua_rawget( L, 1); // fifos key [val [, ...]] fifo|nil fifo = (keeper_fifo*) lua_touserdata( L, -1); if( fifo == NULL) // can be NULL if we store a value at a new key { // fifos key [val [, ...]] nil // no need to wake writers in that case, because a writer can't wait on an inexistent key lua_pop( L, 1); // fifos key [val [, ...]] fifo_new( L); // fifos key [val [, ...]] fifo lua_pushvalue( L, 2); // fifos key [val [, ...]] fifo key lua_pushvalue( L, -2); // fifos key [val [, ...]] fifo key fifo lua_rawset( L, 1); // fifos key [val [, ...]] fifo } else // the fifo exists, we just want to update its contents { // fifos key [val [, ...]] fifo // we create room if the fifo was full but it is no longer the case should_wake_writers = (fifo->limit > 0) && (fifo->count >= fifo->limit) && (count < fifo->limit); // empty the fifo for the specified key: replace uservalue with a virgin table, reset counters, but leave limit unchanged! lua_newtable( L); // fifos key [val [, ...]] fifo {} lua_setuservalue( L, -2); // fifos key [val [, ...]] fifo fifo->first = 1; fifo->count = 0; } fifo = prepare_fifo_access( L, -1); // move the fifo below the values we want to store lua_insert( L, 3); // fifos key fifo [val [, ...]] fifo_push( L, fifo, count); // fifos key fifo } return should_wake_writers ? (lua_pushboolean( L, 1), 1) : 0; }
static int lsettext(lua_State *L) { struct sprite *s = self(L); if (s->type != TYPE_LABEL) { return luaL_error(L, "Only label can set rich text"); } if (lua_isnoneornil(L, 2)) { s->data.rich_text = NULL; lua_pushnil(L); lua_setuservalue(L, 1); return 0; } if (lua_isstring(L, 2)) { s->data.rich_text = (struct rich_text*)lua_newuserdata(L, sizeof(struct rich_text)); s->data.rich_text->text = lua_tostring(L, 2); s->data.rich_text->count = 0; s->data.rich_text->fields = NULL; lua_createtable(L, 2, 0); lua_pushvalue(L, 2); lua_rawseti(L, -2, 1); lua_pushvalue(L, 3); lua_rawseti(L, -2, 2); lua_setuservalue(L, 1); return 0; } s->data.rich_text = NULL; if (!lua_istable(L, 2) || lua_rawlen(L, 2) != 2) { return luaL_error(L, "rich text must has a table with two items"); } lua_rawgeti(L, 2, 1); const char *txt = luaL_checkstring(L, -1); lua_pop(L, 1); lua_rawgeti(L, 2, 2); int cnt = lua_rawlen(L, -1); lua_pop(L, 1); struct rich_text *rich = (struct rich_text*)lua_newuserdata(L, sizeof(struct rich_text)); rich->text = txt; rich->count = cnt; int size = cnt * sizeof(struct label_field); rich->fields = (struct label_field*)lua_newuserdata(L, size); struct label_field *fields = rich->fields; int i; lua_rawgeti(L, 2, 2); for (i=0; i<cnt; i++) { lua_rawgeti(L, -1, i+1); if (!lua_istable(L,-1)) { return luaL_error(L, "rich text unit must be table"); } lua_rawgeti(L, -1, 1); //start ((struct label_field*)(fields+i))->start = luaL_checkinteger(L, -1); lua_pop(L, 1); lua_rawgeti(L, -1, 2); //end ((struct label_field*)(fields+i))->end = luaL_checkinteger(L, -1); lua_pop(L, 1); lua_rawgeti(L, -1, 3); //color ((struct label_field*)(fields+i))->color = luaL_checkunsigned(L, -1); lua_pop(L, 1); //extend here lua_pop(L, 1); } lua_pop(L, 1); lua_createtable(L,3,0); lua_pushvalue(L, 3); lua_rawseti(L, -2, 1); lua_pushvalue(L, 4); lua_rawseti(L, -2, 2); lua_rawgeti(L, 2, 1); lua_rawseti(L, -2, 3); lua_setuservalue(L, 1); s->data.rich_text = rich; return 0; }
static int lnewproxy(lua_State *L) { static struct pack_part part = { { NULL, // mat 0xffffffff, // color 0, // additive PROGRAM_DEFAULT, 0, // _dummy }, // trans 0, // component_id 0, // touchable }; static struct pack_frame frame = { &part, 1, // n 0, // _dummy }; static struct pack_action action = { NULL, // name 1, // number 0, // start_frame }; static struct pack_animation ani = { &frame, &action, 1, // frame_number 1, // action_number 1, // component_number 0, // _dummy {{ "proxy", // name 0, // id 0, // _dummy }}, }; struct sprite * s = lua_newuserdata(L, sizeof(struct sprite)); lua_newtable(L); lua_setuservalue(L, -2); s->parent = NULL; s->s.ani = &ani; s->t.mat = NULL; s->t.color = 0xffffffff; s->t.additive = 0; s->t.program = PROGRAM_DEFAULT; s->message = false; s->visible = true; s->multimount = true; s->name = NULL; s->id = 0; s->type = TYPE_ANIMATION; s->start_frame = 0; s->total_frame = 0; s->frame = 0; s->material = NULL; s->data.children[0] = NULL; sprite_action(s, NULL); return 1; }
/* ** Create a new 'ktable' to the pattern at the top of the stack. */ static void newktable (lua_State *L, int n) { lua_createtable(L, n, 0); /* create a fresh table */ lua_setuservalue(L, -2); /* set it as 'ktable' for pattern */ }
/* ** copy 'ktable' of element 'idx' to new tree (on top of stack) */ static void copyktable (lua_State *L, int idx) { lua_getuservalue(L, idx); lua_setuservalue(L, -2); }