[osx.c] Rework directory iteration.

- add opendir() to open a directory and return it.
- add directory listfiles() method, returning all remaining entries as
  an array
- rework directory iteration
This commit is contained in:
Lorenzo Cogotti 2022-12-12 00:42:36 +01:00
parent 86904f62c0
commit 31bc1077c1
1 changed files with 72 additions and 38 deletions

110
osx.c
View File

@ -193,9 +193,7 @@ static bool os_dir_filter(lua_State *L, const char *name)
return result; return result;
} }
static int os_dir_iter(lua_State *L); static int os_dir_open(lua_State *L)
static int os_dir(lua_State *L)
{ {
const char *path = luaL_checkstring(L, 1); const char *path = luaL_checkstring(L, 1);
@ -204,9 +202,42 @@ static int os_dir(lua_State *L)
dir->hn = os_opendir(path); dir->hn = os_opendir(path);
dir->closeflag = false; dir->closeflag = false;
if (!dir->hn) if (!dir->hn)
luaL_error(L, "%s: %s", path, strerror(errno)); return os_pushfail(L, path);
luaL_setmetatable(L, DF_LUA_DIRHANDLE); luaL_setmetatable(L, DF_LUA_DIRHANDLE);
return 1;
}
static int os_dir_close(lua_State *L)
{
df_os_dir *dir = todir(L);
os_closedir(dir->hn);
dir->closeflag = true;
return 0;
}
static int os_dir_gc(lua_State *L)
{
df_os_dir *dir = luaL_checkudata(L, 1, DF_LUA_DIRHANDLE);
if (!dir->closeflag)
os_dir_close(L);
return 0;
}
static int os_dir_iter(lua_State *L);
static int os_dir(lua_State *L)
{
lua_pushcfunction(L, os_dir_open);
lua_pushvalue(L, 1);
lua_call(L, 1, 2);
if (lua_isnil(L, -2))
lua_error(L);
lua_pop(L, 1);
lua_pushcclosure(L, os_dir_iter, 2); lua_pushcclosure(L, os_dir_iter, 2);
return 1; return 1;
@ -239,7 +270,7 @@ nextfilename:
return 1; return 1;
} }
static int os_dir_read(lua_State *L) static int os_dir_readdir(lua_State *L)
{ {
df_os_dir *dir = todir(L); df_os_dir *dir = todir(L);
@ -253,28 +284,9 @@ static int os_dir_read(lua_State *L)
return 1; return 1;
} }
static int os_dir_close(lua_State *L) static int os_dir_dolistfiles(lua_State *L, bool closeflag, const char *path)
{ {
df_os_dir *dir = todir(L); df_os_dir *dir = todir(L);
os_closedir(dir->hn);
dir->closeflag = true;
return 0;
}
static int os_dir_gc(lua_State *L)
{
df_os_dir *dir = luaL_checkudata(L, 1, DF_LUA_DIRHANDLE);
if (!dir->closeflag)
os_dir_close(L);
return 0;
}
static int os_listfiles(lua_State *L)
{
const char *path = luaL_checkstring(L, 1);
bool dofilter = false; bool dofilter = false;
if (!lua_isnoneornil(L, 2)) { if (!lua_isnoneornil(L, 2)) {
@ -282,18 +294,13 @@ static int os_listfiles(lua_State *L)
dofilter = true; dofilter = true;
} }
df_os_dirhn hn = os_opendir(path); char *filename;
if (!hn) int i = 1;
return os_pushfail(L, path);
lua_newtable(L); lua_newtable(L);
const char *filename;
int i = 1;
int err;
errno = 0; errno = 0;
while ((filename = os_readdir(hn)) != NULL) { while ((filename = os_readdir(dir->hn)) != NULL) {
if (strcmp(filename, ".") == 0 || strcmp(filename, "..") == 0) if (strcmp(filename, ".") == 0 || strcmp(filename, "..") == 0)
continue; continue;
if (dofilter && !os_dir_filter(L, filename)) if (dofilter && !os_dir_filter(L, filename))
@ -303,15 +310,40 @@ static int os_listfiles(lua_State *L)
lua_pushstring(L, filename); lua_pushstring(L, filename);
lua_settable(L, -3); lua_settable(L, -3);
} }
err = errno;
os_closedir(hn); int err = errno;
if (err != 0) if (closeflag)
os_dir_close(L);
if (err != 0) {
errno = err;
return os_pushfail(L, path); return os_pushfail(L, path);
}
return 1; return 1;
} }
static int os_dir_listfiles(lua_State *L)
{
return os_dir_dolistfiles(L, false, NULL);
}
static int os_listfiles(lua_State *L)
{
const char *path = luaL_checkstring(L, 1);
if (lua_isnone(L, 2))
lua_pushnil(L);
lua_pushcfunction(L, os_dir_open);
lua_pushvalue(L, 1);
lua_call(L, 1, 2);
if (lua_isnil(L, -2))
lua_error(L);
lua_copy(L, -2, 1);
lua_pop(L, 2);
return os_dir_dolistfiles(L, true, path);
}
static int os_stat(lua_State *L) static int os_stat(lua_State *L)
{ {
const char *path = NULL; const char *path = NULL;
@ -517,7 +549,8 @@ static void createmeta(lua_State *L)
{ NULL, NULL } { NULL, NULL }
}; };
static const luaL_Reg meth[] = { static const luaL_Reg meth[] = {
{ "read", os_dir_read }, { "readdir", os_dir_readdir },
{ "listfiles", os_dir_listfiles },
{ "close", os_dir_close }, { "close", os_dir_close },
{ NULL, NULL } { NULL, NULL }
}; };
@ -534,6 +567,7 @@ DF_OSXMOD_API int luaopen_osx(lua_State *L)
{ {
static const luaL_Reg funcs[] = { static const luaL_Reg funcs[] = {
{ "listfiles", os_listfiles }, { "listfiles", os_listfiles },
{ "opendir", os_dir_open },
{ "dir", os_dir }, { "dir", os_dir },
{ "stat", os_stat }, { "stat", os_stat },
{ "mkdir", os_mkdir }, { "mkdir", os_mkdir },