From 640e8f0d2e6c518dc7ad98c4be94beb4ad37b941 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Sat, 16 Dec 2017 23:09:15 -0400 Subject: [PATCH] love.filesystem.mount can accept a Data object containing zipped data. - Add mount(Data, archivename, mountpoint [, appendtopath]). 'archivename' must be a string that has not been used with mount before. - Add mount(FileData, mountpoint [, appendtopath]). The file path of the FileData is used as the archive name. - Add unmount(Data). - unmount(archivename) also works. --- src/modules/filesystem/Filesystem.h | 2 + src/modules/filesystem/physfs/Filesystem.cpp | 36 +++++++++++ src/modules/filesystem/physfs/Filesystem.h | 68 +++++++++++--------- src/modules/filesystem/wrap_Filesystem.cpp | 37 +++++++++-- 4 files changed, 108 insertions(+), 35 deletions(-) diff --git a/src/modules/filesystem/Filesystem.h b/src/modules/filesystem/Filesystem.h index b465391e8..41a2fd69c 100644 --- a/src/modules/filesystem/Filesystem.h +++ b/src/modules/filesystem/Filesystem.h @@ -135,7 +135,9 @@ public: virtual const char *getSource() const = 0; virtual bool mount(const char *archive, const char *mountpoint, bool appendToPath = false) = 0; + virtual bool mount(Data *data, const char *archivename, const char *mountpoint, bool appendToPath = false) = 0; virtual bool unmount(const char *archive) = 0; + virtual bool unmount(Data *data) = 0; /** * Creates a new file. diff --git a/src/modules/filesystem/physfs/Filesystem.cpp b/src/modules/filesystem/physfs/Filesystem.cpp index 087f24aae..5a9e1ea19 100644 --- a/src/modules/filesystem/physfs/Filesystem.cpp +++ b/src/modules/filesystem/physfs/Filesystem.cpp @@ -397,11 +397,33 @@ bool Filesystem::mount(const char *archive, const char *mountpoint, bool appendT return PHYSFS_mount(realPath.c_str(), mountpoint, appendToPath) != 0; } +bool Filesystem::mount(Data *data, const char *archivename, const char *mountpoint, bool appendToPath) +{ + if (!PHYSFS_isInit()) + return false; + + if (PHYSFS_mountMemory(data->getData(), data->getSize(), nullptr, archivename, mountpoint, appendToPath) != 0) + { + mountedData[archivename] = data; + return true; + } + + return false; +} + bool Filesystem::unmount(const char *archive) { if (!PHYSFS_isInit() || !archive) return false; + auto datait = mountedData.find(archive); + + if (datait != mountedData.end() && PHYSFS_unmount(archive) != 0) + { + mountedData.erase(datait); + return true; + } + std::string realPath; std::string sourceBase = getSourceBaseDirectory(); @@ -438,6 +460,20 @@ bool Filesystem::unmount(const char *archive) return PHYSFS_unmount(realPath.c_str()) != 0; } +bool Filesystem::unmount(Data *data) +{ + for (const auto &datapair : mountedData) + { + if (datapair.second.get() == data) + { + std::string archive = datapair.first; + return unmount(archive.c_str()); + } + } + + return false; +} + love::filesystem::File *Filesystem::newFile(const char *filename) const { return new File(filename); diff --git a/src/modules/filesystem/physfs/Filesystem.h b/src/modules/filesystem/physfs/Filesystem.h index 9f2aab236..e85873a97 100644 --- a/src/modules/filesystem/physfs/Filesystem.h +++ b/src/modules/filesystem/physfs/Filesystem.h @@ -24,6 +24,7 @@ // STD #include #include +#include // LOVE #include "filesystem/Filesystem.h" @@ -35,7 +36,7 @@ namespace filesystem namespace physfs { -class Filesystem : public love::filesystem::Filesystem +class Filesystem final : public love::filesystem::Filesystem { public: @@ -43,54 +44,57 @@ public: virtual ~Filesystem(); // Implements Module. - const char *getName() const; + const char *getName() const override; - void init(const char *arg0); + void init(const char *arg0) override; - void setFused(bool fused); - bool isFused() const; + void setFused(bool fused) override; + bool isFused() const override; - bool setupWriteDirectory(); + bool setupWriteDirectory() override; - bool setIdentity(const char *ident, bool appendToPath = false); - const char *getIdentity() const; + bool setIdentity(const char *ident, bool appendToPath = false) override; + const char *getIdentity() const override; - bool setSource(const char *source); + bool setSource(const char *source) override; - const char *getSource() const; + const char *getSource() const override; - bool mount(const char *archive, const char *mountpoint, bool appendToPath = false); - bool unmount(const char *archive); + bool mount(const char *archive, const char *mountpoint, bool appendToPath = false) override; + bool mount(Data *data, const char *archivename, const char *mountpoint, bool appendToPath = false) override; - love::filesystem::File *newFile(const char *filename) const; + bool unmount(const char *archive) override; + bool unmount(Data *data) override; - const char *getWorkingDirectory(); - std::string getUserDirectory(); - std::string getAppdataDirectory(); - const char *getSaveDirectory(); - std::string getSourceBaseDirectory() const; + love::filesystem::File *newFile(const char *filename) const override; - std::string getRealDirectory(const char *filename) const; + const char *getWorkingDirectory() override; + std::string getUserDirectory() override; + std::string getAppdataDirectory() override; + const char *getSaveDirectory() override; + std::string getSourceBaseDirectory() const override; - bool getInfo(const char *filepath, Info &info) const; + std::string getRealDirectory(const char *filename) const override; - bool createDirectory(const char *dir); + bool getInfo(const char *filepath, Info &info) const override; - bool remove(const char *file); + bool createDirectory(const char *dir) override; - FileData *read(const char *filename, int64 size = File::ALL) const; - void write(const char *filename, const void *data, int64 size) const; - void append(const char *filename, const void *data, int64 size) const; + bool remove(const char *file) override; - void getDirectoryItems(const char *dir, std::vector &items); + FileData *read(const char *filename, int64 size = File::ALL) const override; + void write(const char *filename, const void *data, int64 size) const override; + void append(const char *filename, const void *data, int64 size) const override; - void setSymlinksEnabled(bool enable); - bool areSymlinksEnabled() const; + void getDirectoryItems(const char *dir, std::vector &items) override; - std::vector &getRequirePath(); - std::vector &getCRequirePath(); + void setSymlinksEnabled(bool enable) override; + bool areSymlinksEnabled() const override; - void allowMountingForPath(const std::string &path); + std::vector &getRequirePath() override; + std::vector &getCRequirePath() override; + + void allowMountingForPath(const std::string &path) override; private: @@ -123,6 +127,8 @@ private: std::vector allowedMountPaths; + std::map> mountedData; + }; // Filesystem } // physfs diff --git a/src/modules/filesystem/wrap_Filesystem.cpp b/src/modules/filesystem/wrap_Filesystem.cpp index fc51aba42..5463dff64 100644 --- a/src/modules/filesystem/wrap_Filesystem.cpp +++ b/src/modules/filesystem/wrap_Filesystem.cpp @@ -116,7 +116,29 @@ int w_mount(lua_State *L) { std::string archive; - if (luax_istype(L, 1, DroppedFile::type)) + if (luax_istype(L, 1, Data::type)) + { + Data *data = love::data::luax_checkdata(L, 1); + int startidx = 2; + + if (luax_istype(L, 1, FileData::type) && !lua_isstring(L, 3)) + { + FileData *filedata = luax_checkfiledata(L, 1); + archive = filedata->getFilename(); + startidx = 2; + } + else + { + archive = luax_checkstring(L, 2); + startidx = 3; + } + + const char *mountpoint = luaL_checkstring(L, startidx + 0); + bool append = luax_optboolean(L, startidx + 1, false); + + luax_pushboolean(L, instance()->mount(data, archive.c_str(), mountpoint, append)); + } + else if (luax_istype(L, 1, DroppedFile::type)) { DroppedFile *file = luax_totype(L, 1); archive = file->getFilename(); @@ -133,9 +155,16 @@ int w_mount(lua_State *L) int w_unmount(lua_State *L) { - const char *archive = luaL_checkstring(L, 1); - - luax_pushboolean(L, instance()->unmount(archive)); + if (luax_istype(L, 1, Data::type)) + { + Data *data = love::data::luax_checkdata(L, 1); + luax_pushboolean(L, instance()->unmount(data)); + } + else + { + const char *archive = luaL_checkstring(L, 1); + luax_pushboolean(L, instance()->unmount(archive)); + } return 1; }