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; }
void * qlua_checkLatticeType(lua_State *L, int idx, QLUA_Type t_id, const char *name) { void *p = lua_touserdata(L, idx); int p_id; if (p == NULL) goto bad_value; if (luaL_getmetafield(L, idx, a_type_key) == 0) goto bad_value; p_id = luaL_checkint(L, -1); lua_pop(L, 1); if (p_id != t_id) goto bad_value; return p; bad_value: luaL_error(L, "expecting %s", name); return NULL; }
static int format_index(lua_State*L) { uint32_t width,height; int index = luaL_checkoption(L,-1,NULL,format_fields_name); luaL_getmetafield(L,-2,"__associated_object"); dt_imageio_module_format_t * format = lua_touserdata(L,-1); dt_imageio_module_data_t * data = lua_touserdata(L,-3); switch(index) { case GET_FORMAT_PLUGIN_NAME: lua_pushstring(L,format->plugin_name); return 1; case GET_FORMAT_NAME: lua_pushstring(L,format->name()); return 1; case GET_EXTENSION: lua_pushstring(L,format->extension(data)); return 1; case GET_MIME: lua_pushstring(L,format->mime(data)); return 1; case GET_MAX_WIDTH: width=0; height=0; format->dimension(format,&width,&height); lua_pushinteger(L,width); return 1; case GET_MAX_HEIGHT: width=0; height=0; format->dimension(format,&width,&height); lua_pushinteger(L,height); return 1; default: return luaL_error(L,"should never happen %d",index); } }
// garbage collection metamethod static int gc_T(lua_State *L) { if (luaL_getmetafield(L, 1, "do not trash")) { lua_pushvalue(L, 1); lua_rawget(L, -2); if (!lua_isnil(L, -1)) { return 0; } lua_pop(L, 2); } T **ud = static_cast<T**>(lua_touserdata(L, 1)); if (ud == nullptr) { return 0; } T *obj = *ud; if (obj == nullptr) { return 0; } LunarWrapper::exit(obj, L); // FIXME: Weird, sometimes we try to delete a pointer to somewhere *inside* the T object here... delete obj; luaL_getmetatable(L, T::className); // [-0,+1,-] if (lua_isnil(L, -1)) { return luaL_error(L, "'%s' missing metatable", T::className); } lua_getfield(L, -1, "userdata"); // [-0,+1,e] lua_pushlightuserdata(L, obj); // [-0,+1,-] lua_pushnil(L); // [-0,+1,-] lua_rawset(L, -3); // [-2,+0,e] return 0; }
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; }
static int get_widget_params(lua_State *L) { struct dt_lua_widget_type_t *widget_type = lua_touserdata(L, lua_upvalueindex(1)); if(G_TYPE_IS_ABSTRACT(widget_type->gtk_type)){ luaL_error(L,"Trying to create a widget of an abstract type : %s\n",widget_type->name); } lua_widget widget= malloc(widget_type->alloc_size); widget->widget = gtk_widget_new(widget_type->gtk_type,NULL); g_object_ref_sink(widget->widget); widget->type = widget_type; luaA_push_type(L,widget_type->associated_type,&widget); dt_lua_type_gpointer_alias_type(L,widget_type->associated_type,widget,widget->widget); init_widget_sub(L,widget_type); luaL_getmetafield(L,-1,"__gtk_signals"); lua_pushnil(L); /* first key */ while(lua_next(L, -2) != 0) { g_signal_connect(widget->widget, lua_tostring(L,-2), G_CALLBACK(lua_touserdata(L,-1)), widget); lua_pop(L,1); } lua_pop(L,1); return 1; }
LUALIB_API const char *luaL_tolstring (lua_State *L, int idx, size_t *len) { if (luaL_callmeta(L, idx, "__tostring")) { /* metafield? */ if (!lua_isstring(L, -1)) luaL_error(L, "'__tostring' must return a string"); } else { switch (lua_type(L, idx)) { case LUA_TNUMBER: { if (lua_isinteger(L, idx)) lua_pushfstring(L, "%I", (LUAI_UACINT)lua_tointeger(L, idx)); else lua_pushfstring(L, "%f", (LUAI_UACNUMBER)lua_tonumber(L, idx)); break; } case LUA_TSTRING: lua_pushvalue(L, idx); break; case LUA_TBOOLEAN: lua_pushstring(L, (lua_toboolean(L, idx) ? "true" : "false")); break; case LUA_TNIL: lua_pushliteral(L, "nil"); break; default: { int tt = luaL_getmetafield(L, idx, "__name"); /* try name */ const char *kind = (tt == LUA_TSTRING) ? lua_tostring(L, -1) : luaL_typename(L, idx); lua_pushfstring(L, "%s: %p", kind, lua_topointer(L, idx)); if (tt != LUA_TNIL) lua_remove(L, -2); /* remove '__name' */ break; } } } return lua_tolstring(L, -1, len); }
/** * Gets all attribute names of an extended variable name. This is useful for tab completion. */ std::vector<std::string> lua_kernel_base::get_attribute_names(const std::string & input) { std::vector<std::string> ret; std::string base_path = input; std::size_t last_dot = base_path.find_last_of('.'); std::string partial_name = base_path.substr(last_dot + 1); base_path.erase(last_dot); std::string load = "return " + base_path; lua_State* L = mState; int save_stack = lua_gettop(L); int result = luaL_loadstring(L, load.c_str()); if(result != LUA_OK) { // This isn't at error level because it's a really low priority error; it just means the user tried to tab-complete something that doesn't exist. LOG_LUA << "Error when attempting tab completion:\n"; LOG_LUA << luaL_checkstring(L, -1) << '\n'; // Just return an empty list; no matches were found lua_settop(L, save_stack); return ret; } luaW_pcall(L, 0, 1); if(lua_istable(L, -1) || lua_isuserdata(L, -1)) { int top = lua_gettop(L); int obj = lua_absindex(L, -1); if(luaL_getmetafield(L, obj, "__tab_enum") == LUA_TFUNCTION) { lua_pushvalue(L, obj); lua_pushlstring(L, partial_name.c_str(), partial_name.size()); luaW_pcall(L, 2, 1); ret = lua_check<std::vector<std::string>>(L, -1); } else if(lua_type(L, -1) != LUA_TTABLE) { LOG_LUA << "Userdata missing __tab_enum meta-function for tab completion"; lua_settop(L, save_stack); return ret; } else { lua_settop(L, top); // Metafunction not found, so use lua_next to enumerate the table for(lua_pushnil(L); lua_next(L, obj); lua_pop(L, 1)) { if(lua_type(L, -2) == LUA_TSTRING) { std::string attr = lua_tostring(L, -2); if(attr.empty()) { continue; } if(!isalpha(attr[0]) && attr[0] != '_') { continue; } if(std::any_of(attr.begin(), attr.end(), [](char c){ return !isalpha(c) && !isdigit(c) && c != '_'; })) { continue; } if(attr.substr(0, partial_name.size()) == partial_name) { ret.push_back(base_path + "." + attr); } } } } } lua_settop(L, save_stack); return ret; }
static int js_generator_value(lua_State *L) { int max; int is_array; int type = lua_type(L, 2); switch ( type ) { case LUA_TNIL: return js_generator_null(L); case LUA_TNUMBER: return js_generator_number(L); case LUA_TBOOLEAN: return js_generator_boolean(L); case LUA_TSTRING: return js_generator_string(L); case LUA_TUSERDATA: if ( lua_topointer(L, 2) == js_null ) { return js_generator_null(L); } case LUA_TLIGHTUSERDATA: case LUA_TTABLE: case LUA_TFUNCTION: case LUA_TTHREAD: if ( luaL_getmetafield(L, 2, "__gen_json") ) { if ( lua_isfunction(L, -1) ) { lua_settop(L, 3); /* gen, obj, func */ lua_insert(L, 1); /* func, gen, obj */ lua_insert(L, 2); /* func, obj, gen */ lua_call(L, 2, 0); return 0; } lua_pop(L, 1); } /* Simply ignore it, perhaps we should warn? */ if ( type != LUA_TTABLE ) return 0; max = 0; is_array = 1; /* First iterate over the table to see if it is an array: */ lua_pushnil(L); while ( lua_next(L, 2) != 0 ) { if ( lua_type(L, -2) == LUA_TNUMBER ) { double num = lua_tonumber(L, -2); if ( num == floor(num) ) { if ( num > max ) max = num; } else { lua_pop(L, 2); is_array = 0; break; } } else { lua_pop(L, 2); is_array = 0; break; } lua_pop(L, 1); } if ( is_array ) { int i; js_generator_open_array(L); for ( i=1; i <= max; i++ ) { lua_pushinteger(L, i); lua_gettable(L, 2); /* RECURSIVE CALL: gen, obj, ?, val, func, gen, val */ lua_pushcfunction(L, js_generator_value); lua_pushvalue(L, 1); lua_pushvalue(L, -3); lua_call(L, 2, 0); lua_pop(L, 1); } } else { js_generator_open_object(L); lua_pushnil(L); while ( lua_next(L, 2) != 0 ) { /* gen, obj, ?, key, val, func, gen, key */ lua_pushcfunction(L, js_generator_string); lua_pushvalue(L, 1); if ( lua_isstring(L, -4) ) { lua_pushvalue(L, -4); } else { /* Must coerce into a string: */ lua_getglobal(L, "tostring"); lua_pushvalue(L, -5); lua_call(L, 1, 1); } lua_call(L, 2, 0); /* RECURSIVE CALL: gen, obj, ?, key, val, func, gen, val */ lua_pushcfunction(L, js_generator_value); lua_pushvalue(L, 1); lua_pushvalue(L, -3); lua_call(L, 2, 0); lua_pop(L, 1); } } js_generator_close(L); return 0; case LUA_TNONE: lua_pushfstring(L, "MissingArgument: second parameter to js_generator_value() must be defined at %s line %d", type, __FILE__, __LINE__); default: lua_pushfstring(L, "Unreachable: js_generator_value passed lua type (%d) not recognized at %s line %d", type, __FILE__, __LINE__); } /* Shouldn't get here: */ lua_error(L); return 0; }
static void mar_encode_value(lua_State *L, mar_Buffer *buf, int val, size_t *idx, int nowrap) { size_t l; int val_type = lua_type(L, val); lua_pushvalue(L, val); buf_write(L, (void*)&val_type, MAR_CHR, buf); switch (val_type) { case LUA_TBOOLEAN: { int int_val = lua_toboolean(L, -1); buf_write(L, (void*)&int_val, MAR_CHR, buf); break; } case LUA_TSTRING: { const char *str_val = lua_tolstring(L, -1, &l); buf_write(L, (void*)&l, MAR_I32, buf); buf_write(L, str_val, l, buf); break; } case LUA_TNUMBER: { lua_Number num_val = lua_tonumber(L, -1); buf_write(L, (void*)&num_val, MAR_I64, buf); break; } case LUA_TLIGHTUSERDATA: { if(nowrap) luaL_error(L, "light userdata not permitted"); void * ptr_val = lua_touserdata(L, -1); long long v = (long long)ptr_val; buf_write(L, (char*)&v, MAR_I64, buf); break; } case LUA_TTABLE: { int tag, ref; lua_pushvalue(L, -1); lua_rawget(L, SEEN_IDX); if (!lua_isnil(L, -1)) { ref = lua_tointeger(L, -1); tag = MAR_TREF; buf_write(L, (void*)&tag, MAR_CHR, buf); buf_write(L, (void*)&ref, MAR_I32, buf); lua_pop(L, 1); } else { mar_Buffer rec_buf; lua_pop(L, 1); /* pop nil */ if (luaL_getmetafield(L, -1, "__persist")) { tag = MAR_TUSR; lua_pushvalue(L, -2); /* self */ lua_call(L, 1, 1); if (!lua_isfunction(L, -1)) { luaL_error(L, "__persist must return a function"); } lua_remove(L, -2); /* __persist */ lua_newtable(L); lua_pushvalue(L, -2); /* callback */ lua_rawseti(L, -2, 1); buf_init(L, &rec_buf); mar_encode_table(L, &rec_buf, idx, nowrap); buf_write(L, (void*)&tag, MAR_CHR, buf); buf_write(L, (void*)&rec_buf.head, MAR_I32, buf); buf_write(L, rec_buf.data, rec_buf.head, buf); buf_done(L, &rec_buf); lua_pop(L, 1); } else { tag = MAR_TVAL; lua_pushvalue(L, -1); lua_pushinteger(L, (*idx)++); lua_rawset(L, SEEN_IDX); lua_pushvalue(L, -1); buf_init(L, &rec_buf); mar_encode_table(L, &rec_buf, idx, nowrap); lua_pop(L, 1); buf_write(L, (void*)&tag, MAR_CHR, buf); buf_write(L, (void*)&rec_buf.head, MAR_I32, buf); buf_write(L, rec_buf.data,rec_buf.head, buf); buf_done(L, &rec_buf); } } break; } case LUA_TFUNCTION: { int tag, ref; lua_pushvalue(L, -1); lua_rawget(L, SEEN_IDX); if (!lua_isnil(L, -1)) { ref = lua_tointeger(L, -1); tag = MAR_TREF; buf_write(L, (void*)&tag, MAR_CHR, buf); buf_write(L, (void*)&ref, MAR_I32, buf); lua_pop(L, 1); } else { mar_Buffer rec_buf; int i; lua_Debug ar; lua_pop(L, 1); /* pop nil */ lua_pushvalue(L, -1); lua_getinfo(L, ">nuS", &ar); //printf("Function name='%s' type='%s' nups=%d\n",ar.namewhat,ar.what,ar.nups); if (ar.what[0] != 'L') { luaL_error(L, "attempt to persist a C function '%s'", ar.name); } tag = MAR_TVAL; lua_pushvalue(L, -1); lua_pushinteger(L, (*idx)++); lua_rawset(L, SEEN_IDX); lua_pushvalue(L, -1); buf_init(L, &rec_buf); lua_dump(L, (lua_Writer)buf_write, &rec_buf); buf_write(L, (void*)&tag, MAR_CHR, buf); buf_write(L, (void*)&rec_buf.head, MAR_I32, buf); buf_write(L, rec_buf.data, rec_buf.head, buf); buf_done(L, &rec_buf); lua_pop(L, 1); lua_newtable(L); for (i=1; i <= ar.nups; i++) { #if LUA_VERSION_NUM > 501 const char * str=lua_getupvalue(L, -2, i); if(!strncmp(str,"_ENV",4)) { //printf("Stripping _ENV\n"); lua_pop(L,1); lua_pushliteral(L,LEDA_ENV_MARKER); } #else lua_getupvalue(L, -2, i); #endif lua_rawseti(L, -2, i); } buf_init(L, &rec_buf); mar_encode_table(L, &rec_buf, idx, nowrap); buf_write(L, (void*)&rec_buf.head, MAR_I32, buf); buf_write(L, rec_buf.data, rec_buf.head, buf); buf_done(L, &rec_buf); lua_pop(L, 1); } break; } case LUA_TUSERDATA: { int tag, ref; lua_pushvalue(L, -1); lua_rawget(L, SEEN_IDX); if (!lua_isnil(L, -1)) { ref = lua_tointeger(L, -1); tag = MAR_TREF; buf_write(L, (void*)&tag, MAR_CHR, buf); buf_write(L, (void*)&ref, MAR_I32, buf); lua_pop(L, 1); } else { mar_Buffer rec_buf; lua_pop(L, 1); /* pop nil */ if (!nowrap && luaL_getmetafield(L, -1, "__wrap")) { tag = MAR_TUSR; lua_pushvalue(L, -2); lua_pushinteger(L, (*idx)++); lua_rawset(L, SEEN_IDX); lua_pushvalue(L, -2); lua_call(L, 1, 1); if (!lua_isfunction(L, -1)) { luaL_error(L, "__wrap must return a function"); } lua_newtable(L); lua_pushvalue(L, -2); lua_rawseti(L, -2, 1); lua_remove(L, -2); buf_init(L, &rec_buf); mar_encode_table(L, &rec_buf, idx, nowrap); buf_write(L, (void*)&tag, MAR_CHR, buf); buf_write(L, (void*)&rec_buf.head, MAR_I32, buf); buf_write(L, rec_buf.data, rec_buf.head, buf); buf_done(L, &rec_buf); } else if (luaL_getmetafield(L, -1, "__persist")) { tag = MAR_TUSR; lua_pushvalue(L, -2); lua_pushinteger(L, (*idx)++); lua_rawset(L, SEEN_IDX); lua_pushvalue(L, -2); lua_call(L, 1, 1); if (!lua_isfunction(L, -1)) { luaL_error(L, "__persist must return a function"); } lua_newtable(L); lua_pushvalue(L, -2); lua_rawseti(L, -2, 1); lua_remove(L, -2); buf_init(L, &rec_buf); mar_encode_table(L, &rec_buf, idx, nowrap); buf_write(L, (void*)&tag, MAR_CHR, buf); buf_write(L, (void*)&rec_buf.head, MAR_I32, buf); buf_write(L, rec_buf.data, rec_buf.head, buf); buf_done(L, &rec_buf); } else { luaL_error(L, "attempt to encode userdata (no __wrap hook - or not permited - and no __persist hook)"); } lua_pop(L, 1); } break; } case LUA_TNIL: break; default: luaL_error(L, "invalid value type (%s)", lua_typename(L, val_type)); } lua_pop(L, 1); }
int dt_lua_autotype_next(lua_State *L) { if(luaL_getmetafield(L,-2,"__len") ) { lua_pushvalue(L,-3); lua_call(L,1,1); int length = lua_tonumber(L,-1); lua_pop(L,1); int key = 0; if(lua_isnil(L,-1) && length > 0) { key = 1; } else if(lua_isnumber(L,-1) && lua_tonumber(L,-1) < length) { key = lua_tonumber(L,-1) +1; } else if(lua_isnumber(L,-1) && lua_tonumber(L,-1) == length) { // numbers are done, move-on to something else lua_pop(L,1); lua_pushnil(L); } if(key) { lua_pop(L,1); lua_pushnumber(L,key); lua_pushnumber(L,key); lua_gettable(L,-3); return 2; } } // stack at this point : {object,key} (key is nil if it was length) int key_in_get = false; luaL_getmetafield(L,-2,"__get"); if(lua_isnil(L,-2)) { key_in_get = true; } else { lua_pushvalue(L,-2); lua_gettable(L,-2); if(lua_isnil(L,-1)) { key_in_get = false; lua_pop(L,2); } else { key_in_get = true; lua_pop(L,1); } } if(key_in_get) { lua_pushvalue(L,-2); if(lua_next(L,-2)) { // we have a next lua_pop(L,1); lua_remove(L,-2); lua_remove(L,-2); lua_pushvalue(L,-1); lua_gettable(L,-3); return 2; } else { // key was the last for __get lua_pop(L,2); lua_pushnil(L); } } // stack at this point : {object,key} (key is nil if it was the last of __get) if(luaL_getmetafield(L,-2,"__default_next")) { lua_pushvalue(L,-3); lua_pushvalue(L,-3); lua_call(L,2,2); if(!lua_isnil(L,-1)) { lua_remove(L,-3); // we have a next return 2; } else { // we don't have a next, lua_remove(L,-3); lua_remove(L,-3); return 1; } } else { return 1; } }
void initTimerModule(lua_State* L) { // Load timer metatable luaL_newmetatable(L, Meta); // Duplicate the metatable on the stack. lua_pushvalue(L, -1); // metatable.__index = metatable lua_setfield(L, -2, "__index"); // Put the members into the metatable. const luaL_Reg functions[] = { { "__index", [](lua_State* L) { std::string fieldName(script::get<const char*>(L, 2)); if(luaL_getmetafield(L, 1, std::string("get_" + fieldName).c_str())) { lua_pushvalue(L, 1); lua_call(L, 1, 1); return 1; } return luaL_getmetafield(L, 1, fieldName.c_str()); } }, { "__newindex", [](lua_State* L) { std::string fieldName(script::get<const char*>(L, 2)); /* L, 3 is the value to set. */ if(luaL_getmetafield(L, 1, std::string("set_" + fieldName).c_str())) { lua_pushvalue(L, 1); lua_pushvalue(L, 3); lua_call(L, 2, 0); } return 0; } }, { "__tostring", [](lua_State* L) { script::push(L, Meta); return 1; } }, { "__pairs", [](lua_State* L) { lua_getglobal(L, "next"); luaL_getmetatable(L, Meta); lua_pushnil(L); return 3; } }, { "get_time", [](lua_State* L) { script::push(L, script::instance(L).timer().getTime()); return 1; } }, { "get_gap", [](lua_State* L) { script::push(L, script::instance(L).timer().getDelta()); return 1; } }, { "get_fps", [](lua_State* L) { script::push(L, script::instance(L).timer().getFPS()); return 1; } }, { "get_speed", [](lua_State* L) { script::push(L, int(script::instance(L).timer().getSpeed())); return 1; } }, { "set_speed", [](lua_State* L) { auto speed = plum::TimerSpeed(script::get<int>(L, 2)); script::instance(L).timer().setSpeed(speed); return 0; } }, { "get_maxGap", [](lua_State* L) { script::push(L, script::instance(L).timer().getMaxDelta()); return 1; } }, { "set_maxGap", [](lua_State* L) { auto delta = script::get<int>(L, 2); script::instance(L).timer().setMaxDelta(delta); return 0; } }, {nullptr, nullptr} }; luaL_setfuncs(L, functions, 0); lua_pop(L, 1); // Push plum namespace. lua_getglobal(L, "plum"); // Create timer namespace lua_newtable(L); lua_pushvalue(L, -1); lua_setfield(L, -3, "timer"); luaL_getmetatable(L, Meta); lua_setmetatable(L, -2); // Pop timer namespace. lua_pop(L, 1); // Pop plum namespace. lua_pop(L, 1); }
static int name_member(lua_State*L) { luaL_getmetafield(L,1,"__associated_object"); dt_imageio_module_format_t * format = lua_touserdata(L,-1); lua_pushstring(L,format->name()); return 1; }
static int mh_index (lua_State* l) { menu* m = lua_touserdata(l,1); if (lua_isnumber(l,2)) { if (!m->sub) return 0; int n = lua_tointeger(l,2); if (n==0) n=-1; if (n<0) n += GetMenuItemCount(m->menu); else n--; MENUITEMINFO mii; mii.cbSize = sizeof(MENUITEMINFO); mii.fMask = MIIM_ID | MIIM_SUBMENU; if (!GetMenuItemInfo(m->menu, n, TRUE, &mii)) return 0; menu x; x.sub = mii.hSubMenu!=0; x.origin = m->origin; x.parent = m->menu; x.position = n; if (mii.hSubMenu!=0) x.menu = mii.hSubMenu; else x.command = mii.wID; lua_settop(l,0); lua_pushfulluserdata(l, &x, sizeof(x), "menuhandle"); return 1; } const char* nm = luaL_checkstring(l,2); if (streq(nm, "checked")) { if (m->sub) luaL_error(l, "unsupported operation"); MENUITEMINFO mii; mii.cbSize = sizeof(MENUITEMINFO); mii.fMask = MIIM_STATE | MIIM_FTYPE; if (!GetMenuItemInfo(m->parent, m->command, FALSE, &mii)) return 0; lua_pushboolean(l, 0!=(mii.fState&MFS_CHECKED)); return 1; } else if (streq(nm, "radio")) { if (m->sub) luaL_error(l, "unsupported operation"); MENUITEMINFO mii; mii.cbSize = sizeof(MENUITEMINFO); mii.fMask = MIIM_FTYPE; if (!GetMenuItemInfo(m->parent, m->command, FALSE, &mii)) return 0; lua_pushboolean(l, 0!=(mii.fType&MFT_RADIOCHECK)); return 1; } else if (streq(nm, "enabled")) { if (m->sub) luaL_error(l, "unsupported operation"); MENUITEMINFO mii; mii.cbSize = sizeof(MENUITEMINFO); mii.fMask = MIIM_STATE; if (!GetMenuItemInfo(m->parent, m->command, FALSE, &mii)) return 0; lua_settop(l,0); lua_pushboolean(l, 0==(mii.fState&MFS_DISABLED)); return 1; } else if (streq(nm, "text")) { const wchar_t* wc = mh_getLabel(m); const char* mbc = strcvt(wc, CP_UTF16, CP_UTF8, NULL); lua_pushstring(l, mbc); free(mbc); free(wc); return 1; } else if (streq(nm, "name")) { const char* menuName = GetMenuName(m->parent, m->position); lua_settop(l,0); lua_pushstring(l,menuName); return 1; } else if (streq(nm, "accelerator")) { int f, k; if (!(m->sub) && findAccelerator(m->command, &f, &k)) { const wchar_t* wkn = getKeyName(f,k,0); const char* kn = strcvt(wkn, CP_UTF16, CP_UTF8, NULL); lua_pushstring(l,kn); free(kn); free(wkn); return 1; } return 0; } else if (streq(nm, "onAction")) { if (m->sub) return 0; if (m->command>=IDM_CUSTOMCOMMAND) lua_pushluafunction(l, *getCustomCommand(m->command - IDM_CUSTOMCOMMAND)); else { lua_pushinteger(l, m->command); lua_pushcclosure(l, mh_commandclosure, 1); } return 1; } else if (streq(nm, "builtIn")) { if (m->sub) return 0; lua_pushboolean(l, m->command<IDM_CUSTOMCOMMAND); return 1; } else if (streq(nm, "parent")) { menu x; x.sub = TRUE; x.parent = GetParentMenu(m->parent, m->origin, &(x.position)); x.menu = m->parent; x.origin = m->origin; if (!x.parent) return 0; lua_settop(l,0); lua_pushfulluserdata(l, &x, sizeof(x), "menuhandle"); return 1; } else if (streq(nm, "parentHandle")) { lua_pushlightuserdata(l, m->parent); return 1; } else if (streq(nm, "handle") || streq(nm, "command")) { if (m->sub) lua_pushlightuserdata(l, m->command); else lua_pushinteger(l, m->command); return 1; } //SUITE else if (luaL_getmetafield(l, 1, nm)) return 1; else if (m->sub) { MENUITEMINFO mii; mii.cbSize = sizeof(MENUITEMINFO); mii.fMask = MIIM_ID | MIIM_SUBMENU | MIIM_DATA; for (int i=0, n=GetMenuItemCount(m->menu); i<n; i++) { if (!GetMenuItemInfo(m->menu, i, TRUE, &mii)) continue; if (mii.dwItemData && streq(nm, mii.dwItemData)) { menu x; x.sub = mii.hSubMenu!=0; x.parent = m->menu; x.origin = m->origin; x.position = i; if (mii.hSubMenu!=0) x.menu = mii.hSubMenu; else x.command = mii.wID; lua_settop(l,0); lua_pushfulluserdata(l, &x, sizeof(x), "menuhandle"); return 1; }}} return 0; }
static void lua_field_inspect_table(struct lua_State *L, struct luaL_serializer *cfg, int idx, struct luaL_field *field) { assert(lua_type(L, idx) == LUA_TTABLE); const char *type; uint32_t size = 0; uint32_t max = 0; /* Try to get field LUAL_SERIALIZER_TYPE from metatable */ if (!cfg->encode_load_metatables || !luaL_getmetafield(L, idx, LUAL_SERIALIZE)) goto skip; if (lua_isfunction(L, -1)) { /* copy object itself */ lua_pushvalue(L, idx); lua_call(L, 1, 1); /* replace obj with the unpacked value */ lua_replace(L, idx); luaL_tofield(L, cfg, idx, field); return; } else if (!lua_isstring(L, -1)) { luaL_error(L, "invalid " LUAL_SERIALIZE " value"); } type = lua_tostring(L, -1); if (strcmp(type, "array") == 0 || strcmp(type, "seq") == 0 || strcmp(type, "sequence") == 0) { field->type = MP_ARRAY; /* Override type */ field->size = luaL_arrlen(L, idx); /* YAML: use flow mode if __serialize == 'seq' */ if (cfg->has_compact && type[3] == '\0') field->compact = true; lua_pop(L, 1); /* type */ return; } else if (strcmp(type, "map") == 0 || strcmp(type, "mapping") == 0) { field->type = MP_MAP; /* Override type */ field->size = luaL_maplen(L, idx); /* YAML: use flow mode if __serialize == 'map' */ if (cfg->has_compact && type[3] == '\0') field->compact = true; lua_pop(L, 1); /* type */ return; } else { luaL_error(L, "invalid " LUAL_SERIALIZE " value"); } skip: field->type = MP_ARRAY; /* Calculate size and check that table can represent an array */ lua_pushnil(L); while (lua_next(L, idx)) { size++; lua_pop(L, 1); /* pop the value */ lua_Number k; if (lua_type(L, -1) != LUA_TNUMBER || ((k = lua_tonumber(L, -1)) != size && (k < 1 || floor(k) != k))) { /* Finish size calculation */ while (lua_next(L, idx)) { size++; lua_pop(L, 1); /* pop the value */ } field->type = MP_MAP; field->size = size; return; } if (k > max) max = k; } /* Encode excessively sparse arrays as objects (if enabled) */ if (cfg->encode_sparse_ratio > 0 && max > size * (uint32_t)cfg->encode_sparse_ratio && max > (uint32_t)cfg->encode_sparse_safe) { if (!cfg->encode_sparse_convert) luaL_error(L, "excessively sparse array"); field->type = MP_MAP; field->size = size; return; } assert(field->type == MP_ARRAY); field->size = max; }
static void on_export_selection(gpointer instance,dt_control_image_enumerator_t * export_descriptor, gpointer user_data){ lua_State* L = darktable.lua_state; dt_control_export_t *export_data= (dt_control_export_t*)export_descriptor->data; dt_imageio_module_storage_t *mstorage = dt_imageio_get_storage_by_index(export_data->storage_index); g_assert(mstorage); dt_imageio_module_data_t *fdata = mstorage->get_params(mstorage); luaA_push_typeid(L,mstorage->parameter_lua_type,fdata); mstorage->free_params(mstorage,fdata); dt_imageio_module_format_t *mformat = dt_imageio_get_format_by_index(export_data->format_index); g_assert(mformat); fdata = mformat->get_params(mformat); luaA_push_typeid(L,mformat->parameter_lua_type,fdata); mformat->free_params(mformat,fdata); GList * elt = export_descriptor->index; lua_newtable(L); while(elt) { luaA_push(L,dt_lua_image_t,&elt->data); luaL_ref(L,-2); elt = g_list_next(elt); } g_list_free(export_descriptor->index); export_descriptor->index =NULL; dt_lua_trigger_event("pre-export",3,3); // get the new storage data and the new storage luaL_getmetafield(L,-3,"__associated_object"); mstorage = lua_touserdata(L,-1); lua_pop(L,1); fdata = mstorage->get_params(mstorage); luaL_getmetafield(L,-3,"__luaA_Type"); luaA_Type storage_type = lua_tointeger(L,-1); lua_pop(L,1); luaA_to_typeid(L,storage_type,fdata,-3); mstorage->set_params(mstorage,fdata,mstorage->params_size(mstorage)); mstorage->free_params(mstorage,fdata); export_data->storage_index = dt_imageio_get_index_of_storage(mstorage); // get the new format data and the new format luaL_getmetafield(L,-2,"__associated_object"); mformat = lua_touserdata(L,-1); lua_pop(L,1); fdata = mformat->get_params(mformat); luaL_getmetafield(L,-2,"__luaA_Type"); luaA_Type format_type = lua_tointeger(L,-1); lua_pop(L,1); luaA_to_typeid(L,format_type,fdata,-2); mformat->set_params(mformat,fdata,mstorage->params_size(mstorage)); mformat->free_params(mformat,fdata); export_data->format_index = dt_imageio_get_index_of_format(mformat); // load the new list of images to process if(lua_isnoneornil(L,-1)) {lua_pop(L,3); return; }// everything already has been removed luaA_to(L,dt_lua_image_t,&export_descriptor->index,-1); lua_pop(L,1); }
static void mar_encode_value(lua_State *L, mar_Buffer *buf, int val, size_t *idx) { size_t l; int val_type = lua_type(L, val); lua_pushvalue(L, val); buf_write(L, (void*)&val_type, MAR_CHR, buf); switch (val_type) { case LUA_TBOOLEAN: { int int_val = lua_toboolean(L, -1); buf_write(L, (void*)&int_val, MAR_CHR, buf); break; } case LUA_TSTRING: { const char *str_val = lua_tolstring(L, -1, &l); buf_write(L, (void*)&l, MAR_I32, buf); buf_write(L, str_val, l, buf); break; } case LUA_TNUMBER: { lua_Number num_val = lua_tonumber(L, -1); buf_write(L, (void*)&num_val, MAR_I64, buf); break; } case LUA_TTABLE: { int tag, ref; lua_pushvalue(L, -1); lua_rawget(L, SEEN_IDX); if (!lua_isnil(L, -1)) { ref = lua_tointeger(L, -1); tag = MAR_TREF; buf_write(L, (void*)&tag, MAR_CHR, buf); buf_write(L, (void*)&ref, MAR_I32, buf); lua_pop(L, 1); } else { mar_Buffer rec_buf; lua_pop(L, 1); /* pop nil */ if (luaL_getmetafield(L, -1, "__persist")) { tag = MAR_TUSR; lua_pushvalue(L, -2); /* self */ lua_call(L, 1, 1); if (!lua_isfunction(L, -1)) { luaL_error(L, "__persist must return a function"); } lua_remove(L, -2); /* __persist */ lua_newtable(L); lua_pushvalue(L, -2); /* callback */ lua_rawseti(L, -2, 1); buf_init(L, &rec_buf); mar_encode_table(L, &rec_buf, idx); buf_write(L, (void*)&tag, MAR_CHR, buf); buf_write(L, (void*)&rec_buf.head, MAR_I32, buf); buf_write(L, rec_buf.data, rec_buf.head, buf); buf_done(L, &rec_buf); lua_pop(L, 1); } else { tag = MAR_TVAL; lua_pushvalue(L, -1); lua_pushinteger(L, (*idx)++); lua_rawset(L, SEEN_IDX); lua_pushvalue(L, -1); buf_init(L, &rec_buf); mar_encode_table(L, &rec_buf, idx); lua_pop(L, 1); buf_write(L, (void*)&tag, MAR_CHR, buf); buf_write(L, (void*)&rec_buf.head, MAR_I32, buf); buf_write(L, rec_buf.data,rec_buf.head, buf); buf_done(L, &rec_buf); } } break; } case LUA_TFUNCTION: { int tag, ref; lua_pushvalue(L, -1); lua_rawget(L, SEEN_IDX); if (!lua_isnil(L, -1)) { ref = lua_tointeger(L, -1); tag = MAR_TREF; buf_write(L, (void*)&tag, MAR_CHR, buf); buf_write(L, (void*)&ref, MAR_I32, buf); lua_pop(L, 1); } else { mar_Buffer rec_buf; int i; lua_Debug ar; lua_pop(L, 1); /* pop nil */ lua_pushvalue(L, -1); lua_getinfo(L, ">nuS", &ar); if (ar.what[0] != 'L') { luaL_error(L, "attempt to persist a C function '%s'", ar.name); } tag = MAR_TVAL; lua_pushvalue(L, -1); lua_pushinteger(L, (*idx)++); lua_rawset(L, SEEN_IDX); lua_pushvalue(L, -1); buf_init(L, &rec_buf); lua_dump(L, (lua_Writer)buf_write, &rec_buf); buf_write(L, (void*)&tag, MAR_CHR, buf); buf_write(L, (void*)&rec_buf.head, MAR_I32, buf); buf_write(L, rec_buf.data, rec_buf.head, buf); buf_done(L, &rec_buf); lua_pop(L, 1); lua_newtable(L); for (i=1; i <= ar.nups; i++) { lua_getupvalue(L, -2, i); lua_rawseti(L, -2, i); } buf_init(L, &rec_buf); mar_encode_table(L, &rec_buf, idx); buf_write(L, (void*)&rec_buf.head, MAR_I32, buf); buf_write(L, rec_buf.data, rec_buf.head, buf); buf_done(L, &rec_buf); lua_pop(L, 1); } break; } case LUA_TUSERDATA: { int tag, ref; lua_pushvalue(L, -1); lua_rawget(L, SEEN_IDX); if (!lua_isnil(L, -1)) { ref = lua_tointeger(L, -1); tag = MAR_TREF; buf_write(L, (void*)&tag, MAR_CHR, buf); buf_write(L, (void*)&ref, MAR_I32, buf); lua_pop(L, 1); } else { mar_Buffer rec_buf; lua_pop(L, 1); /* pop nil */ if (luaL_getmetafield(L, -1, "__persist")) { tag = MAR_TUSR; lua_pushvalue(L, -2); lua_pushinteger(L, (*idx)++); lua_rawset(L, SEEN_IDX); lua_pushvalue(L, -2); lua_call(L, 1, 1); if (!lua_isfunction(L, -1)) { luaL_error(L, "__persist must return a function"); } lua_newtable(L); lua_pushvalue(L, -2); lua_rawseti(L, -2, 1); lua_remove(L, -2); buf_init(L, &rec_buf); mar_encode_table(L, &rec_buf, idx); buf_write(L, (void*)&tag, MAR_CHR, buf); buf_write(L, (void*)&rec_buf.head, MAR_I32, buf); buf_write(L, rec_buf.data, rec_buf.head, buf); buf_done(L, &rec_buf); } else { luaL_error(L, "attempt to encode userdata (no __persist hook)"); } lua_pop(L, 1); } break; } case LUA_TNIL: break; default: luaL_error(L, "invalid value type (%s)", lua_typename(L, val_type)); } lua_pop(L, 1); }
/* * Arguments: options (table: {1..n: library names, "cpu": number}), * filename (string) | function_dump (string), * [arguments (string | number | boolean | ludata | share_object) ...] * Returns: [thread_udata] */ static int thread_runvm (lua_State *L) { const char *path = luaL_checkstring(L, 2); struct sys_thread *vmtd = sys_thread_get(); struct sys_thread *td, *faketd; lua_State *NL; unsigned int loadlibs = ~0U; /* load all standard libraries */ int is_affin = 0, cpu = 0; if (!vmtd) luaL_argerror(L, 0, "Threading not initialized"); /* options */ if (lua_istable(L, 1)) { unsigned int libs = 0; int i; for (i = 1; ; ++i) { const char *s; lua_rawgeti(L, 1, i); s = lua_tostring(L, -1); if (!s || !*s) { if (s) loadlibs = 0; /* don't load any libraries */ lua_pop(L, 1); break; } libs |= 1 << luaL_checkoption(L, -1, NULL, stdlib_names); lua_pop(L, 1); } if (libs) loadlibs = libs; /* CPU affinity */ lua_getfield(L, 1, "cpu"); if (lua_type(L, -1) == LUA_TNUMBER) { cpu = (int) lua_tointeger(L, -1); is_affin = 1; } lua_pop(L, 1); } td = thread_newvm(NULL, vmtd, loadlibs); if (!td) goto err; faketd = sys_thread_new(L, vmtd, td, 1); if (!faketd) goto err; lua_replace(L, 1); /* fake thread_udata */ if (is_affin) td->vmtd->cpu = cpu; NL = td->L; /* function */ if (path[0] == LUA_SIGNATURE[0] ? luaL_loadbuffer(NL, path, lua_rawlen(L, ARG_LAST), "thread") : luaL_loadfile(NL, path)) { lua_pushstring(L, lua_tostring(NL, -1)); /* error message */ lua_close(NL); lua_error(L); } /* arguments */ { int i, top = lua_gettop(L); luaL_checkstack(NL, top + LUA_MINSTACK, "too many arguments"); for (i = ARG_LAST + 1; i <= top; ++i) { switch (lua_type(L, i)) { case LUA_TSTRING: { size_t len; const char *s = lua_tolstring(L, i, &len); lua_pushlstring(NL, s, len); } break; case LUA_TNUMBER: lua_pushnumber(NL, lua_tonumber(L, i)); break; case LUA_TBOOLEAN: lua_pushboolean(NL, lua_toboolean(L, i)); break; case LUA_TLIGHTUSERDATA: lua_pushlightuserdata(NL, lua_touserdata(L, i)); break; case LUA_TUSERDATA: if (!luaL_getmetafield(L, i, THREAD_XDUP_TAG)) luaL_argerror(L, i, "shareable object expected"); lua_pushvalue(L, i); lua_pushlightuserdata(L, NL); lua_call(L, 2, 0); break; case LUA_TNIL: lua_pushnil(NL); break; default: luaL_argerror(L, i, "primitive type expected"); } } } if (!sys_thread_create(td, is_affin)) { faketd->tid = td->tid; lua_settop(L, 1); return 1; } lua_close(NL); err: return sys_seterror(L, 0); }
static int autotype_next(lua_State *L) { /* CONVENTION each block has the following stack on entry and exit 1 : the object 2 : the last entry ("next" convention) each block should return according to "next" convention on success each block should leave the key untouched if it doesn't know about it each block should replace the key with "nil" if the key was the last entry it can handle */ // printf("aaaaa %s %d\n",__FUNCTION__,__LINE__); if(luaL_getmetafield(L, 1, "__len")) { lua_pushvalue(L, -3); lua_call(L, 1, 1); int length = lua_tonumber(L, -1); lua_pop(L, 1); int key = 0; if(lua_isnil(L, -1) && length > 0) { key = 1; } else if(lua_isnumber(L, -1) && lua_tonumber(L, -1) < length) { key = lua_tonumber(L, -1) + 1; } else if(lua_isnumber(L, -1) && lua_tonumber(L, -1) == length) { // numbers are done, move-on to something else lua_pop(L, 1); lua_pushnil(L); } if(key) { lua_pop(L, 1); lua_pushnumber(L, key); lua_pushnumber(L, key); lua_gettable(L, -3); return 2; } } // stack at this point : {object,key} int key_in_get = false; luaL_getmetafield(L, 1, "__get"); if(lua_isnil(L, -2)) { key_in_get = true; } else { lua_pushvalue(L, -2); lua_gettable(L, -2); if(lua_isnil(L, -1)) { key_in_get = false; lua_pop(L, 2); } else { key_in_get = true; lua_pop(L, 1); } } if(key_in_get) { lua_pushvalue(L, -2); int nil_found = false; while(!nil_found) { if(lua_next(L, -2)) { // we have a next lua_pop(L, 1); lua_pushvalue(L, -4); lua_pushvalue(L, -2); // hacky way to avoid a subfunction just to do a pcall around getting a value in a table int result = dt_lua_dostring(L, "args ={...}; return args[1][args[2]]", 2, 1); if(result == LUA_OK) { return 2; } else { lua_pop(L, 1); // and loop to find the next possible value } } else { // key was the last for __get lua_pop(L, 2); lua_pushnil(L); nil_found = true; } } } // stack at this point : {object,key} if(lua_isnil(L, -1)) { return 1; } else { return luaL_error(L, "invalid key to 'next' : %s", lua_tostring(L, 2)); } }
static void lua_val_to_bson(lua_State *L, const char *key, int vpos, bson *bs, int tref) { int vtype = lua_type(L, vpos); char nbuf[TCNUMBUFSIZ]; if (key == NULL && vtype != LUA_TTABLE) { luaL_error(L, "lua_val_to_bson: Table must be on top of lua stack"); return; } switch (vtype) { case LUA_TTABLE: { if (vpos < 0) { vpos = lua_gettop(L) + vpos + 1; } lua_checkstack(L, 3); int bsontype_found = luaL_getmetafield(L, vpos, "__bsontype"); if (!bsontype_found) { lua_rawgeti(L, LUA_REGISTRYINDEX, tref); //+ reg table lua_pushvalue(L, vpos); //+ val lua_rawget(L, -2); //-val +reg table val if (lua_toboolean(L, -1)) { //already traversed lua_pop(L, 2); break; } lua_pop(L, 1); //-reg table val lua_pushvalue(L, vpos); lua_pushboolean(L, 1); lua_rawset(L, -3); lua_pop(L, 1); //-reg table int len = 0; bool query = false; bool array = true; if (luaL_getmetafield(L, vpos, "__query")) { lua_pop(L, 1); query = true; array = false; } if (array) { for (lua_pushnil(L); lua_next(L, vpos); lua_pop(L, 1)) { ++len; if ((lua_type(L, -2) != LUA_TNUMBER) || (lua_tointeger(L, -2) != len)) { lua_pop(L, 2); array = false; break; } } } if (array) { if (key) bson_append_start_array(bs, key); int i; for (i = 1; i <= len; ++i, lua_pop(L, 1)) { lua_rawgeti(L, vpos, i); bson_numstrn(nbuf, TCNUMBUFSIZ, (int64_t) i); lua_val_to_bson(L, nbuf, -1, bs, tref); } if (key) bson_append_finish_array(bs); } else if (query) { //special query builder case //oarr format: //{ {fname1, v1, v2...}, {fname2, v21, v22,..}, ... } //where: vN: {op, val} OR {val} with '__bval' metafield //Eg: {fname : {$inc : {...}, $dec : {...}}} -> {fname, {$inc, {}}, {$dec, {}}} lua_getfield(L, vpos, "_oarr"); //+oarr if (!lua_istable(L, -1)) { //it is not array lua_pop(L, 1); break; } if (key) bson_append_start_object(bs, key); //iterate over _oarr int ipos = lua_gettop(L); size_t ilen = lua_objlen(L, ipos); lua_checkstack(L, 2); size_t i; for (i = 1; i <= ilen; ++i, lua_pop(L, 1)) { lua_rawgeti(L, ipos, i); //gettop == 3 if (!lua_istable(L, -1)) continue; char *fname = NULL; int jpos = lua_gettop(L); size_t jlen = lua_objlen(L, jpos); lua_checkstack(L, 3); bool wrapped = false; size_t j; for (j = 1; j <= jlen; ++j, lua_pop(L, 1)) { lua_rawgeti(L, jpos, j); if (j == 1) { fname = strdup(lua_tostring(L, -1)); continue; } if (!fname || !lua_istable(L, -1)) { //invalid state lua_pop(L, 1); //pop val break; } int vblkpos = lua_gettop(L); if (j == 2 && luaL_getmetafield(L, -1, "__bval")) { //{val} single value +metafield lua_pop(L, 1); //-metafield lua_rawgeti(L, vblkpos, 1); //+val lua_val_to_bson(L, fname, lua_gettop(L), bs, tref); lua_pop(L, 2); //-val -lua_rawgeti break; //Terminate due single val } else { //{op, val} value if (!wrapped) { bson_append_start_object(bs, fname); wrapped = true; } lua_rawgeti(L, vblkpos, 1); //+op const char *op = lua_tostring(L, -1); if (op) { lua_rawgeti(L, vblkpos, 2); //+val lua_val_to_bson(L, op, lua_gettop(L), bs, tref); lua_pop(L, 1); //-val } lua_pop(L, 1); //-op } } if (wrapped) { bson_append_finish_object(bs); } if (fname) { free(fname); fname = NULL; } } if (key) bson_append_finish_object(bs); lua_pop(L, 1); //-oarr } else { if (key) bson_append_start_object(bs, key); TCLIST *keys = tclistnew(); //we need to sort keys due to unordered nature of lua tables for (lua_pushnil(L); lua_next(L, vpos);) { lua_pop(L, 1); //-val size_t ksize = 0; int ktype = lua_type(L, -1); if (ktype == LUA_TSTRING) { //accept only string keys const char* key = lua_tolstring(L, -1, &ksize); tclistpush(keys, key, ksize); } } tclistsort(keys); int i; for (i = 0; i < TCLISTNUM(keys); ++i) { int vkeysz = TCLISTVALSIZ(keys, i); const char *vkey = TCLISTVALPTR(keys, i); lua_pushlstring(L, vkey, vkeysz); lua_rawget(L, vpos); //+val if (key == NULL && lua_type(L, -1) == LUA_TSTRING && vkeysz == JDBIDKEYNAMEL && !strcmp(JDBIDKEYNAME, vkey)) { //root level OID as string //pack OID as type table lua_push_bsontype_table(L, BSON_OID); //+type table lua_pushvalue(L, -2); //dup oid(val) on stack lua_rawseti(L, -2, 1); //pop oid val if (ejdbisvalidoidstr(lua_tostring(L, -2))) { lua_val_to_bson(L, vkey, lua_gettop(L), bs, tref); } else { luaL_error(L, "OID _id='%s' is not valid", lua_tostring(L, -2)); } lua_pop(L, 1); //-type table } else { lua_val_to_bson(L, vkey, lua_gettop(L), bs, tref); } lua_pop(L, 1); //-val } tclistdel(keys); if (key) bson_append_finish_object(bs); } } else { //metafield __bsontype on top int bson_type = lua_tointeger(L, -1); if (!key && bson_type != BSON_OBJECT && bson_type != BSON_ARRAY) { lua_pop(L, 1); luaL_error(L, "Invalid object structure"); } lua_pop(L, 1); //-metafield __bsontype lua_rawgeti(L, -1, 1); //get first value switch (bson_type) { case BSON_OID: { const char* boid = lua_tostring(L, -1); if (boid && strlen(boid) == 24) { bson_oid_t oid; bson_oid_from_string(&oid, boid); bson_append_oid(bs, key, &oid); } break; } case BSON_DATE: bson_append_date(bs, key, (bson_date_t) lua_tonumber(L, -1)); break; case BSON_REGEX: { const char* regex = lua_tostring(L, -1); lua_rawgeti(L, -2, 2); // re opts const char* options = lua_tostring(L, -1); if (regex && options) { bson_append_regex(bs, key, regex, options); } lua_pop(L, 1); break; } case BSON_BINDATA: { size_t len; const char* cbuf = lua_tolstring(L, -1, &len); bson_append_binary(bs, key, BSON_BIN_BINARY, cbuf, len); break; } case BSON_NULL: bson_append_null(bs, key); break; case BSON_UNDEFINED: bson_append_undefined(bs, key); break; case BSON_OBJECT: if (key) bson_append_start_object(bs, key); lua_val_to_bson(L, NULL, vpos, bs, tref); if (key) bson_append_finish_object(bs); break; case BSON_ARRAY: if (key) bson_append_start_array(bs, key); lua_val_to_bson(L, NULL, vpos, bs, tref); if (key) bson_append_finish_array(bs); break; case BSON_DOUBLE: bson_append_double(bs, key, (double) lua_tonumber(L, -1)); break; case BSON_INT: bson_append_int(bs, key, (int32_t) lua_tonumber(L, -1)); break; case BSON_LONG: bson_append_long(bs, key, (int64_t) lua_tonumber(L, -1)); break; case BSON_BOOL: bson_append_bool(bs, key, lua_toboolean(L, -1)); break; default: break; } lua_pop(L, 1); //-1 first value } break; } case LUA_TNIL: bson_append_null(bs, key); break; case LUA_TNUMBER: { lua_Number numval = lua_tonumber(L, vpos); if (numval == floor(numval)) { int64_t iv = (int64_t) numval; if (-(1LL << 31) <= iv && iv <= (1LL << 31)) { bson_append_int(bs, key, iv); } else { bson_append_long(bs, key, iv); } } else { bson_append_double(bs, key, numval); } break; } case LUA_TBOOLEAN: bson_append_bool(bs, key, lua_toboolean(L, vpos)); break; case LUA_TSTRING: bson_append_string(bs, key, lua_tostring(L, vpos)); break; } }
static int ch_index (lua_State* l) { HWND h = gethandle(l,1); if (lua_isnumber(l,2)) { int pos = luaL_checkint(l,2); if (pos==0) pos=-1; if (pos<0) pos += SendMessage(h, LB_GETCOUNT, 0, 0); else pos--; int len = SendMessage(h, LB_GETTEXTLEN, pos, 0); wchar_t* wstr = malloc(sizeof(wchar_t) * (len+1)); SendMessage(h, LB_GETTEXT, pos, wstr); wstr[len]=0; const char* str = strncvt(wstr, len, CP_UTF16, CP_UTF8, &len); lua_settop(l,0); lua_pushlstring(l, str, len); free(str); free(wstr); return 1; } const char* nm = luaL_checkstring(l,2); if (streq(nm, "selectedIndex")) { int cur = SendMessage(h, LB_GETCURSEL, 0, 0); if (cur==LB_ERR || cur<0) lua_pushinteger(l,0); else lua_pushinteger(l,cur+1); return 1; } else if (streq(nm, "selectedItem")) { int cur = SendMessage(h, LB_GETCURSEL, 0, 0); if (cur==LB_ERR || cur<0) return 0; int len = SendMessage(h, LB_GETTEXTLEN, cur, 0); wchar_t* wstr = malloc(sizeof(wchar_t) * (len+1)); SendMessage(h, LB_GETTEXT, cur, wstr); wstr[len]=0; const char* str = strncvt(wstr, len, CP_UTF16, CP_UTF8, &len); lua_settop(l,0); lua_pushlstring(l, str, len); free(str); free(wstr); return 1; } else if (streq(nm, "closed")) { lua_pushboolean(l, IsWindow(h)!=0); return 1; } else if (streq(nm, "onClose")) { void* p = GetProp(h, L"onClose"); if (p) lua_pushluafunction(l,p); else lua_pushnil(l); return 1; } else if (streq(nm, "onAction")) { void* p = GetProp(h, L"onAction"); if (p) lua_pushluafunction(l,p); else lua_pushnil(l); return 1; } else if (streq(nm, "onSelect")) { void* p = GetProp(h, L"onSelect"); if (p) lua_pushluafunction(l,p); else lua_pushnil(l); return 1; } else if (streq(nm, "onContextMenu")) { void* p = GetProp(h, L"onContextMenu"); if (p) lua_pushluafunction(l,p); else lua_pushnil(l); return 1; } else if (streq(nm, "hwnd")) { lua_pushlightuserdata(l, h); return 1; } //SUITE return luaL_getmetafield(l, 1, nm); }
/// Wrapper around luaL_getmetafield. /// /// \param index The second parameter to luaL_getmetafield. /// \param name The third parameter to luaL_getmetafield. /// /// \return The return value of luaL_getmetafield. /// /// \warning Terminates execution if there is not enough memory to manipulate /// the Lua stack. bool lutok::state::get_metafield(const int index, const std::string& name) { return luaL_getmetafield(_pimpl->lua_state, index, name.c_str()) != 0; }
static void pack_value(lua_State *L, mar_Buffer *buf, int val, int *idx) { size_t l; int val_type = lua_type(L, val); buf_write(L, (void*)&val_type, MAR_CHR, buf); switch (val_type) { case LUA_TBOOLEAN: { int int_val = lua_toboolean(L, val); buf_write(L, (void*)&int_val, MAR_CHR, buf); break; } case LUA_TSTRING: { const char *str_val = lua_tolstring(L, val, &l); buf_write(L, (void*)&l, MAR_I32, buf); buf_write(L, str_val, l, buf); break; } case LUA_TNUMBER: { lua_Number num_val = lua_tonumber(L, val); buf_write(L, (void*)&num_val, MAR_I64, buf); break; } case LUA_TTABLE: { int tag, ref; lua_pushvalue(L, val); lua_rawget(L, 2); if (!lua_isnil(L, -1)) { ref = lua_tointeger(L, -1); tag = MAR_TREF; buf_write(L, (void*)&tag, MAR_CHR, buf); buf_write(L, (void*)&ref, MAR_I32, buf); lua_pop(L, 1); } else { mar_Buffer rec_buf; lua_pop(L, 1); if (luaL_getmetafield(L, val, "__persist")) { tag = MAR_TUSR; lua_pushvalue(L, val-1); lua_pushinteger(L, (*idx)++); lua_rawset(L, 2); lua_pushvalue(L, val-1); lua_call(L, 1, 1); if (!lua_isfunction(L, -1)) { luaL_error(L, "__persist must return a function"); } lua_newtable(L); lua_pushvalue(L, -2); lua_rawseti(L, -2, 1); lua_remove(L, -2); buf_init(L, &rec_buf); mar_pack(L, &rec_buf, idx); buf_write(L, (void*)&tag, MAR_CHR, buf); buf_write(L, (void*)&rec_buf.head, MAR_I32, buf); buf_write(L, rec_buf.data, rec_buf.head, buf); buf_done(L, &rec_buf); lua_pop(L, 1); } else { tag = MAR_TVAL; lua_pushvalue(L, val); lua_pushinteger(L, (*idx)++); lua_rawset(L, 2); lua_pushvalue(L, val); buf_init(L, &rec_buf); mar_pack(L, &rec_buf, idx); buf_write(L, (void*)&tag, MAR_CHR, buf); buf_write(L, (void*)&rec_buf.head, MAR_I32, buf); buf_write(L, rec_buf.data,rec_buf.head, buf); buf_done(L, &rec_buf); lua_pop(L, 1); } } break; } case LUA_TFUNCTION: { int tag, ref; lua_pushvalue(L, val); lua_rawget(L, 2); if (!lua_isnil(L, -1)) { ref = lua_tointeger(L, -1); tag = MAR_TREF; buf_write(L, (void*)&tag, MAR_CHR, buf); buf_write(L, (void*)&ref, MAR_I32, buf); lua_pop(L, 1); } else { mar_Buffer rec_buf; int i; lua_Debug ar; lua_pop(L, 1); tag = MAR_TVAL; lua_pushvalue(L, val); lua_pushinteger(L, (*idx)++); lua_rawset(L, 2); lua_pushvalue(L, val); buf_init(L, &rec_buf); lua_dump(L, (lua_Writer)buf_write, &rec_buf); buf_write(L, (void*)&tag, MAR_CHR, buf); buf_write(L, (void*)&rec_buf.head, MAR_I32, buf); buf_write(L, rec_buf.data, rec_buf.head, buf); buf_done(L, &rec_buf); lua_pop(L, 1); lua_pushvalue(L, val); lua_getinfo(L, ">uS", &ar); if (ar.what[0] != 'L') { luaL_error(L, "attempt to persist a C function"); } lua_newtable(L); for (i=1; i <= ar.nups; i++) { lua_getupvalue(L, -2, i); lua_rawseti(L, -2, i); } buf_init(L, &rec_buf); mar_pack(L, &rec_buf, idx); buf_write(L, (void*)&rec_buf.head, MAR_I32, buf); buf_write(L, rec_buf.data, rec_buf.head, buf); buf_done(L, &rec_buf); lua_pop(L, 1); } break; } case LUA_TUSERDATA: { int tag, ref; lua_pushvalue(L, val); lua_rawget(L, 2); if (!lua_isnil(L, -1)) { ref = lua_tointeger(L, -1); tag = MAR_TREF; buf_write(L, (void*)&tag, MAR_CHR, buf); buf_write(L, (void*)&ref, MAR_I32, buf); lua_pop(L, 1); } else { mar_Buffer rec_buf; lua_pop(L, 1); if (luaL_getmetafield(L, val, "__persist")) { tag = MAR_TUSR; lua_pushvalue(L, val-1); lua_pushinteger(L, (*idx)++); lua_rawset(L, 2); lua_pushvalue(L, val-1); lua_call(L, 1, 1); if (!lua_isfunction(L, -1)) { luaL_error(L, "__persist must return a function"); } lua_newtable(L); lua_pushvalue(L, -2); lua_rawseti(L, -2, 1); lua_remove(L, -2); buf_init(L, &rec_buf); mar_pack(L, &rec_buf, idx); buf_write(L, (void*)&tag, MAR_CHR, buf); buf_write(L, (void*)&rec_buf.head, MAR_I32, buf); buf_write(L, rec_buf.data, rec_buf.head, buf); buf_done(L, &rec_buf); lua_pop(L, 1); } else { tag = MAR_TVAL; buf_write(L, (void*)&tag, MAR_CHR, buf); } } break; } case LUA_TTHREAD: break; /* just give them a nil during unpack */ default: luaL_error(L, "invalid value type"); } }
void LuaShipDef::Register() { lua_State *l = Lua::manager->GetLuaState(); LUA_DEBUG_START(l); lua_newtable(l); for (auto iter : ShipType::types) { const ShipType &st = iter.second; lua_newtable(l); pi_lua_settable(l, "id", iter.first.c_str()); pi_lua_settable(l, "name", st.name.c_str()); pi_lua_settable(l, "shipClass", st.shipClass.c_str()); pi_lua_settable(l, "manufacturer", st.manufacturer.c_str()); pi_lua_settable(l, "modelName", st.modelName.c_str()); pi_lua_settable(l, "cockpitName", st.cockpitName.c_str()); pi_lua_settable(l, "tag", EnumStrings::GetString("ShipTypeTag", st.tag)); pi_lua_settable(l, "angularThrust", st.angThrust); pi_lua_settable(l, "capacity", st.capacity); pi_lua_settable(l, "hullMass", st.hullMass); pi_lua_settable(l, "fuelTankMass", st.fuelTankMass); pi_lua_settable(l, "basePrice", st.baseprice); pi_lua_settable(l, "minCrew", st.minCrew); pi_lua_settable(l, "maxCrew", st.maxCrew); pi_lua_settable(l, "hyperdriveClass", st.hyperdriveClass); pi_lua_settable(l, "effectiveExhaustVelocity", st.effectiveExhaustVelocity); pi_lua_settable(l, "thrusterFuelUse", st.GetFuelUseRate()); lua_newtable(l); for (int t = Thruster::THRUSTER_REVERSE; t < Thruster::THRUSTER_MAX; t++) pi_lua_settable(l, EnumStrings::GetString("ShipTypeThruster", t), st.linThrust[t]); pi_lua_readonly_table_proxy(l, -1); lua_setfield(l, -3, "linearThrust"); lua_pop(l, 1); lua_newtable(l); for (auto it = st.slots.cbegin(); it != st.slots.cend(); ++it) { pi_lua_settable(l, it->first.c_str(), it->second); } pi_lua_readonly_table_proxy(l, -1); luaL_getmetafield(l, -1, "__index"); if (!lua_getmetatable(l, -1)) { lua_newtable(l); } pi_lua_import(l, "EquipSet"); luaL_getsubtable(l, -1, "default"); lua_setfield(l, -3, "__index"); lua_pop(l, 1); lua_setmetatable(l, -2); lua_pop(l, 1); lua_setfield(l, -3, "equipSlotCapacity"); lua_pop(l, 1); lua_newtable(l); for (auto it = st.roles.cbegin(); it != st.roles.cend(); ++it) { pi_lua_settable(l, it->first.c_str(), it->second); } pi_lua_readonly_table_proxy(l, -1); lua_setfield(l, -3, "roles"); lua_pop(l, 1); pi_lua_readonly_table_proxy(l, -1); lua_setfield(l, -3, iter.first.c_str()); lua_pop(l, 1); } lua_getfield(l, LUA_REGISTRYINDEX, "CoreImports"); pi_lua_readonly_table_proxy(l, -2); lua_setfield(l, -2, "ShipDef"); lua_pop(l, 2); LUA_DEBUG_END(l, 0); }