Created
January 4, 2025 15:08
-
-
Save st235/b8bbf94e730362aefb288fa715dea1f2 to your computer and use it in GitHub Desktop.
Revisions
-
st235 created this gist
Jan 4, 2025 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,119 @@ // Exercise 30.1: // Modify the dir_iter function in the directory example // so that it closes the DIR structure when it reaches // the end of the traversal. // With this change, // the program does not need to wait for a garbage collection // to release a resource that it knows it will not need anymore. // (When you close the directory, // you should set the address stored in the userdatum to NULL, // to signal to the finalizer that the directory is already closed. // Also, function dir_iter will have to check whether the directory // is not closed before using it.) #define LUA_COMPAT_APIINTCASTS #include <cmath> #include <cstdint> #include <dirent.h> #include <exception> #include <iomanip> #include <iostream> #include <limits> #include <string> #include <vector> #include <stack> #include <unordered_set> #include "lua.hpp" namespace { bool AbortWithMessage(const char* message) { std::cout << message << std::endl; std::abort(); } bool LoadFile(lua_State* state, const std::string& filename) { return !(luaL_loadfile(state, filename.c_str()) || lua_pcall(state, 0, 0, 0)); } int dir_iter(lua_State *L) { DIR** dir_ptr = (DIR**) lua_touserdata(L, lua_upvalueindex(1)); struct dirent* entry; if (*dir_ptr && (entry = readdir(*dir_ptr)) != NULL) { lua_pushstring(L, entry->d_name); return 1; } // Directory is empty. if (*dir_ptr) { closedir(*dir_ptr); *dir_ptr = nullptr; } return 0; } int l_dir(lua_State *L) { const char *path = luaL_checkstring(L, 1); DIR** d = (DIR**) lua_newuserdata(L, sizeof(DIR*)); luaL_getmetatable(L, "LuaBook.dir"); lua_setmetatable(L, -2); *d = opendir(path); if (*d == NULL) { luaL_error(L, "cannot open %s: %s", path, strerror(errno)); } lua_pushcclosure(L, dir_iter, 1); return 1; } int dir_gc(lua_State *L) { DIR* d = *(DIR**) lua_touserdata(L, 1); if (d) { closedir(d); } return 0; } const struct luaL_Reg dirlib[] = { {"open", l_dir}, {NULL, NULL} }; int luaopen_dir(lua_State *L) { luaL_newmetatable(L, "LuaBook.dir"); lua_pushcfunction(L, dir_gc); lua_setfield(L, -2, "__gc"); luaL_newlib(L, dirlib); lua_setglobal(L, "dir"); return 0; } } // namespace int main(int argc, char* argv[]) { if (argc < 2) { std::cout << "Please, specify lua script file to run." << std::endl; return 0; } lua_State* L = luaL_newstate(); luaL_openlibs(L); luaopen_dir(L); if (!LoadFile(L, std::string(argv[1]))) { AbortWithMessage(lua_tostring(L, -1)); return -1; } return 0; } This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,3 @@ for fname in dir.open(".") do print(fname) end This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,8 @@ . .. CMakeFiles Makefile cmake_install.cmake deps CMakeCache.txt lua-test