173 lines
4.0 KiB
C++
173 lines
4.0 KiB
C++
// Copyright © 2008-2021 Pioneer Developers. See AUTHORS.txt for details
|
|
// Licensed under the terms of the GPL v3. See licenses/GPL-3.txt
|
|
|
|
#include "LuaFileSystem.h"
|
|
#include "FileSystem.h"
|
|
#include "LuaConstants.h"
|
|
#include "LuaObject.h"
|
|
#include "Pi.h"
|
|
|
|
/*
|
|
* Interface: FileSystem
|
|
*
|
|
* A global table that provides access to the filesystem.
|
|
*
|
|
* This interface is protected. It can only be used by scripts in Pioneer's
|
|
* data directory. Mods and scripts in the user directory that try to use it
|
|
* will get a Lua error.
|
|
*/
|
|
|
|
static void push_date_time(lua_State *l, const Time::DateTime &dt)
|
|
{
|
|
int year, month, day, hour, minute, second;
|
|
dt.GetDateParts(&year, &month, &day);
|
|
dt.GetTimeParts(&hour, &minute, &second);
|
|
|
|
lua_newtable(l);
|
|
pi_lua_settable(l, "year", year);
|
|
pi_lua_settable(l, "month", month);
|
|
pi_lua_settable(l, "day", day);
|
|
pi_lua_settable(l, "hour", hour);
|
|
pi_lua_settable(l, "minute", minute);
|
|
pi_lua_settable(l, "second", second);
|
|
pi_lua_settable(l, "timestamp", dt.ToGameTime());
|
|
}
|
|
|
|
/*
|
|
* Function: ReadDirectory
|
|
*
|
|
* > local files, dirs = FileSystem.ReadDirectory(root, path)
|
|
*
|
|
* Return a list of files and dirs in the specified directory.
|
|
*
|
|
* Parameters:
|
|
*
|
|
* root - a <FileSystemRoot> constant for the root of the dir to read from
|
|
* path - optional. a directory under the root
|
|
*
|
|
* Returns:
|
|
*
|
|
* files - a list of files as full paths from the root
|
|
* dirs - a list of dirs as full paths from the root
|
|
*
|
|
* Availability:
|
|
*
|
|
* alpha 26
|
|
*
|
|
* Status:
|
|
*
|
|
* experimental
|
|
*/
|
|
static int l_filesystem_read_dir(lua_State *l)
|
|
{
|
|
LuaFileSystem::Root root = static_cast<LuaFileSystem::Root>(LuaConstants::GetConstantFromArg(l, "FileSystemRoot", 1));
|
|
std::string path;
|
|
if (lua_gettop(l) > 1)
|
|
path = luaL_checkstring(l, 2);
|
|
|
|
FileSystem::FileSource *fs = nullptr;
|
|
switch (root) {
|
|
case LuaFileSystem::ROOT_USER:
|
|
fs = &FileSystem::userFiles;
|
|
break;
|
|
|
|
case LuaFileSystem::ROOT_DATA:
|
|
fs = &FileSystem::gameDataFiles;
|
|
break;
|
|
|
|
default:
|
|
assert(0); // can't happen
|
|
return 0;
|
|
}
|
|
|
|
assert(fs);
|
|
|
|
{
|
|
try {
|
|
const FileSystem::FileInfo &info = fs->Lookup(path);
|
|
if (!info.IsDir()) {
|
|
luaL_error(l, "'%s' is not a directory", path.c_str());
|
|
return 0;
|
|
}
|
|
} catch (const std::invalid_argument &) {
|
|
luaL_error(l, "'%s' is not a valid path", path.c_str());
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
FileSystem::FileEnumerator files(*fs, FileSystem::FileEnumerator::IncludeDirs);
|
|
files.AddSearchRoot(path);
|
|
|
|
lua_newtable(l);
|
|
int filesTable = lua_gettop(l);
|
|
lua_newtable(l);
|
|
int dirsTable = lua_gettop(l);
|
|
|
|
for (; !files.Finished(); files.Next()) {
|
|
const FileSystem::FileInfo &info = files.Current();
|
|
|
|
lua_newtable(l);
|
|
pi_lua_settable(l, "name", info.GetName().c_str());
|
|
push_date_time(l, info.GetModificationTime());
|
|
lua_setfield(l, -2, "mtime");
|
|
|
|
if (info.IsDir())
|
|
lua_rawseti(l, dirsTable, lua_rawlen(l, dirsTable) + 1);
|
|
else
|
|
lua_rawseti(l, filesTable, lua_rawlen(l, filesTable) + 1);
|
|
}
|
|
|
|
return 2;
|
|
}
|
|
|
|
/*
|
|
* Function: JoinPath
|
|
*
|
|
* > local path = FileSystem.JoinPath(...)
|
|
*
|
|
* Join the passed arguments into a path, correctly handling separators and .
|
|
* and .. special dirs.
|
|
*
|
|
* Availability:
|
|
*
|
|
* alpha 26
|
|
*
|
|
* Status:
|
|
*
|
|
* experimental
|
|
*/
|
|
static int l_filesystem_join_path(lua_State *l)
|
|
{
|
|
try {
|
|
std::string path;
|
|
for (int i = 1; i <= lua_gettop(l); i++)
|
|
path = FileSystem::JoinPath(path, luaL_checkstring(l, i));
|
|
path = FileSystem::NormalisePath(path);
|
|
lua_pushlstring(l, path.c_str(), path.size());
|
|
return 1;
|
|
} catch (const std::invalid_argument &) {
|
|
luaL_error(l, "result is not a valid path");
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
void LuaFileSystem::Register()
|
|
{
|
|
lua_State *l = Lua::manager->GetLuaState();
|
|
|
|
LUA_DEBUG_START(l);
|
|
|
|
static const luaL_Reg l_methods[] = {
|
|
{ "ReadDirectory", l_filesystem_read_dir },
|
|
{ "JoinPath", l_filesystem_join_path },
|
|
{ 0, 0 }
|
|
};
|
|
|
|
lua_getfield(l, LUA_REGISTRYINDEX, "CoreImports");
|
|
LuaObjectBase::CreateObject(l_methods, 0, 0, true); // protected interface
|
|
lua_setfield(l, -2, "FileSystem");
|
|
lua_pop(l, 1);
|
|
|
|
LUA_DEBUG_END(l, 0);
|
|
}
|