Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Create a lua table representing tree of current working dir.
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
#include <dirent.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#define PATHBUFLEN 1024
#define RECURLIMIT 16
#define TREEFILESLIMIT 1024
#define sdump(L, str) printf("\e[32m"); stackDump(L); printf("\e[0m"); printf((str)); printf(".\n");
static void stackDump (lua_State *L) {
int i;
int top = lua_gettop(L);
for (i = 1; i <= top; i++) { /* repeat for each level */
int t = lua_type(L, i);
switch (t) {
case LUA_TSTRING: printf("'%s'", lua_tostring(L, i)); break;
case LUA_TBOOLEAN: printf(lua_toboolean(L, i) ? "true" : "false"); break;
case LUA_TNUMBER: printf("%g", lua_tonumber(L, i)); break;
default: printf("%s", lua_typename(L, t)); break;
}
printf("\t"); /* put a separator */
}
}
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
static inline void initTree(lua_State *L, const char *basepath) {
sdump(L, "init")
lua_newtable(L);
lua_pushstring(L, "base");
lua_pushstring(L, basepath);
lua_rawset(L, -3);
lua_pushstring(L, "files");
lua_newtable(L);
lua_rawset(L, -3);
lua_pushstring(L, "dirs");
lua_newtable(L);
lua_rawset(L, -3);
sdump(L, "endinit")
}
static inline void fillTree(lua_State *L, char *pathbuf) {
DIR *d = opendir(pathbuf);
if (d) {
size_t files = 0, dirs = 0, baselen = strlen(pathbuf);
struct dirent *entry;
size_t entries = 0; while(entry = readdir(d)) entries++;
if (entries < TREEFILESLIMIT) {
rewinddir(d);
lua_pushstring(L, "dirs"); lua_rawget(L, -2);
lua_pushstring(L, "files"); lua_rawget(L, -3);
while ((entry = readdir(d))) {
char *name = entry-> d_name;
char c1 = name[0], c2 = name[1];
if (!(c1 == '.' && (!c2 || (c2 == '.' && !name[2])))) {
pathbuf[baselen] = '/';
pathbuf[baselen + 1] = 0;
strcat(pathbuf, name);
struct stat s;
if (lstat(pathbuf, &s) != -1) {
if (S_ISDIR(s.st_mode)) {
initTree(L, name);
fillTree(L, pathbuf);
lua_rawseti(L, -2, ++dirs);
} else {
lua_pushstring(L, name);
lua_rawseti(L, -3, ++files);
}
}
pathbuf[baselen] = 0;
}
}
lua_pop(L, 2);
closedir(d);
}
}
};
static inline int l_tree(lua_State *L) {
luaL_checktype(L, 1, LUA_TSTRING); /* 1 subsequence to ssmatch against to. */
size_t lpath;
const char *path = luaL_checklstring(L, 1, &lpath);
char basepath[PATHBUFLEN];
if (path[lpath - 1] == '/') {
strncpy(basepath, path, lpath - 1);
} else {
strcpy(basepath, path);
}
lua_pop(L, 1); // done with the basepath.
initTree(L, basepath);
fillTree(L, basepath);
return 1;
}
static const struct luaL_Reg mwalker [] = {
{"tree", l_tree},
{NULL, NULL} /* sentinel */
};
int luaopen_mwalker(lua_State *L) {
luaL_register(L, "mwalker", mwalker);
return 1;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment