initial commit
This commit is contained in:
@@ -0,0 +1,182 @@
|
||||
// @lua-module fs FsLib
|
||||
// @lua-const MAX_READ_BYTES integer 65536 Largest portable whole-file or line read.
|
||||
|
||||
#include "../helpers.h"
|
||||
|
||||
namespace esp32lua {
|
||||
namespace bindings {
|
||||
namespace {
|
||||
|
||||
constexpr int32_t MAX_READ_BYTES = 65536;
|
||||
|
||||
int32_t checkReadLimit(lua_State* state, int index) {
|
||||
const int32_t maxBytes = checkInt(state, index);
|
||||
luaL_argcheck(state, maxBytes >= 0 && maxBytes <= MAX_READ_BYTES, index, "exceeds fs.MAX_READ_BYTES");
|
||||
return maxBytes;
|
||||
}
|
||||
|
||||
int exists(lua_State* state) {
|
||||
const std::string path = checkString(state, 1);
|
||||
lua_pushboolean(state, Runtime::from(state)->fs().exists(path));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int fileSize(lua_State* state) {
|
||||
const std::string path = checkString(state, 1);
|
||||
int32_t size = 0;
|
||||
const Status status = Runtime::from(state)->fs().fileSize(path, size);
|
||||
if (!status.ok) return pushError(state, status.error);
|
||||
lua_pushinteger(state, size);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int list(lua_State* state, bool directories) {
|
||||
const std::string path = checkString(state, 1);
|
||||
std::vector<std::string> names;
|
||||
const FsProvider& fs = Runtime::from(state)->fs();
|
||||
const Status status = directories ? fs.listDirs(path, names) : fs.listFiles(path, names);
|
||||
if (!status.ok) return pushError(state, status.error);
|
||||
pushStrings(state, names);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int listDirs(lua_State* state) { return list(state, true); }
|
||||
int listFiles(lua_State* state) { return list(state, false); }
|
||||
|
||||
int mkdir(lua_State* state) {
|
||||
const std::string path = checkString(state, 1);
|
||||
return pushStatus(state, Runtime::from(state)->fs().mkdir(path));
|
||||
}
|
||||
|
||||
int readFile(lua_State* state) {
|
||||
const int32_t maxBytes = checkReadLimit(state, 2);
|
||||
const std::string path = checkString(state, 1);
|
||||
std::string content;
|
||||
const Status status = Runtime::from(state)->fs().readFile(path, maxBytes, content);
|
||||
if (!status.ok) return pushError(state, status.error);
|
||||
pushString(state, content);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int readLineAt(lua_State* state) {
|
||||
const int32_t offset = checkInt(state, 2);
|
||||
const int32_t maxBytes = checkReadLimit(state, 3);
|
||||
luaL_argcheck(state, offset >= 0, 2, "must not be negative");
|
||||
const std::string path = checkString(state, 1);
|
||||
|
||||
bool found = false;
|
||||
int32_t nextOffset = 0;
|
||||
std::string line;
|
||||
const Status status = Runtime::from(state)->fs().readLineAt(path, offset, maxBytes, found, line, nextOffset);
|
||||
if (!status.ok) {
|
||||
lua_pushnil(state);
|
||||
lua_pushnil(state);
|
||||
pushString(state, status.error);
|
||||
return 3;
|
||||
}
|
||||
if (!found) {
|
||||
lua_pushnil(state);
|
||||
return 1;
|
||||
}
|
||||
pushString(state, line);
|
||||
lua_pushinteger(state, nextOffset);
|
||||
return 2;
|
||||
}
|
||||
|
||||
int remove(lua_State* state) {
|
||||
const std::string path = checkString(state, 1);
|
||||
return pushStatus(state, Runtime::from(state)->fs().remove(path));
|
||||
}
|
||||
|
||||
int removeTree(lua_State* state) {
|
||||
const std::string path = checkString(state, 1);
|
||||
return pushStatus(state, Runtime::from(state)->fs().removeTree(path));
|
||||
}
|
||||
|
||||
int rename(lua_State* state) {
|
||||
const std::string source = checkString(state, 1);
|
||||
const std::string destination = checkString(state, 2);
|
||||
return pushStatus(state, Runtime::from(state)->fs().rename(source, destination));
|
||||
}
|
||||
|
||||
int writeFile(lua_State* state) {
|
||||
const std::string path = checkString(state, 1);
|
||||
const std::string content = checkString(state, 2);
|
||||
return pushStatus(state, Runtime::from(state)->fs().writeFile(path, content));
|
||||
}
|
||||
|
||||
const luaL_Reg FUNCTIONS[] = {
|
||||
// --- Whether a path exists.
|
||||
// @param path string Absolute SD-card path; traversal components are rejected.
|
||||
// @return boolean
|
||||
{"exists", exists},
|
||||
// --- Returns the size of a file in bytes.
|
||||
// @param path string Absolute SD-card path.
|
||||
// @return integer|nil size
|
||||
// @return string|nil error Present when the path is missing or not a file.
|
||||
{"fileSize", fileSize},
|
||||
// --- Lists the directories in a directory.
|
||||
// @param path string Absolute directory path.
|
||||
// @return string[]|nil names Sorted names, excluding hidden entries.
|
||||
// @return string|nil error
|
||||
{"listDirs", listDirs},
|
||||
// --- Lists the files in a directory.
|
||||
// @param path string Absolute directory path.
|
||||
// @return string[]|nil names Sorted names, excluding hidden entries.
|
||||
// @return string|nil error
|
||||
{"listFiles", listFiles},
|
||||
// --- Creates a directory.
|
||||
// @param path string Absolute directory path.
|
||||
// @return true|nil ok
|
||||
// @return string|nil error
|
||||
{"mkdir", mkdir},
|
||||
// --- Reads a whole file.
|
||||
// @param path string Absolute file path.
|
||||
// @param maxBytes integer Maximum bytes to allocate, up to fs.MAX_READ_BYTES; oversized files fail rather than truncate.
|
||||
// @return string|nil content
|
||||
// @return string|nil error
|
||||
{"readFile", readFile},
|
||||
// --- Reads one line starting at a byte offset.
|
||||
// @param path string Absolute file path.
|
||||
// @param offset integer Zero-based byte offset; a mid-line offset advances to the next line.
|
||||
// @param maxBytes integer Maximum line bytes to allocate, up to fs.MAX_READ_BYTES.
|
||||
// @return string|nil line Nil at end of file or on failure.
|
||||
// @return integer|nil nextOffset Byte offset of the following line.
|
||||
// @return string|nil error Present when the file cannot be read or the line exceeds maxBytes.
|
||||
{"readLineAt", readLineAt},
|
||||
// --- Removes a file.
|
||||
// @param path string Absolute file path. Firmware-protected roots cannot be removed.
|
||||
// @return true|nil ok
|
||||
// @return string|nil error
|
||||
{"remove", remove},
|
||||
// --- Removes a directory and everything below it.
|
||||
// @param path string Absolute directory path. Firmware-protected roots cannot be removed.
|
||||
// @return true|nil ok
|
||||
// @return string|nil error
|
||||
{"removeTree", removeTree},
|
||||
// --- Renames a file or directory.
|
||||
// @param source string Absolute source path.
|
||||
// @param destination string Absolute destination path, which must not exist.
|
||||
// @return true|nil ok
|
||||
// @return string|nil error
|
||||
{"rename", rename},
|
||||
// --- Atomically replaces the destination or leaves its previous contents intact.
|
||||
// @param path string Absolute file path.
|
||||
// @param content string
|
||||
// @return true|nil ok
|
||||
// @return string|nil error
|
||||
{"writeFile", writeFile},
|
||||
{nullptr, nullptr},
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
void registerFs(lua_State* state) {
|
||||
luaL_newlib(state, FUNCTIONS);
|
||||
lua_pushinteger(state, MAX_READ_BYTES);
|
||||
lua_setfield(state, -2, "MAX_READ_BYTES");
|
||||
lua_setglobal(state, "fs");
|
||||
}
|
||||
|
||||
} // namespace bindings
|
||||
} // namespace esp32lua
|
||||
Reference in New Issue
Block a user