Create a lua table representing tree of current working dir.
This file contains 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 characters
| #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