lovr/src/api/l_filesystem_file.c

132 lines
3.5 KiB
C

#include "api.h"
#include "data/blob.h"
#include "filesystem/filesystem.h"
#include "util.h"
#include <stdlib.h>
static int l_lovrFileGetMode(lua_State* L) {
File* file = luax_checktype(L, 1, File);
OpenMode mode = lovrFileGetMode(file);
luax_pushenum(L, OpenMode, mode);
return 1;
}
static int l_lovrFileGetPath(lua_State* L) {
File* file = luax_checktype(L, 1, File);
const char* path = lovrFileGetPath(file);
lua_pushstring(L, path);
return 1;
}
static int l_lovrFileGetSize(lua_State* L) {
File* file = luax_checktype(L, 1, File);
uint64_t size = lovrFileGetSize(file);
if (size >= 1ull << 53) {
lua_pushnil(L);
} else {
lua_pushinteger(L, size);
}
return 1;
}
static int l_lovrFileRead(lua_State* L) {
File* file = luax_checktype(L, 1, File);
size_t size;
if (lua_type(L, 2) == LUA_TNUMBER) {
lua_Number n = lua_tonumber(L, 2);
lovrCheck(n >= 0, "Number of bytes to read can not be negative");
lovrCheck(n < 9007199254740992.0, "Number of bytes to read must be less than 2^53");
size = (size_t) n;
} else {
size = lovrFileGetSize(file) - lovrFileTell(file);
}
size_t count;
void* data = lovrMalloc(size);
bool success = lovrFileRead(file, data, size, &count);
if (success) {
lua_pushlstring(L, data, count);
lua_pushnumber(L, count);
lovrFree(data);
return 2;
} else {
lua_pushnil(L);
lovrFree(data);
return 1;
}
}
static int l_lovrFileWrite(lua_State* L) {
File* file = luax_checktype(L, 1, File);
const void* data;
size_t size;
Blob* blob = luax_totype(L, 2, Blob);
if (blob) {
data = blob->data;
size = blob->size;
} else if (lua_type(L, 2) == LUA_TSTRING) {
data = lua_tolstring(L, 2, &size);
} else {
return luax_typeerror(L, 2, "string or Blob");
}
if (lua_type(L, 3) == LUA_TNUMBER) {
lua_Number n = lua_tonumber(L, 2);
lovrCheck(n >= 0, "Number of bytes to write can not be negative");
lovrCheck(n < 9007199254740992.0, "Number of bytes to write must be less than 2^53");
lovrCheck(n <= size, "Number of bytes to write is bigger than the size of the source");
size = (size_t) n;
}
size_t count;
bool success = lovrFileWrite(file, data, size, &count);
if (success && count == size) {
lua_pushboolean(L, true);
} else {
lua_pushboolean(L, false);
}
return 1;
}
static int l_lovrFileSeek(lua_State* L) {
File* file = luax_checktype(L, 1, File);
lua_Number offset = luaL_checknumber(L, 2);
lovrCheck(offset >= 0 && offset < 9007199254740992.0, "Invalid seek position");
bool success = lovrFileSeek(file, offset);
lua_pushboolean(L, success);
return 1;
}
static int l_lovrFileTell(lua_State* L) {
File* file = luax_checktype(L, 1, File);
uint64_t offset = lovrFileTell(file);
if (offset >= 1ull << 53) {
lua_pushnil(L);
} else {
lua_pushinteger(L, offset);
}
return 1;
}
static int l_lovrFileIsEOF(lua_State* L) {
File* file = luax_checktype(L, 1, File);
OpenMode mode = lovrFileGetMode(file);
if (mode == OPEN_READ) {
uint64_t offset = lovrFileTell(file);
uint64_t extent = lovrFileGetSize(file);
lua_pushboolean(L, offset >= extent);
} else {
lua_pushboolean(L, false);
}
return 1;
}
const luaL_Reg lovrFile[] = {
{ "getMode", l_lovrFileGetMode },
{ "getPath", l_lovrFileGetPath },
{ "getSize", l_lovrFileGetSize },
{ "read", l_lovrFileRead },
{ "write", l_lovrFileWrite },
{ "seek", l_lovrFileSeek },
{ "tell", l_lovrFileTell },
{ "isEOF", l_lovrFileIsEOF },
{ NULL, NULL }
};