lovr/src/api/filesystem.c

302 lines
7.7 KiB
C
Raw Normal View History

2017-03-11 11:08:07 +00:00
#include "api/lovr.h"
2016-11-19 09:28:01 +00:00
#include "filesystem/filesystem.h"
2017-04-01 23:50:10 +00:00
#include "filesystem/blob.h"
2016-11-02 03:27:15 +00:00
#include <stdlib.h>
#include <string.h>
2017-03-11 09:37:00 +00:00
static void pushDirectoryItem(void* userdata, const char* path, const char* filename) {
lua_State* L = userdata;
int n = lua_objlen(L, -1);
lua_pushstring(L, filename);
lua_rawseti(L, -2, n + 1);
}
2016-11-02 03:27:15 +00:00
// Loader to help Lua's require understand PhysFS.
static int filesystemLoader(lua_State* L) {
const char* module = luaL_checkstring(L, -1);
char* dot;
while ((dot = strchr(module, '.')) != NULL) {
*dot = '/';
}
const char* requirePath[] = {
"?.lua",
"?/init.lua"
};
2016-11-14 22:16:16 +00:00
for (size_t i = 0; i < sizeof(requirePath) / sizeof(char*); i++) {
2016-11-02 03:27:15 +00:00
char filename[256];
char* sub = strchr(requirePath[i], '?');
memset(filename, 0, 256);
if (sub) {
int index = (int) (sub - requirePath[i]);
strncat(filename, requirePath[i], index);
strncat(filename, module, strlen(module));
strncat(filename, requirePath[i] + index + 1, strlen(requirePath[i]) - index);
if (lovrFilesystemIsFile(filename)) {
2017-03-11 09:37:00 +00:00
size_t size;
2016-11-05 22:55:01 +00:00
void* data = lovrFilesystemRead(filename, &size);
2016-11-02 03:27:15 +00:00
if (data) {
if (!luaL_loadbuffer(L, data, size, filename)) {
return 1;
}
free(data);
}
}
}
}
return 0;
}
2016-11-01 00:14:31 +00:00
int l_lovrFilesystemInit(lua_State* L) {
lua_newtable(L);
luaL_register(L, NULL, lovrFilesystem);
2017-04-01 23:50:10 +00:00
luax_registertype(L, "Blob", lovrBlob);
2016-11-02 03:27:15 +00:00
2017-03-11 09:37:00 +00:00
lua_getglobal(L, "arg");
lua_rawgeti(L, -1, -2);
lua_rawgeti(L, -2, 1);
const char* arg0 = lua_tostring(L, -2);
const char* arg1 = lua_tostring(L, -1);
lovrFilesystemInit(arg0, arg1);
lua_pop(L, 3);
2016-11-02 03:27:15 +00:00
// Add custom package loader
2016-11-29 07:37:50 +00:00
lua_getglobal(L, "table");
lua_getfield(L, -1, "insert");
2016-11-02 03:27:15 +00:00
lua_getglobal(L, "package");
lua_getfield(L, -1, "loaders");
2016-11-29 07:37:50 +00:00
lua_remove(L, -2);
2016-11-02 03:27:15 +00:00
if (lua_istable(L, -1)) {
2016-11-29 07:37:50 +00:00
lua_pushinteger(L, 2); // Insert our loader after package.preload
2016-11-02 03:27:15 +00:00
lua_pushcfunction(L, filesystemLoader);
2016-11-29 07:37:50 +00:00
lua_call(L, 3, 0);
2016-11-02 03:27:15 +00:00
}
2016-11-29 07:37:50 +00:00
lua_pop(L, 1);
2016-11-02 03:27:15 +00:00
2016-11-01 00:14:31 +00:00
return 1;
}
2016-11-07 22:31:11 +00:00
int l_lovrFilesystemAppend(lua_State* L) {
size_t size;
const char* path = luaL_checkstring(L, 1);
const char* content = luaL_checklstring(L, 2, &size);
2017-03-11 09:37:00 +00:00
lua_pushnumber(L, lovrFilesystemWrite(path, content, size, 1));
2016-11-07 22:31:11 +00:00
return 1;
}
2016-11-01 00:14:31 +00:00
int l_lovrFilesystemExists(lua_State* L) {
const char* path = luaL_checkstring(L, 1);
lua_pushboolean(L, lovrFilesystemExists(path));
return 1;
}
2017-03-11 09:37:00 +00:00
int l_lovrFilesystemGetAppdataDirectory(lua_State* L) {
char buffer[1024];
if (lovrFilesystemGetAppdataDirectory(buffer, sizeof(buffer))) {
2017-03-11 09:37:00 +00:00
lua_pushnil(L);
} else {
lua_pushstring(L, buffer);
}
return 1;
}
int l_lovrFilesystemGetDirectoryItems(lua_State* L) {
const char* path = luaL_checkstring(L, 1);
lua_newtable(L);
lovrFilesystemGetDirectoryItems(path, pushDirectoryItem, L);
return 1;
}
2016-11-01 00:14:31 +00:00
int l_lovrFilesystemGetExecutablePath(lua_State* L) {
2016-11-07 22:30:32 +00:00
char buffer[1024];
2016-11-01 00:14:31 +00:00
2016-11-07 22:30:32 +00:00
if (lovrFilesystemGetExecutablePath(buffer, sizeof(buffer))) {
lua_pushnil(L);
} else {
lua_pushstring(L, buffer);
}
return 1;
}
int l_lovrFilesystemGetIdentity(lua_State* L) {
2016-11-08 21:45:12 +00:00
lua_pushstring(L, lovrFilesystemGetIdentity());
2016-11-07 22:30:32 +00:00
return 1;
}
2017-03-11 09:37:00 +00:00
int l_lovrFilesystemGetLastModified(lua_State* L) {
const char* path = luaL_checkstring(L, 1);
int lastModified = lovrFilesystemGetLastModified(path);
if (lastModified < 0) {
lua_pushnil(L);
} else {
lua_pushinteger(L, lastModified);
}
return 1;
}
2016-11-07 22:30:32 +00:00
int l_lovrFilesystemGetRealDirectory(lua_State* L) {
const char* path = luaL_checkstring(L, 1);
2016-11-08 21:45:12 +00:00
lua_pushstring(L, lovrFilesystemGetRealDirectory(path));
2016-11-07 22:30:32 +00:00
return 1;
}
2017-03-11 09:37:00 +00:00
int l_lovrFilesystemGetSaveDirectory(lua_State* L) {
lua_pushstring(L, lovrFilesystemGetSaveDirectory());
return 1;
}
int l_lovrFilesystemGetSize(lua_State* L) {
const char* path = luaL_checkstring(L, 1);
lua_pushinteger(L, lovrFilesystemGetSize(path));
return 1;
}
2016-11-07 22:30:32 +00:00
int l_lovrFilesystemGetSource(lua_State* L) {
2016-11-08 21:45:12 +00:00
lua_pushstring(L, lovrFilesystemGetSource());
2016-11-01 00:14:31 +00:00
return 1;
}
2016-11-07 22:30:32 +00:00
int l_lovrFilesystemGetUserDirectory(lua_State* L) {
lua_pushstring(L, lovrFilesystemGetUserDirectory());
return 1;
}
2016-11-01 01:35:00 +00:00
int l_lovrFilesystemIsDirectory(lua_State* L) {
const char* path = luaL_checkstring(L, 1);
lua_pushboolean(L, lovrFilesystemIsDirectory(path));
return 1;
}
int l_lovrFilesystemIsFile(lua_State* L) {
const char* path = luaL_checkstring(L, 1);
lua_pushboolean(L, lovrFilesystemIsFile(path));
return 1;
}
2017-03-11 09:37:00 +00:00
int l_lovrFilesystemIsFused(lua_State* L) {
lua_pushboolean(L, lovrFilesystemIsFused());
return 1;
}
2017-03-02 04:08:13 +00:00
int l_lovrFilesystemLoad(lua_State* L) {
const char* path = luaL_checkstring(L, 1);
2017-03-11 09:37:00 +00:00
size_t size;
2017-03-02 04:08:13 +00:00
char* content = lovrFilesystemRead(path, &size);
int status = luaL_loadbuffer(L, content, size, path);
switch (status) {
case LUA_ERRMEM: return luaL_error(L, "Memory allocation error: %s", lua_tostring(L, -1));
case LUA_ERRSYNTAX: return luaL_error(L, "Syntax error: %s", lua_tostring(L, -1));
default: return 1;
}
}
2017-03-11 09:37:00 +00:00
int l_lovrFilesystemMount(lua_State* L) {
const char* path = luaL_checkstring(L, 1);
const char* mountpoint = luaL_optstring(L, 2, NULL);
int append = lua_isnoneornil(L, 3) ? 0 : lua_toboolean(L, 3);
lua_pushboolean(L, !lovrFilesystemMount(path, mountpoint, append));
return 1;
}
2017-04-01 23:50:10 +00:00
int l_lovrFilesystemNewBlob(lua_State* L) {
const char* path;
const char* data;
size_t size;
if (lua_gettop(L) == 1) {
path = luaL_checkstring(L, 1);
data = lovrFilesystemRead(path, &size);
} else {
data = luaL_checklstring(L, 1, &size);
path = luaL_checkstring(L, 2);
}
Blob* blob = lovrBlobCreate((void*) data, size, path);
luax_pushtype(L, Blob, blob);
return 1;
}
2016-11-05 22:55:01 +00:00
int l_lovrFilesystemRead(lua_State* L) {
const char* path = luaL_checkstring(L, 1);
2017-03-11 09:37:00 +00:00
size_t size;
2016-11-07 22:30:32 +00:00
char* content = lovrFilesystemRead(path, &size);
if (!content) {
2016-11-05 22:55:01 +00:00
return luaL_error(L, "Could not read file '%s'", path);
}
2016-11-07 22:30:32 +00:00
lua_pushlstring(L, content, size);
2016-11-08 06:23:13 +00:00
free(content);
2016-11-05 22:55:01 +00:00
return 1;
}
2017-03-11 09:37:00 +00:00
int l_lovrFilesystemRemove(lua_State* L) {
const char* path = luaL_checkstring(L, 1);
lua_pushboolean(L, !lovrFilesystemRemove(path));
return 1;
}
2016-11-07 22:30:32 +00:00
int l_lovrFilesystemSetIdentity(lua_State* L) {
const char* identity = luaL_checkstring(L, 1);
2016-11-01 00:14:31 +00:00
2016-11-07 22:30:32 +00:00
if (lovrFilesystemSetIdentity(identity)) {
2016-11-12 09:19:47 +00:00
return 0;
2016-11-01 00:14:31 +00:00
}
2016-11-07 22:30:32 +00:00
return 0;
}
2017-03-11 09:37:00 +00:00
int l_lovrFilesystemUnmount(lua_State* L) {
const char* path = luaL_checkstring(L, 1);
lua_pushboolean(L, !lovrFilesystemUnmount(path));
2016-11-01 00:14:31 +00:00
return 1;
}
2016-11-07 22:31:02 +00:00
int l_lovrFilesystemWrite(lua_State* L) {
size_t size;
const char* path = luaL_checkstring(L, 1);
const char* content = luaL_checklstring(L, 2, &size);
2017-03-11 09:37:00 +00:00
lua_pushnumber(L, lovrFilesystemWrite(path, content, size, 0));
2016-11-07 22:31:02 +00:00
return 1;
}
2017-03-11 11:08:07 +00:00
const luaL_Reg lovrFilesystem[] = {
{ "append", l_lovrFilesystemAppend },
{ "exists", l_lovrFilesystemExists },
{ "getAppdataDirectory", l_lovrFilesystemGetAppdataDirectory },
{ "getDirectoryItems", l_lovrFilesystemGetDirectoryItems },
{ "getExecutablePath", l_lovrFilesystemGetExecutablePath },
{ "getIdentity", l_lovrFilesystemGetIdentity },
{ "getLastModified", l_lovrFilesystemGetLastModified },
{ "getRealDirectory", l_lovrFilesystemGetRealDirectory },
{ "getSaveDirectory", l_lovrFilesystemGetSaveDirectory },
{ "getSize", l_lovrFilesystemGetSize },
{ "getSource", l_lovrFilesystemGetSource },
{ "getUserDirectory", l_lovrFilesystemGetUserDirectory },
{ "isDirectory", l_lovrFilesystemIsDirectory },
{ "isFile", l_lovrFilesystemIsFile },
{ "isFused", l_lovrFilesystemIsFused },
{ "load", l_lovrFilesystemLoad },
{ "mount", l_lovrFilesystemMount },
2017-04-01 23:50:10 +00:00
{ "newBlob", l_lovrFilesystemNewBlob },
2017-03-11 11:08:07 +00:00
{ "read", l_lovrFilesystemRead },
{ "remove", l_lovrFilesystemRemove },
{ "setIdentity", l_lovrFilesystemSetIdentity },
{ "write", l_lovrFilesystemWrite },
{ NULL, NULL }
};