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