diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7485832d9..3364876d2 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -186,10 +186,16 @@ source_group("modules\\event\\sdl" FILES ${LOVE_SRC_MODULE_EVENT_SDL})
#
set(LOVE_SRC_MODULE_FILESYSTEM_ROOT
+ src/modules/filesystem/DroppedFile.cpp
+ src/modules/filesystem/DroppedFile.h
src/modules/filesystem/File.cpp
src/modules/filesystem/File.h
src/modules/filesystem/FileData.cpp
src/modules/filesystem/FileData.h
+ src/modules/filesystem/Filesystem.cpp
+ src/modules/filesystem/Filesystem.h
+ src/modules/filesystem/wrap_DroppedFile.cpp
+ src/modules/filesystem/wrap_DroppedFile.h
src/modules/filesystem/wrap_File.cpp
src/modules/filesystem/wrap_File.h
src/modules/filesystem/wrap_FileData.cpp
diff --git a/platform/macosx/love-Info.plist b/platform/macosx/love-Info.plist
index 3dbad5b89..3be04e47f 100644
--- a/platform/macosx/love-Info.plist
+++ b/platform/macosx/love-Info.plist
@@ -32,6 +32,18 @@
LSHandlerRank
None
+
+ CFBundleTypeName
+ Document
+ CFBundleTypeRole
+ Editor
+ CFBundleTypeOSTypes
+
+ ****
+
+ CFBundleTypeIconFile
+ Document
+
CFBundleExecutable
love
diff --git a/platform/macosx/love-framework.xcodeproj/project.pbxproj b/platform/macosx/love-framework.xcodeproj/project.pbxproj
index d40cffc25..3fadf03fa 100644
--- a/platform/macosx/love-framework.xcodeproj/project.pbxproj
+++ b/platform/macosx/love-framework.xcodeproj/project.pbxproj
@@ -272,7 +272,13 @@
FA636D8B171B70920065623F /* RandomGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = FA636D89171B70920065623F /* RandomGenerator.h */; };
FA636D8E171B72A70065623F /* wrap_RandomGenerator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA636D8C171B72A70065623F /* wrap_RandomGenerator.cpp */; };
FA636D8F171B72A70065623F /* wrap_RandomGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = FA636D8D171B72A70065623F /* wrap_RandomGenerator.h */; };
+ FA70573C194A3FC600670B30 /* DroppedFile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA70573A194A3FC600670B30 /* DroppedFile.cpp */; };
+ FA70573D194A3FC600670B30 /* DroppedFile.h in Headers */ = {isa = PBXBuildFile; fileRef = FA70573B194A3FC600670B30 /* DroppedFile.h */; };
+ FA705740194A55CB00670B30 /* wrap_DroppedFile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA70573E194A55CB00670B30 /* wrap_DroppedFile.cpp */; };
+ FA705741194A55CB00670B30 /* wrap_DroppedFile.h in Headers */ = {isa = PBXBuildFile; fileRef = FA70573F194A55CB00670B30 /* wrap_DroppedFile.h */; };
FA7175AA178E8418001FE7FE /* lua.h in Headers */ = {isa = PBXBuildFile; fileRef = FA7175A9178E8418001FE7FE /* lua.h */; };
+ FA782D0119F2F945006A3E93 /* Filesystem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA782CFF19F2F945006A3E93 /* Filesystem.cpp */; };
+ FA782D0219F2F945006A3E93 /* Filesystem.h in Headers */ = {isa = PBXBuildFile; fileRef = FA782D0019F2F945006A3E93 /* Filesystem.h */; };
FA7AA59217F6AC1F00704BE2 /* wrap_Mesh.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA7AA59017F6AC1F00704BE2 /* wrap_Mesh.cpp */; };
FA7AA59317F6AC1F00704BE2 /* wrap_Mesh.h in Headers */ = {isa = PBXBuildFile; fileRef = FA7AA59117F6AC1F00704BE2 /* wrap_Mesh.h */; };
FA7C937A16DCC6C2006F2BEE /* wrap_Math.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA7C937516DCC6C2006F2BEE /* wrap_Math.cpp */; };
@@ -843,7 +849,13 @@
FA636D89171B70920065623F /* RandomGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RandomGenerator.h; sourceTree = ""; };
FA636D8C171B72A70065623F /* wrap_RandomGenerator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_RandomGenerator.cpp; sourceTree = ""; };
FA636D8D171B72A70065623F /* wrap_RandomGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_RandomGenerator.h; sourceTree = ""; };
+ FA70573A194A3FC600670B30 /* DroppedFile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DroppedFile.cpp; sourceTree = ""; };
+ FA70573B194A3FC600670B30 /* DroppedFile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DroppedFile.h; sourceTree = ""; };
+ FA70573E194A55CB00670B30 /* wrap_DroppedFile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_DroppedFile.cpp; sourceTree = ""; };
+ FA70573F194A55CB00670B30 /* wrap_DroppedFile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_DroppedFile.h; sourceTree = ""; };
FA7175A9178E8418001FE7FE /* lua.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = lua.h; sourceTree = ""; };
+ FA782CFF19F2F945006A3E93 /* Filesystem.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Filesystem.cpp; sourceTree = ""; };
+ FA782D0019F2F945006A3E93 /* Filesystem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Filesystem.h; sourceTree = ""; };
FA7AA59017F6AC1F00704BE2 /* wrap_Mesh.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_Mesh.cpp; sourceTree = ""; };
FA7AA59117F6AC1F00704BE2 /* wrap_Mesh.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_Mesh.h; sourceTree = ""; };
FA7C937516DCC6C2006F2BEE /* wrap_Math.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_Math.cpp; sourceTree = ""; };
@@ -1757,11 +1769,17 @@
7B0734182055607468261A5E /* filesystem */ = {
isa = PBXGroup;
children = (
+ FA70573A194A3FC600670B30 /* DroppedFile.cpp */,
+ FA70573B194A3FC600670B30 /* DroppedFile.h */,
11D141087979064B441B787D /* File.cpp */,
31A444CF0B4E6DA450120730 /* File.h */,
62370A494F9D6E2D570065EB /* FileData.cpp */,
54A13C2209F945671BC27974 /* FileData.h */,
+ FA782CFF19F2F945006A3E93 /* Filesystem.cpp */,
+ FA782D0019F2F945006A3E93 /* Filesystem.h */,
64DD03B45BF6265723662DAF /* physfs */,
+ FA70573E194A55CB00670B30 /* wrap_DroppedFile.cpp */,
+ FA70573F194A55CB00670B30 /* wrap_DroppedFile.h */,
6C367AE309C453C412D91363 /* wrap_File.cpp */,
52E15B702C40593D3BF431DF /* wrap_File.h */,
597478A255B82B56488B4717 /* wrap_FileData.cpp */,
@@ -2044,6 +2062,7 @@
FAE010DD170DDE99006F29D0 /* ddsparse.h in Headers */,
FAE010E1170DE25E006F29D0 /* ddsHandler.h in Headers */,
FAE010E5170DF75C006F29D0 /* wrap_CompressedData.h in Headers */,
+ FA705741194A55CB00670B30 /* wrap_DroppedFile.h in Headers */,
FAF6704E18184FF800DBDEEA /* wuff_config.h in Headers */,
FA0CDE3D1710F9A50056E8D7 /* FormatHandler.h in Headers */,
FA7AA59317F6AC1F00704BE2 /* wrap_Mesh.h in Headers */,
@@ -2088,8 +2107,10 @@
FA34E7CE174B513F00E04D3F /* System.h in Headers */,
FA34E7D3174B515D00E04D3F /* System.h in Headers */,
FAF670571818501300DBDEEA /* WaveDecoder.h in Headers */,
+ FA70573D194A3FC600670B30 /* DroppedFile.h in Headers */,
FA1EF7C51799FEB200FF380C /* wrap_System.h in Headers */,
FA435EA417B36E9C004C3F22 /* Polyline.h in Headers */,
+ FA782D0219F2F945006A3E93 /* Filesystem.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -2283,6 +2304,7 @@
FA08F62C16C7541400F007B5 /* wrap_Shader.cpp in Sources */,
FA0A4BFA182E26F500E1E4D2 /* wrap_MotorJoint.cpp in Sources */,
FA08F62D16C7541400F007B5 /* wrap_SpriteBatch.cpp in Sources */,
+ FA782D0119F2F945006A3E93 /* Filesystem.cpp in Sources */,
FA08F62E16C7542600F007B5 /* ImageData.cpp in Sources */,
FA08F62F16C7542600F007B5 /* Image.cpp in Sources */,
FA08F63116C7542600F007B5 /* wrap_Image.cpp in Sources */,
@@ -2351,10 +2373,12 @@
FA08F66D16C7549200F007B5 /* wrap_Sound.cpp in Sources */,
FA08F66E16C7549200F007B5 /* wrap_SoundData.cpp in Sources */,
FA08F66F16C754A100F007B5 /* Decoder.cpp in Sources */,
+ FA70573C194A3FC600670B30 /* DroppedFile.cpp in Sources */,
FA08F67016C754A100F007B5 /* FLACDecoder.cpp in Sources */,
FA08F67116C754A100F007B5 /* GmeDecoder.cpp in Sources */,
FA08F67216C754A100F007B5 /* ModPlugDecoder.cpp in Sources */,
FA08F67316C754A100F007B5 /* Mpg123Decoder.cpp in Sources */,
+ FA705740194A55CB00670B30 /* wrap_DroppedFile.cpp in Sources */,
FA08F67416C754A100F007B5 /* Sound.cpp in Sources */,
FA08F67516C754A100F007B5 /* VorbisDecoder.cpp in Sources */,
FA08F67716C754A900F007B5 /* threads.cpp in Sources */,
diff --git a/src/common/runtime.cpp b/src/common/runtime.cpp
index f152e4df4..e26c4d1e2 100644
--- a/src/common/runtime.cpp
+++ b/src/common/runtime.cpp
@@ -634,6 +634,7 @@ StringMap::Entry typeEntries[] =
// Filesystem
{"File", FILESYSTEM_FILE_ID},
+ {"DroppedFile", FILESYSTEM_DROPPED_FILE_ID},
{"FileData", FILESYSTEM_FILE_DATA_ID},
// Font
diff --git a/src/common/types.h b/src/common/types.h
index e9319ea58..016cfa41f 100644
--- a/src/common/types.h
+++ b/src/common/types.h
@@ -37,6 +37,7 @@ enum Type
// Filesystem.
FILESYSTEM_FILE_ID,
+ FILESYSTEM_DROPPED_FILE_ID,
FILESYSTEM_FILE_DATA_ID,
// Font
@@ -123,6 +124,7 @@ const bits MODULE_T = (bits(1) << MODULE_ID) | OBJECT_T;
// Filesystem.
const bits FILESYSTEM_FILE_T = (bits(1) << FILESYSTEM_FILE_ID) | OBJECT_T;
+const bits FILESYSTEM_DROPPED_FILE_T = (bits(1) << FILESYSTEM_DROPPED_FILE_ID) | FILESYSTEM_FILE_T;
const bits FILESYSTEM_FILE_DATA_T = (bits(1) << FILESYSTEM_FILE_DATA_ID) | DATA_T;
const bits FONT_GLYPH_DATA_T = (bits(1) << FONT_GLYPH_DATA_ID) | DATA_T;
diff --git a/src/modules/event/sdl/Event.cpp b/src/modules/event/sdl/Event.cpp
index bae71cfc7..5d98924f4 100644
--- a/src/modules/event/sdl/Event.cpp
+++ b/src/modules/event/sdl/Event.cpp
@@ -20,6 +20,8 @@
#include "Event.h"
+#include "filesystem/DroppedFile.h"
+#include "filesystem/Filesystem.h"
#include "keyboard/Keyboard.h"
#include "mouse/Mouse.h"
#include "joystick/JoystickModule.h"
@@ -108,7 +110,8 @@ Message *Event::convert(const SDL_Event &e) const
{
Message *msg = NULL;
- love::keyboard::Keyboard *kb = 0;
+ love::keyboard::Keyboard *kb = nullptr;
+ love::filesystem::Filesystem *filesystem = nullptr;
love::keyboard::Keyboard::Key key;
love::mouse::Mouse::Button button;
@@ -210,6 +213,29 @@ Message *Event::convert(const SDL_Event &e) const
msg = convertWindowEvent(e);
break;
case SDL_DROPFILE:
+ filesystem = Module::getInstance(Module::M_FILESYSTEM);
+ if (filesystem != nullptr)
+ {
+ // Allow mounting any dropped path, so zips or dirs can be mounted.
+ filesystem->allowMountingForPath(e.drop.file);
+
+ if (filesystem->isRealDirectory(e.drop.file))
+ {
+ arg1 = new Variant(e.drop.file, strlen(e.drop.file));
+ msg = new Message("directorydropped", arg1);
+ arg1->release();
+ }
+ else
+ {
+ Proxy proxy;
+ proxy.data = new love::filesystem::DroppedFile(e.drop.file);
+ proxy.flags = FILESYSTEM_DROPPED_FILE_T;
+ arg1 = new Variant(FILESYSTEM_DROPPED_FILE_ID, &proxy);
+ msg = new Message("filedropped", arg1);
+ arg1->release();
+ ((Object *) proxy.data)->release();
+ }
+ }
SDL_free(e.drop.file);
break;
case SDL_QUIT:
diff --git a/src/modules/filesystem/DroppedFile.cpp b/src/modules/filesystem/DroppedFile.cpp
new file mode 100644
index 000000000..f83df867d
--- /dev/null
+++ b/src/modules/filesystem/DroppedFile.cpp
@@ -0,0 +1,252 @@
+/**
+ * Copyright (c) 2006-2014 LOVE Development Team
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ **/
+
+// LOVE
+#include "DroppedFile.h"
+#include "common/utf8.h"
+
+// Assume POSIX or Visual Studio.
+#include
+#include
+
+#ifdef LOVE_WINDOWS
+#include
+#else
+#include // POSIX.
+#endif
+
+namespace love
+{
+namespace filesystem
+{
+
+DroppedFile::DroppedFile(const std::string &filename)
+ : filename(filename)
+ , file(nullptr)
+ , mode(MODE_CLOSED)
+ , bufferMode(BUFFER_NONE)
+ , bufferSize(0)
+{
+}
+
+DroppedFile::~DroppedFile()
+{
+ if (mode != MODE_CLOSED)
+ close();
+}
+
+bool DroppedFile::open(Mode newmode)
+{
+ if (newmode == MODE_CLOSED)
+ return true;
+
+ // File already open?
+ if (file != nullptr)
+ return false;
+
+#ifdef LOVE_WINDOWS
+ // make sure non-ASCII filenames work.
+ std::wstring modestr = to_widestr(getModeString(newmode));
+ file = _wfopen(to_widestr(filename).c_str(), modestr.c_str());
+#else
+ file = fopen(filename.c_str(), getModeString(newmode));
+#endif
+
+ if (newmode == MODE_READ && file == nullptr)
+ throw love::Exception("Could not open file %s. Does not exist.", filename.c_str());
+
+ mode = newmode;
+
+ if (file != nullptr && !setBuffer(bufferMode, bufferSize))
+ {
+ // Revert to buffer defaults if we don't successfully set the buffer.
+ bufferMode = BUFFER_NONE;
+ bufferSize = 0;
+ }
+
+ return file != nullptr;
+}
+
+bool DroppedFile::close()
+{
+ if (file == nullptr || fclose(file) != 0)
+ return false;
+
+ mode = MODE_CLOSED;
+ file = nullptr;
+
+ return true;
+}
+
+bool DroppedFile::isOpen() const
+{
+ return mode != MODE_CLOSED && file != nullptr;
+}
+
+int64 DroppedFile::getSize()
+{
+#ifdef LOVE_WINDOWS
+
+ // make sure non-ASCII filenames work.
+ struct _stat buf;
+ if (_wstat(to_widestr(filename).c_str(), &buf) != 0)
+ return -1;
+
+ return (int64) buf.st_size;
+
+#else
+
+ // Assume POSIX support...
+ struct stat buf;
+ if (stat(filename.c_str(), &buf) != 0)
+ return -1;
+
+ return (int64) buf.st_size;
+
+#endif
+}
+
+int64 DroppedFile::read(void *dst, int64 size)
+{
+ if (!file || mode != MODE_READ)
+ throw love::Exception("File is not opened for reading.");
+
+ if (size < 0)
+ throw love::Exception("Invalid read size.");
+
+ size_t read = fread(dst, 1, (size_t) size, file);
+
+ return (int64) read;
+}
+
+bool DroppedFile::write(const void *data, int64 size)
+{
+ if (!file || (mode != MODE_WRITE && mode != MODE_APPEND))
+ throw love::Exception("File is not opened for writing.");
+
+ if (size < 0)
+ throw love::Exception("Invalid write size.");
+
+ int64 written = (int64) fwrite(data, 1, (size_t) size, file);
+
+ return written == size;
+}
+
+bool DroppedFile::flush()
+{
+ if (!file || (mode != MODE_WRITE && mode != MODE_APPEND))
+ throw love::Exception("File is not opened for writing.");
+
+ return fflush(file) == 0;
+}
+
+bool DroppedFile::eof()
+{
+ return file == nullptr || feof(file) != 0;
+}
+
+int64 DroppedFile::tell()
+{
+ if (file == nullptr)
+ return -1;
+
+ return (int64) ftell(file);
+}
+
+bool DroppedFile::seek(uint64 pos)
+{
+ return file != nullptr && fseek(file, (long) pos, SEEK_SET) == 0;
+}
+
+bool DroppedFile::setBuffer(BufferMode bufmode, int64 size)
+{
+ if (size < 0)
+ return false;
+
+ if (bufmode == BUFFER_NONE)
+ size = 0;
+
+ // If the file isn't open, we'll make sure the buffer values are set in
+ // DroppedFile::open.
+ if (!isOpen())
+ {
+ bufferMode = bufmode;
+ bufferSize = size;
+ return true;
+ }
+
+ int vbufmode;
+ switch (bufmode)
+ {
+ case File::BUFFER_NONE:
+ default:
+ vbufmode = _IONBF;
+ break;
+ case File::BUFFER_LINE:
+ vbufmode = _IOLBF;
+ break;
+ case File::BUFFER_FULL:
+ vbufmode = _IOFBF;
+ break;
+ }
+
+ if (setvbuf(file, nullptr, vbufmode, (size_t) size) != 0)
+ return false;
+
+ bufferMode = bufmode;
+ bufferSize = size;
+
+ return true;
+}
+
+File::BufferMode DroppedFile::getBuffer(int64 &size) const
+{
+ size = bufferSize;
+ return bufferMode;
+}
+
+const std::string &DroppedFile::getFilename() const
+{
+ return filename;
+}
+
+File::Mode DroppedFile::getMode() const
+{
+ return mode;
+}
+
+const char *DroppedFile::getModeString(Mode mode)
+{
+ switch (mode)
+ {
+ case File::MODE_CLOSED:
+ default:
+ return "c";
+ case File::MODE_READ:
+ return "rb";
+ case File::MODE_WRITE:
+ return "wb";
+ case File::MODE_APPEND:
+ return "ab";
+ }
+}
+
+} // filesystem
+} // love
diff --git a/src/modules/filesystem/DroppedFile.h b/src/modules/filesystem/DroppedFile.h
new file mode 100644
index 000000000..50cacda83
--- /dev/null
+++ b/src/modules/filesystem/DroppedFile.h
@@ -0,0 +1,83 @@
+/**
+ * Copyright (c) 2006-2014 LOVE Development Team
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ **/
+
+#ifndef LOVE_FILESYSTEM_DROPPED_FILE_H
+#define LOVE_FILESYSTEM_DROPPED_FILE_H
+
+// LOVE
+#include "common/config.h"
+#include "File.h"
+
+// C
+#include
+
+namespace love
+{
+namespace filesystem
+{
+
+/**
+ * File which is created when a user drags and drops an actual file onto the
+ * LOVE game. Uses C's stdio. Filenames are system-dependent full paths.
+ **/
+class DroppedFile : public File
+{
+public:
+
+ DroppedFile(const std::string &filename);
+ virtual ~DroppedFile();
+
+ // Implements File.
+ using File::read;
+ using File::write;
+ bool open(Mode mode);
+ bool close();
+ bool isOpen() const;
+ int64 getSize();
+ int64 read(void *dst, int64 size);
+ bool write(const void *data, int64 size);
+ bool flush();
+ bool eof();
+ int64 tell();
+ bool seek(uint64 pos);
+ bool setBuffer(BufferMode bufmode, int64 size);
+ BufferMode getBuffer(int64 &size) const;
+ Mode getMode() const;
+ const std::string &getFilename() const;
+
+private:
+
+ static const char *getModeString(Mode mode);
+
+ std::string filename;
+
+ FILE *file;
+
+ Mode mode;
+
+ BufferMode bufferMode;
+ int64 bufferSize;
+
+}; // DroppedFile
+
+} // filesystem
+} // love
+
+#endif // LOVE_FILESYSTEM_DROPPED_FILE_H
diff --git a/src/modules/filesystem/File.cpp b/src/modules/filesystem/File.cpp
index ef20621d7..105e52f95 100644
--- a/src/modules/filesystem/File.cpp
+++ b/src/modules/filesystem/File.cpp
@@ -29,6 +29,68 @@ File::~File()
{
}
+FileData *File::read(int64 size)
+{
+ bool isopen = isOpen();
+
+ if (!isopen && !open(MODE_READ))
+ throw love::Exception("Could not read file %s.", getFilename().c_str());
+
+ int64 max = getSize();
+ int64 cur = tell();
+ size = (size == ALL) ? max : size;
+
+ if (size < 0)
+ throw love::Exception("Invalid read size.");
+
+ // Clamping because the file offset may be in a weird position.
+ if (cur < 0)
+ cur = 0;
+ else if (cur > max)
+ cur = max;
+
+ if (cur + size > max)
+ size = max - cur;
+
+ FileData *fileData = new FileData(size, getFilename());
+ int64 bytesRead = read(fileData->getData(), size);
+
+ if (bytesRead < 0 || (bytesRead == 0 && bytesRead != size))
+ {
+ delete fileData;
+ throw love::Exception("Could not read from file.");
+ }
+
+ if (bytesRead < size)
+ {
+ FileData *tmpFileData = new FileData(bytesRead, getFilename());
+ memcpy(tmpFileData->getData(), fileData->getData(), (size_t) bytesRead);
+ fileData->release();
+ fileData = tmpFileData;
+ }
+
+ if (!isopen)
+ close();
+
+ return fileData;
+}
+
+bool File::write(const Data *data, int64 size)
+{
+ return write(data->getData(), (size == ALL) ? data->getSize() : size);
+}
+
+std::string File::getExtension() const
+{
+ const std::string &filename = getFilename();
+ std::string::size_type idx = filename.rfind('.');
+
+ if (idx != std::string::npos)
+ return filename.substr(idx+1);
+ else
+ return std::string();
+}
+
bool File::getConstant(const char *in, Mode &out)
{
return modes.find(in, out);
@@ -51,10 +113,10 @@ bool File::getConstant(BufferMode in, const char *&out)
StringMap::Entry File::modeEntries[] =
{
- {"c", File::CLOSED},
- {"r", File::READ},
- {"w", File::WRITE},
- {"a", File::APPEND},
+ {"c", File::MODE_CLOSED},
+ {"r", File::MODE_READ},
+ {"w", File::MODE_WRITE},
+ {"a", File::MODE_APPEND},
};
StringMap File::modes(File::modeEntries, sizeof(File::modeEntries));
diff --git a/src/modules/filesystem/File.h b/src/modules/filesystem/File.h
index e0be859e4..d46e13727 100644
--- a/src/modules/filesystem/File.h
+++ b/src/modules/filesystem/File.h
@@ -49,10 +49,10 @@ public:
**/
enum Mode
{
- CLOSED,
- READ,
- WRITE,
- APPEND,
+ MODE_CLOSED,
+ MODE_READ,
+ MODE_WRITE,
+ MODE_APPEND,
MODE_MAX_ENUM
};
@@ -77,7 +77,7 @@ public:
/**
* Opens the file in a certain mode.
*
- * @param mode READ, WRITE, APPEND.
+ * @param mode MODE_READ, MODE_WRITE, MODE_APPEND.
* @return True if successful, false otherwise.
**/
virtual bool open(Mode mode) = 0;
@@ -107,7 +107,7 @@ public:
* @param size The number of bytes to attempt reading, or -1 for EOF.
* @return A newly allocated Data object.
**/
- virtual FileData *read(int64 size = ALL) = 0;
+ virtual FileData *read(int64 size = ALL);
/**
* Reads data into the destination buffer.
@@ -134,7 +134,7 @@ public:
* @param size The number of bytes to attempt writing, or -1 for everything.
* @return True of success, false otherwise.
**/
- virtual bool write(const Data *data, int64 size = ALL) = 0;
+ virtual bool write(const Data *data, int64 size = ALL);
/**
* Flushes the currently buffered file data to disk. Only applicable in
@@ -192,13 +192,13 @@ public:
* Gets the filename for this File, or empty string if none.
* @return The filename for this File.
**/
- virtual std::string getFilename() const = 0;
+ virtual const std::string &getFilename() const = 0;
/**
* Gets the file extension for this File, or empty string if none.
* @return The file extension for this File (without the dot).
**/
- virtual std::string getExtension() const = 0;
+ virtual std::string getExtension() const;
static bool getConstant(const char *in, Mode &out);
static bool getConstant(Mode in, const char *&out);
diff --git a/src/modules/filesystem/Filesystem.cpp b/src/modules/filesystem/Filesystem.cpp
new file mode 100644
index 000000000..4e5a538c1
--- /dev/null
+++ b/src/modules/filesystem/Filesystem.cpp
@@ -0,0 +1,62 @@
+/**
+ * Copyright (c) 2006-2014 LOVE Development Team
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ **/
+
+// LOVE
+#include "Filesystem.h"
+#include "common/utf8.h"
+
+// Assume POSIX or Visual Studio.
+#include
+#include
+
+namespace love
+{
+namespace filesystem
+{
+
+Filesystem::Filesystem()
+{
+}
+
+Filesystem::~Filesystem()
+{
+}
+
+bool Filesystem::isRealDirectory(const std::string &path) const
+{
+#ifdef LOVE_WINDOWS
+ // make sure non-ASCII paths work.
+ struct _stat buf;
+ if (_wstat(to_widestr(path).c_str(), &buf) != 0)
+ return false;
+
+ return (buf.st_mode & _S_IFDIR) == _S_IFDIR;
+#else
+ // Assume POSIX support...
+ struct stat buf;
+ if (stat(path.c_str(), &buf) != 0)
+ return false;
+
+ return S_ISDIR(buf.st_mode) != 0;
+#endif
+}
+
+} // filesystem
+} // love
diff --git a/src/modules/filesystem/Filesystem.h b/src/modules/filesystem/Filesystem.h
new file mode 100644
index 000000000..bba774472
--- /dev/null
+++ b/src/modules/filesystem/Filesystem.h
@@ -0,0 +1,261 @@
+/**
+ * Copyright (c) 2006-2014 LOVE Development Team
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ **/
+
+#ifndef LOVE_FILESYSTEM_FILESYSTEM_H
+#define LOVE_FILESYSTEM_FILESYSTEM_H
+
+// LOVE
+#include "common/config.h"
+#include "common/runtime.h"
+#include "common/Module.h"
+#include "common/int.h"
+#include "FileData.h"
+#include "File.h"
+
+// C++
+#include
+#include
+
+// In Windows, we would like to use "LOVE" as the
+// application folder, but in Linux, we like .love.
+#define LOVE_APPDATA_PREFIX ""
+#ifdef LOVE_WINDOWS
+# define LOVE_APPDATA_FOLDER "LOVE"
+# define LOVE_PATH_SEPARATOR "/"
+# define LOVE_MAX_PATH _MAX_PATH
+#else
+# ifdef LOVE_MACOSX
+# define LOVE_APPDATA_FOLDER "LOVE"
+# elif defined(LOVE_LINUX)
+# define LOVE_APPDATA_FOLDER "love"
+# else
+# define LOVE_APPDATA_PREFIX "."
+# define LOVE_APPDATA_FOLDER "love"
+# endif
+# define LOVE_PATH_SEPARATOR "/"
+# define LOVE_MAX_PATH MAXPATHLEN
+#endif
+
+namespace love
+{
+namespace filesystem
+{
+
+class Filesystem : public Module
+{
+public:
+
+ Filesystem();
+ virtual ~Filesystem();
+
+ // Implements Module.
+ virtual ModuleType getModuleType() const { return M_FILESYSTEM; }
+
+ virtual void init(const char *arg0) = 0;
+
+ virtual void setFused(bool fused) = 0;
+ virtual bool isFused() const = 0;
+
+ /**
+ * This sets up the save directory. If the
+ * it is already set up, nothing happens.
+ * @return True on success, false otherwise.
+ **/
+ virtual bool setupWriteDirectory() = 0;
+
+ /**
+ * Sets the name of the save folder.
+ * @param ident The name of the game. Will be used to
+ * to create the folder in the LOVE data folder.
+ **/
+ virtual bool setIdentity(const char *ident, bool appendToPath = false) = 0;
+ virtual const char *getIdentity() const = 0;
+
+ /**
+ * Sets the path to the game source.
+ * This can only be set once.
+ * @param source Path to a directory or a .love-file.
+ **/
+ virtual bool setSource(const char *source) = 0;
+
+ /**
+ * Gets the path to the game source.
+ * Returns a 0-length string if the source has not been set.
+ **/
+ virtual const char *getSource() const = 0;
+
+ virtual bool mount(const char *archive, const char *mountpoint, bool appendToPath = false) = 0;
+ virtual bool unmount(const char *archive) = 0;
+
+ /**
+ * Creates a new file.
+ **/
+ virtual File *newFile(const char *filename) const = 0;
+
+ /**
+ * Creates a new FileData object. Data will be copied.
+ * @param data Pointer to the data.
+ * @param size The size of the data.
+ * @param filename The full filename used to file type identification.
+ **/
+ virtual FileData *newFileData(void *data, unsigned int size, const char *filename) const = 0;
+
+ /**
+ * Creates a new FileData object from base64 data.
+ * @param b64 The base64 data.
+ **/
+ virtual FileData *newFileData(const char *b64, const char *filename) const = 0;
+
+ /**
+ * Gets the current working directory.
+ **/
+ virtual const char *getWorkingDirectory() = 0;
+
+ /**
+ * Gets the user home directory.
+ **/
+ virtual std::string getUserDirectory() = 0;
+
+ /**
+ * Gets the APPDATA directory. On Windows, this is the folder
+ * in the %APPDATA% enviroment variable. On Linux, this is the
+ * user home folder.
+ **/
+ virtual std::string getAppdataDirectory() = 0;
+
+ /**
+ * Gets the full path of the save folder.
+ **/
+ virtual const char *getSaveDirectory() = 0;
+
+ /**
+ * Gets the full path to the directory containing the game source.
+ * For example if the game source is C:\Games\mygame.love, this will return
+ * C:\Games.
+ **/
+ virtual std::string getSourceBaseDirectory() const = 0;
+
+ /**
+ * Gets the real directory path containing the file.
+ **/
+ virtual std::string getRealDirectory(const char *filename) const = 0;
+
+ /**
+ * Checks if a path is a directory.
+ * @param dir The directory name to check.
+ **/
+ virtual bool isDirectory(const char *dir) const = 0;
+
+ /**
+ * Checks if a filename exists.
+ * @param file The filename to check.
+ **/
+ virtual bool isFile(const char *file) const = 0;
+
+ /**
+ * Creates a directory. Write dir must be set.
+ * @param dir The directory to create.
+ **/
+ virtual bool createDirectory(const char *dir) = 0;
+
+ /**
+ * Removes a file (or directory).
+ * @param file The file or directory to remove.
+ **/
+ virtual bool remove(const char *file) = 0;
+
+ /**
+ * Reads data from a file.
+ * @param filename The name of the file to read from.
+ * @param size The size in bytes of the data to read.
+ **/
+ virtual FileData *read(const char *filename, int64 size = File::ALL) const = 0;
+
+ /**
+ * Write data to a file.
+ * @param filename The name of the file to write to.
+ * @param data The data to write.
+ * @param size The size in bytes of the data to write.
+ **/
+ virtual void write(const char *filename, const void *data, int64 size) const = 0;
+
+ /**
+ * Append data to a file, creating it if it doesn't exist.
+ * @param filename The name of the file to write to.
+ * @param data The data to append.
+ * @param size The size in bytes of the data to append.
+ **/
+ virtual void append(const char *filename, const void *data, int64 size) const = 0;
+
+ /**
+ * This "native" method returns a table of all
+ * files in a given directory.
+ **/
+ virtual int getDirectoryItems(lua_State *L) = 0;
+
+ /**
+ * Gets the last modification time of a file, in seconds
+ * since the Unix epoch.
+ * @param filename The name of the file.
+ **/
+ virtual int64 getLastModified(const char *filename) const = 0;
+
+ /**
+ * Gets the size of a file in bytes.
+ * @param filename The name of the file.
+ **/
+ virtual int64 getSize(const char *filename) const = 0;
+
+ /**
+ * Enable or disable symbolic link support in love.filesystem.
+ **/
+ virtual void setSymlinksEnabled(bool enable) = 0;
+
+ /**
+ * Gets whether symbolic link support is enabled.
+ **/
+ virtual bool areSymlinksEnabled() const = 0;
+
+ /**
+ * Gets whether a filepath is actually a symlink.
+ * Always returns false if symlinks are not enabled.
+ **/
+ virtual bool isSymlink(const char *filename) const = 0;
+
+ // Require path accessors
+ // Not const because it's R/W
+ virtual std::vector &getRequirePath() = 0;
+
+ /**
+ * Allows a full (OS-dependent) path to be used with Filesystem::mount.
+ **/
+ virtual void allowMountingForPath(const std::string &path) = 0;
+
+ /**
+ * Gets whether the given full (OS-dependent) path is a directory.
+ **/
+ virtual bool isRealDirectory(const std::string &path) const;
+
+}; // Filesystem
+
+} // filesystem
+} // love
+
+#endif // LOVE_FILESYSTEM_FILESYSTEM_H
diff --git a/src/modules/filesystem/physfs/File.cpp b/src/modules/filesystem/physfs/File.cpp
index be137c4b0..dbec8c6eb 100644
--- a/src/modules/filesystem/physfs/File.cpp
+++ b/src/modules/filesystem/physfs/File.cpp
@@ -39,8 +39,8 @@ namespace physfs
File::File(const std::string &filename)
: filename(filename)
- , file(0)
- , mode(CLOSED)
+ , file(nullptr)
+ , mode(MODE_CLOSED)
, bufferMode(BUFFER_NONE)
, bufferSize(0)
{
@@ -48,25 +48,25 @@ File::File(const std::string &filename)
File::~File()
{
- if (mode != CLOSED)
+ if (mode != MODE_CLOSED)
close();
}
bool File::open(Mode mode)
{
- if (mode == CLOSED)
+ if (mode == MODE_CLOSED)
return true;
// File must exist if read mode.
- if ((mode == READ) && !PHYSFS_exists(filename.c_str()))
+ if ((mode == MODE_READ) && !PHYSFS_exists(filename.c_str()))
throw love::Exception("Could not open file %s. Does not exist.", filename.c_str());
// Check whether the write directory is set.
- if ((mode == APPEND || mode == WRITE) && (PHYSFS_getWriteDir() == 0) && !hack_setupWriteDirectory())
+ if ((mode == MODE_APPEND || mode == MODE_WRITE) && (PHYSFS_getWriteDir() == 0) && !hack_setupWriteDirectory())
throw love::Exception("Could not set write directory.");
// File already open?
- if (file != 0)
+ if (file != nullptr)
return false;
PHYSFS_getLastError(); // Clear the error buffer.
@@ -74,13 +74,13 @@ bool File::open(Mode mode)
switch (mode)
{
- case READ:
+ case MODE_READ:
handle = PHYSFS_openRead(filename.c_str());
break;
- case APPEND:
+ case MODE_APPEND:
handle = PHYSFS_openAppend(filename.c_str());
break;
- case WRITE:
+ case MODE_WRITE:
handle = PHYSFS_openWrite(filename.c_str());
break;
default:
@@ -99,94 +99,50 @@ bool File::open(Mode mode)
this->mode = mode;
- if (file != 0 && !setBuffer(bufferMode, bufferSize))
+ if (file != nullptr && !setBuffer(bufferMode, bufferSize))
{
// Revert to buffer defaults if we don't successfully set the buffer.
bufferMode = BUFFER_NONE;
bufferSize = 0;
}
- return (file != 0);
+ return (file != nullptr);
}
bool File::close()
{
- if (!PHYSFS_close(file))
+ if (file == nullptr || !PHYSFS_close(file))
return false;
- mode = CLOSED;
- file = 0;
+
+ mode = MODE_CLOSED;
+ file = nullptr;
+
return true;
}
bool File::isOpen() const
{
- return mode != CLOSED && file != 0;
+ return mode != MODE_CLOSED && file != nullptr;
}
int64 File::getSize()
{
// If the file is closed, open it to
// check the size.
- if (file == 0)
+ if (file == nullptr)
{
- open(READ);
- int64 size = (int64)PHYSFS_fileLength(file);
+ open(MODE_READ);
+ int64 size = (int64) PHYSFS_fileLength(file);
close();
return size;
}
- return (int64)PHYSFS_fileLength(file);
-}
-
-
-FileData *File::read(int64 size)
-{
- bool isOpen = (file != 0);
-
- if (!isOpen && !open(READ))
- throw love::Exception("Could not read file %s.", filename.c_str());
-
- int64 max = getSize();
- int64 cur = tell();
- size = (size == ALL) ? max : size;
-
- if (size < 0)
- throw love::Exception("Invalid read size.");
-
- // Clamping because the file offset may be in a weird position.
- if (cur < 0)
- cur = 0;
- else if (cur > max)
- cur = max;
-
- if (cur + size > max)
- size = max - cur;
-
- FileData *fileData = new FileData(size, getFilename());
- int64 bytesRead = read(fileData->getData(), size);
-
- if (bytesRead < 0 || (bytesRead == 0 && bytesRead != size))
- {
- delete fileData;
- throw love::Exception("Could not read from file.");
- }
- if (bytesRead < size)
- {
- FileData *tmpFileData = new FileData(bytesRead, getFilename());
- memcpy(tmpFileData->getData(), fileData->getData(), (size_t) bytesRead);
- delete fileData;
- fileData = tmpFileData;
- }
-
- if (!isOpen)
- close();
-
- return fileData;
+ return (int64) PHYSFS_fileLength(file);
}
int64 File::read(void *dst, int64 size)
{
- if (!file || mode != READ)
+ if (!file || mode != MODE_READ)
throw love::Exception("File is not opened for reading.");
int64 max = (int64)PHYSFS_fileLength(file);
@@ -205,7 +161,7 @@ int64 File::read(void *dst, int64 size)
bool File::write(const void *data, int64 size)
{
- if (!file || (mode != WRITE && mode != APPEND))
+ if (!file || (mode != MODE_WRITE && mode != MODE_APPEND))
throw love::Exception("File is not opened for writing.");
// Another clamp, for the time being.
@@ -215,7 +171,7 @@ bool File::write(const void *data, int64 size)
throw love::Exception("Invalid write size.");
// Try to write.
- int64 written = static_cast(PHYSFS_write(file, data, 1, (PHYSFS_uint32) size));
+ int64 written = (int64) PHYSFS_write(file, data, 1, (PHYSFS_uint32) size);
// Check that correct amount of data was written.
if (written != size)
@@ -231,14 +187,9 @@ bool File::write(const void *data, int64 size)
return true;
}
-bool File::write(const Data *data, int64 size)
-{
- return write(data->getData(), (size == ALL) ? data->getSize() : size);
-}
-
bool File::flush()
{
- if (!file || (mode != WRITE && mode != APPEND))
+ if (!file || (mode != MODE_WRITE && mode != MODE_APPEND))
throw love::Exception("File is not opened for writing.");
return PHYSFS_flush(file) != 0;
@@ -263,14 +214,12 @@ inline bool test_eof(File *, PHYSFS_File *file)
bool File::eof()
{
- if (file == 0 || test_eof(this, file))
- return true;
- return false;
+ return file == nullptr || test_eof(this, file);
}
int64 File::tell()
{
- if (file == 0)
+ if (file == nullptr)
return -1;
return (int64) PHYSFS_tell(file);
@@ -278,23 +227,17 @@ int64 File::tell()
bool File::seek(uint64 pos)
{
- if (file == 0)
- return false;
-
- if (!PHYSFS_seek(file, (PHYSFS_uint64) pos))
- return false;
- return true;
+ return file != nullptr && PHYSFS_seek(file, (PHYSFS_uint64) pos) != 0;
}
bool File::setBuffer(BufferMode bufmode, int64 size)
{
- // No negativity allowed!
if (size < 0)
return false;
// If the file isn't open, we'll make sure the buffer values are set in
// File::open.
- if (file == 0 || mode == CLOSED)
+ if (!isOpen())
{
bufferMode = bufmode;
bufferSize = size;
@@ -331,21 +274,11 @@ File::BufferMode File::getBuffer(int64 &size) const
return bufferMode;
}
-std::string File::getFilename() const
+const std::string &File::getFilename() const
{
return filename;
}
-std::string File::getExtension() const
-{
- std::string::size_type idx = filename.rfind('.');
-
- if (idx != std::string::npos)
- return filename.substr(idx+1);
- else
- return std::string();
-}
-
filesystem::File::Mode File::getMode() const
{
return mode;
diff --git a/src/modules/filesystem/physfs/File.h b/src/modules/filesystem/physfs/File.h
index a3fe33792..13cd26925 100644
--- a/src/modules/filesystem/physfs/File.h
+++ b/src/modules/filesystem/physfs/File.h
@@ -54,14 +54,14 @@ public:
virtual ~File();
// Implements love::filesystem::File.
+ using love::filesystem::File::read;
+ using love::filesystem::File::write;
bool open(Mode mode);
bool close();
bool isOpen() const;
int64 getSize();
- FileData *read(int64 size = ALL);
- int64 read(void *dst, int64 size);
+ virtual int64 read(void *dst, int64 size);
bool write(const void *data, int64 size);
- bool write(const Data *data, int64 size = ALL);
bool flush();
bool eof();
int64 tell();
@@ -69,8 +69,7 @@ public:
bool setBuffer(BufferMode bufmode, int64 size);
BufferMode getBuffer(int64 &size) const;
Mode getMode() const;
- std::string getFilename() const;
- std::string getExtension() const;
+ const std::string &getFilename() const;
private:
diff --git a/src/modules/filesystem/physfs/Filesystem.cpp b/src/modules/filesystem/physfs/Filesystem.cpp
index cf395aec7..f51807d33 100644
--- a/src/modules/filesystem/physfs/Filesystem.cpp
+++ b/src/modules/filesystem/physfs/Filesystem.cpp
@@ -18,8 +18,6 @@
* 3. This notice may not be removed or altered from any source distribution.
**/
-#include "common/config.h"
-
#include
#include
@@ -27,6 +25,25 @@
#include "common/b64.h"
#include "Filesystem.h"
+#include "File.h"
+
+// PhysFS
+#ifdef LOVE_MACOSX_USE_FRAMEWORKS
+#include
+#else
+#include
+#endif
+
+// For great CWD. (Current Working Directory)
+// Using this instead of boost::filesystem which totally
+// cramped our style.
+#ifdef LOVE_WINDOWS
+# include
+# include
+#else
+# include
+# include
+#endif
namespace
{
@@ -73,8 +90,7 @@ namespace physfs
{
Filesystem::Filesystem()
- : initialized(false)
- , fused(false)
+ : fused(false)
, fusedSet(false)
{
requirePath = {"?.lua", "?/init.lua"};
@@ -82,7 +98,7 @@ Filesystem::Filesystem()
Filesystem::~Filesystem()
{
- if (initialized)
+ if (PHYSFS_isInit())
PHYSFS_deinit();
}
@@ -95,7 +111,6 @@ void Filesystem::init(const char *arg0)
{
if (!PHYSFS_init(arg0))
throw Exception(PHYSFS_getLastError());
- initialized = true;
}
void Filesystem::setFused(bool fused)
@@ -115,7 +130,7 @@ bool Filesystem::isFused() const
bool Filesystem::setIdentity(const char *ident, bool appendToPath)
{
- if (!initialized)
+ if (!PHYSFS_isInit())
return false;
std::string old_save_path = save_path_full;
@@ -164,7 +179,7 @@ const char *Filesystem::getIdentity() const
bool Filesystem::setSource(const char *source)
{
- if (!initialized)
+ if (!PHYSFS_isInit())
return false;
// Check whether directory is already set.
@@ -188,7 +203,7 @@ const char *Filesystem::getSource() const
bool Filesystem::setupWriteDirectory()
{
- if (!initialized)
+ if (!PHYSFS_isInit())
return false;
// These must all be set.
@@ -244,13 +259,20 @@ bool Filesystem::setupWriteDirectory()
bool Filesystem::mount(const char *archive, const char *mountpoint, bool appendToPath)
{
- if (!initialized || !archive)
+ if (!PHYSFS_isInit() || !archive)
return false;
std::string realPath;
std::string sourceBase = getSourceBaseDirectory();
- if (isFused() && sourceBase.compare(archive) == 0)
+ // Check whether the given archive path is in the list of allowed full paths.
+ auto it = std::find(allowedMountPaths.begin(), allowedMountPaths.end(), archive);
+
+ if (it != allowedMountPaths.end())
+ {
+ realPath = *it;
+ }
+ else if (isFused() && sourceBase.compare(archive) == 0)
{
// Special case: if the game is fused and the archive is the source's
// base directory, mount it even though it's outside of the save dir.
@@ -285,7 +307,7 @@ bool Filesystem::mount(const char *archive, const char *mountpoint, bool appendT
bool Filesystem::unmount(const char *archive)
{
- if (!initialized || !archive)
+ if (!PHYSFS_isInit() || !archive)
return false;
std::string realPath;
@@ -319,7 +341,7 @@ bool Filesystem::unmount(const char *archive)
return PHYSFS_removeFromSearchPath(realPath.c_str());
}
-File *Filesystem::newFile(const char *filename) const
+love::filesystem::File *Filesystem::newFile(const char *filename) const
{
return new File(filename);
}
@@ -478,7 +500,7 @@ FileData *Filesystem::read(const char *filename, int64 size) const
{
File file(filename);
- file.open(File::READ);
+ file.open(File::MODE_READ);
// close() is called in the File destructor.
return file.read(size);
@@ -488,7 +510,7 @@ void Filesystem::write(const char *filename, const void *data, int64 size) const
{
File file(filename);
- file.open(File::WRITE);
+ file.open(File::MODE_WRITE);
// close() is called in the File destructor.
if (!file.write(data, size))
@@ -499,7 +521,7 @@ void Filesystem::append(const char *filename, const void *data, int64 size) cons
{
File file(filename);
- file.open(File::APPEND);
+ file.open(File::MODE_APPEND);
// close() is called in the File destructor.
if (!file.write(data, size))
@@ -538,108 +560,6 @@ int Filesystem::getDirectoryItems(lua_State *L)
return 1;
}
-int Filesystem::lines_i(lua_State *L)
-{
- const int bufsize = 1024;
- char buf[bufsize];
- int linesize = 0;
- bool newline = false;
-
- File *file = luax_checktype(L, lua_upvalueindex(1), "File", FILESYSTEM_FILE_T);
-
- // Only accept read mode at this point.
- if (file->getMode() != File::READ)
- return luaL_error(L, "File needs to stay in read mode.");
-
- int64 pos = file->tell();
- int64 userpos = -1;
-
- if (lua_isnoneornil(L, lua_upvalueindex(2)) == 0)
- {
- // User may have changed the file position.
- userpos = pos;
- pos = (int64) lua_tonumber(L, lua_upvalueindex(2));
- if (userpos != pos)
- file->seek(pos);
- }
-
- while (!newline && !file->eof())
- {
- // This 64-bit to 32-bit integer cast should be safe as it never exceeds bufsize.
- int read = (int) file->read(buf, bufsize);
- if (read < 0)
- return luaL_error(L, "Could not read from file.");
-
- linesize += read;
-
- for (int i = 0; i < read; i++)
- {
- if (buf[i] == '\n')
- {
- linesize -= read - i;
- newline = true;
- break;
- }
- }
- }
-
- if (newline || (file->eof() && linesize > 0))
- {
- if (linesize < bufsize)
- {
- // We have the line in the buffer on the stack. No 'new' and 'read' needed.
- lua_pushlstring(L, buf, linesize > 0 && buf[linesize - 1] == '\r' ? linesize - 1 : linesize);
- if (userpos < 0)
- file->seek(pos + linesize + 1);
- }
- else
- {
- char *str = 0;
- try
- {
- str = new char[linesize + 1];
- }
- catch(std::bad_alloc &)
- {
- // Can't lua_error (longjmp) in exception handlers.
- }
-
- if (!str)
- return luaL_error(L, "Out of memory.");
-
- file->seek(pos);
-
- // Read the \n anyway and save us a call to seek.
- if (file->read(str, linesize + 1) == -1)
- {
- delete [] str;
- return luaL_error(L, "Could not read from file.");
- }
-
- lua_pushlstring(L, str, str[linesize - 1] == '\r' ? linesize - 1 : linesize);
- delete [] str;
- }
-
- if (userpos >= 0)
- {
- // Save new position in upvalue.
- lua_pushnumber(L, (lua_Number)(pos + linesize + 1));
- lua_replace(L, lua_upvalueindex(2));
- file->seek(userpos);
- }
-
- return 1;
- }
-
- // EOF reached.
- if (userpos >= 0 && luax_toboolean(L, lua_upvalueindex(3)))
- file->seek(userpos);
- else
- file->close();
-
- return 0;
-}
-
int64 Filesystem::getLastModified(const char *filename) const
{
PHYSFS_sint64 time = PHYSFS_getLastModTime(filename);
@@ -677,6 +597,12 @@ std::vector &Filesystem::getRequirePath()
return requirePath;
}
+void Filesystem::allowMountingForPath(const std::string &path)
+{
+ if (std::find(allowedMountPaths.begin(), allowedMountPaths.end(), path) == allowedMountPaths.end())
+ allowedMountPaths.push_back(path);
+}
+
} // physfs
} // filesystem
} // love
diff --git a/src/modules/filesystem/physfs/Filesystem.h b/src/modules/filesystem/physfs/Filesystem.h
index 647f15fe2..82ff6b4f4 100644
--- a/src/modules/filesystem/physfs/Filesystem.h
+++ b/src/modules/filesystem/physfs/Filesystem.h
@@ -24,47 +24,9 @@
// STD
#include
#include
-#include
-#include
// LOVE
-#include "common/Module.h"
-#include "common/config.h"
-#include "common/int.h"
-#include "common/runtime.h"
-#include "filesystem/FileData.h"
-#include "File.h"
-
-// For great CWD. (Current Working Directory)
-// Using this instead of boost::filesystem which totally
-// cramped our style.
-#ifdef LOVE_WINDOWS
-# include
-# include
-#else
-# include
-# include
-#endif
-
-// In Windows, we would like to use "LOVE" as the
-// application folder, but in Linux, we like .love.
-#define LOVE_APPDATA_PREFIX ""
-#ifdef LOVE_WINDOWS
-# define LOVE_APPDATA_FOLDER "LOVE"
-# define LOVE_PATH_SEPARATOR "/"
-# define LOVE_MAX_PATH _MAX_PATH
-#else
-# ifdef LOVE_MACOSX
-# define LOVE_APPDATA_FOLDER "LOVE"
-# elif defined(LOVE_LINUX)
-# define LOVE_APPDATA_FOLDER "love"
-# else
-# define LOVE_APPDATA_PREFIX "."
-# define LOVE_APPDATA_FOLDER "love"
-# endif
-# define LOVE_PATH_SEPARATOR "/"
-# define LOVE_MAX_PATH MAXPATHLEN
-#endif
+#include "filesystem/Filesystem.h"
namespace love
{
@@ -73,7 +35,7 @@ namespace filesystem
namespace physfs
{
-class Filesystem : public Module
+class Filesystem : public love::filesystem::Filesystem
{
public:
@@ -81,7 +43,6 @@ public:
virtual ~Filesystem();
// Implements Module.
- virtual ModuleType getModuleType() const { return M_FILESYSTEM; }
const char *getName() const;
void init(const char *arg0);
@@ -89,183 +50,55 @@ public:
void setFused(bool fused);
bool isFused() const;
- /**
- * This sets up the save directory. If the
- * it is already set up, nothing happens.
- * @return True on success, false otherwise.
- **/
bool setupWriteDirectory();
- /**
- * Sets the name of the save folder.
- * @param ident The name of the game. Will be used to
- * to create the folder in the LOVE data folder.
- **/
bool setIdentity(const char *ident, bool appendToPath = false);
const char *getIdentity() const;
- /**
- * Sets the path to the game source.
- * This can only be set once.
- * @param source Path to a directory or a .love-file.
- **/
bool setSource(const char *source);
- /**
- * Gets the path to the game source.
- * Returns a 0-length string if the source has not been set.
- **/
const char *getSource() const;
bool mount(const char *archive, const char *mountpoint, bool appendToPath = false);
bool unmount(const char *archive);
- /**
- * Creates a new file.
- **/
File *newFile(const char *filename) const;
- /**
- * Creates a new FileData object. Data will be copied.
- * @param data Pointer to the data.
- * @param size The size of the data.
- * @param filename The full filename used to file type identification.
- **/
FileData *newFileData(void *data, unsigned int size, const char *filename) const;
-
- /**
- * Creates a new FileData object from base64 data.
- * @param b64 The base64 data.
- **/
FileData *newFileData(const char *b64, const char *filename) const;
- /**
- * Gets the current working directory.
- **/
const char *getWorkingDirectory();
-
- /**
- * Gets the user home directory.
- **/
std::string getUserDirectory();
-
- /**
- * Gets the APPDATA directory. On Windows, this is the folder
- * in the %APPDATA% enviroment variable. On Linux, this is the
- * user home folder.
- **/
std::string getAppdataDirectory();
-
- /**
- * Gets the full path of the save folder.
- **/
const char *getSaveDirectory();
-
- /**
- * Gets the full path to the directory containing the game source.
- * For example if the game source is C:\Games\mygame.love, this will return
- * C:\Games.
- **/
std::string getSourceBaseDirectory() const;
- /**
- * Gets the real directory path containing the file.
- **/
std::string getRealDirectory(const char *filename) const;
- /**
- * Checks if a path is a directory.
- * @param dir The directory name to check.
- **/
bool isDirectory(const char *dir) const;
-
- /**
- * Checks if a filename exists.
- * @param file The filename to check.
- **/
bool isFile(const char *file) const;
- /**
- * Creates a directory. Write dir must be set.
- * @param dir The directory to create.
- **/
bool createDirectory(const char *dir);
- /**
- * Removes a file (or directory).
- * @param file The file or directory to remove.
- **/
bool remove(const char *file);
- /**
- * Reads data from a file.
- * @param filename The name of the file to read from.
- * @param size The size in bytes of the data to read.
- **/
FileData *read(const char *filename, int64 size = File::ALL) const;
-
- /**
- * Write data to a file.
- * @param filename The name of the file to write to.
- * @param data The data to write.
- * @param size The size in bytes of the data to write.
- **/
void write(const char *filename, const void *data, int64 size) const;
-
- /**
- * Append data to a file, creating it if it doesn't exist.
- * @param filename The name of the file to write to.
- * @param data The data to append.
- * @param size The size in bytes of the data to append.
- **/
void append(const char *filename, const void *data, int64 size) const;
- /**
- * This "native" method returns a table of all
- * files in a given directory.
- **/
int getDirectoryItems(lua_State *L);
- /**
- * Gets the last modification time of a file, in seconds
- * since the Unix epoch.
- * @param filename The name of the file.
- **/
int64 getLastModified(const char *filename) const;
-
- /**
- * Gets the size of a file in bytes.
- * @param filename The name of the file.
- **/
int64 getSize(const char *filename) const;
- /**
- * Enable or disable symbolic link support in love.filesystem.
- **/
void setSymlinksEnabled(bool enable);
-
- /**
- * Gets whether symbolic link support is enabled.
- **/
bool areSymlinksEnabled() const;
-
- /**
- * Gets whether a filepath is actually a symlink.
- * Always returns false if symlinks are not enabled.
- **/
bool isSymlink(const char *filename) const;
- /**
- * Text file line-reading iterator function used and
- * pushed on the Lua stack by love.filesystem.lines
- * and File:lines.
- **/
- static int lines_i(lua_State *L);
-
- // Require path accessors
- // Not const because it's R/W
std::vector &getRequirePath();
+ void allowMountingForPath(const std::string &path);
+
private:
// Contains the current working directory (UTF8).
@@ -286,9 +119,6 @@ private:
// The full path to the source of the game.
std::string game_source;
- // Workaround for machines without PhysFS 2.0
- bool initialized;
-
// Allow saving outside of the LOVE_APPDATA_FOLDER
// for release 'builds'
bool fused;
@@ -297,6 +127,8 @@ private:
// Search path for require
std::vector requirePath;
+ std::vector allowedMountPaths;
+
}; // Filesystem
} // physfs
diff --git a/src/modules/filesystem/wrap_DroppedFile.cpp b/src/modules/filesystem/wrap_DroppedFile.cpp
new file mode 100644
index 000000000..9be0312e2
--- /dev/null
+++ b/src/modules/filesystem/wrap_DroppedFile.cpp
@@ -0,0 +1,62 @@
+/**
+ * Copyright (c) 2006-2014 LOVE Development Team
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ **/
+
+#include "wrap_DroppedFile.h"
+#include "wrap_File.h"
+
+namespace love
+{
+namespace filesystem
+{
+
+DroppedFile *luax_checkdroppedfile(lua_State *L, int idx)
+{
+ return luax_checktype(L, idx, "DroppedFile", FILESYSTEM_DROPPED_FILE_T);
+}
+
+static const luaL_Reg functions[] =
+{
+ // Inherits from File.
+ { "getSize", w_File_getSize },
+ { "open", w_File_open },
+ { "close", w_File_close },
+ { "isOpen", w_File_isOpen },
+ { "read", w_File_read },
+ { "write", w_File_write },
+ { "flush", w_File_flush },
+ { "eof", w_File_eof },
+ { "tell", w_File_tell },
+ { "seek", w_File_seek },
+ { "lines", w_File_lines },
+ { "setBuffer", w_File_setBuffer },
+ { "getBuffer", w_File_getBuffer },
+ { "getMode", w_File_getMode },
+ { "getFilename", w_File_getFilename },
+ { "getExtension", w_File_getExtension },
+ { 0, 0 }
+};
+
+extern "C" int luaopen_droppedfile(lua_State *L)
+{
+ return luax_register_type(L, "DroppedFile", functions);
+}
+
+} // filesystem
+} // love
diff --git a/src/modules/filesystem/wrap_DroppedFile.h b/src/modules/filesystem/wrap_DroppedFile.h
new file mode 100644
index 000000000..8a6516fb1
--- /dev/null
+++ b/src/modules/filesystem/wrap_DroppedFile.h
@@ -0,0 +1,39 @@
+/**
+ * Copyright (c) 2006-2014 LOVE Development Team
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ **/
+
+#ifndef LOVE_FILESYSTEM_WRAP_DROPPED_FILE_H
+#define LOVE_FILESYSTEM_WRAP_DROPPED_FILE_H
+
+// LOVE
+#include "common/runtime.h"
+#include "DroppedFile.h"
+
+namespace love
+{
+namespace filesystem
+{
+
+DroppedFile *luax_checkdroppedfile(lua_State *L, int idx);
+extern "C" int luaopen_droppedfile(lua_State *L);
+
+} // filesystem
+} // love
+
+#endif // LOVE_FILESYSTEM_WRAP_DROPPED_FILE_H
diff --git a/src/modules/filesystem/wrap_File.cpp b/src/modules/filesystem/wrap_File.cpp
index dda6da74a..a467625f5 100644
--- a/src/modules/filesystem/wrap_File.cpp
+++ b/src/modules/filesystem/wrap_File.cpp
@@ -20,8 +20,6 @@
#include "wrap_File.h"
-#include "physfs/Filesystem.h"
-
#include "common/Data.h"
#include "common/Exception.h"
#include "common/int.h"
@@ -223,26 +221,128 @@ int w_File_seek(lua_State *L)
return 1;
}
+int w_File_lines_i(lua_State *L)
+{
+ const int bufsize = 1024;
+ char buf[bufsize];
+ int linesize = 0;
+ bool newline = false;
+
+ File *file = luax_checktype(L, lua_upvalueindex(1), "File", FILESYSTEM_FILE_T);
+
+ // Only accept read mode at this point.
+ if (file->getMode() != File::MODE_READ)
+ return luaL_error(L, "File needs to stay in read mode.");
+
+ int64 pos = file->tell();
+ int64 userpos = -1;
+
+ if (lua_isnoneornil(L, lua_upvalueindex(2)) == 0)
+ {
+ // User may have changed the file position.
+ userpos = pos;
+ pos = (int64) lua_tonumber(L, lua_upvalueindex(2));
+ if (userpos != pos)
+ file->seek(pos);
+ }
+
+ while (!newline && !file->eof())
+ {
+ // This 64-bit to 32-bit integer cast should be safe as it never exceeds bufsize.
+ int read = (int) file->read(buf, bufsize);
+ if (read < 0)
+ return luaL_error(L, "Could not read from file.");
+
+ linesize += read;
+
+ for (int i = 0; i < read; i++)
+ {
+ if (buf[i] == '\n')
+ {
+ linesize -= read - i;
+ newline = true;
+ break;
+ }
+ }
+ }
+
+ if (newline || (file->eof() && linesize > 0))
+ {
+ if (linesize < bufsize)
+ {
+ // We have the line in the buffer on the stack. No 'new' and 'read' needed.
+ lua_pushlstring(L, buf, linesize > 0 && buf[linesize - 1] == '\r' ? linesize - 1 : linesize);
+ if (userpos < 0)
+ file->seek(pos + linesize + 1);
+ }
+ else
+ {
+ char *str = 0;
+ try
+ {
+ str = new char[linesize + 1];
+ }
+ catch(std::bad_alloc &)
+ {
+ // Can't lua_error (longjmp) in exception handlers.
+ }
+
+ if (!str)
+ return luaL_error(L, "Out of memory.");
+
+ file->seek(pos);
+
+ // Read the \n anyway and save us a call to seek.
+ if (file->read(str, linesize + 1) == -1)
+ {
+ delete [] str;
+ return luaL_error(L, "Could not read from file.");
+ }
+
+ lua_pushlstring(L, str, str[linesize - 1] == '\r' ? linesize - 1 : linesize);
+ delete [] str;
+ }
+
+ if (userpos >= 0)
+ {
+ // Save new position in upvalue.
+ lua_pushnumber(L, (lua_Number)(pos + linesize + 1));
+ lua_replace(L, lua_upvalueindex(2));
+ file->seek(userpos);
+ }
+
+ return 1;
+ }
+
+ // EOF reached.
+ if (userpos >= 0 && luax_toboolean(L, lua_upvalueindex(3)))
+ file->seek(userpos);
+ else
+ file->close();
+
+ return 0;
+}
+
int w_File_lines(lua_State *L)
{
File *file = luax_checkfile(L, 1);
lua_pushnumber(L, 0); // File position.
- luax_pushboolean(L, file->getMode() != File::CLOSED); // Save current file mode.
+ luax_pushboolean(L, file->getMode() != File::MODE_CLOSED); // Save current file mode.
- if (file->getMode() != File::READ)
+ if (file->getMode() != File::MODE_READ)
{
- if (file->getMode() != File::CLOSED)
+ if (file->getMode() != File::MODE_CLOSED)
file->close();
bool success = false;
- luax_catchexcept(L, [&](){ success = file->open(File::READ); });
+ luax_catchexcept(L, [&](){ success = file->open(File::MODE_READ); });
if (!success)
return luaL_error(L, "Could not open file.");
}
- lua_pushcclosure(L, physfs::Filesystem::lines_i, 3);
+ lua_pushcclosure(L, w_File_lines_i, 3);
return 1;
}
@@ -299,6 +399,20 @@ int w_File_getMode(lua_State *L)
return 1;
}
+int w_File_getFilename(lua_State *L)
+{
+ File *file = luax_checkfile(L, 1);
+ luax_pushstring(L, file->getFilename());
+ return 1;
+}
+
+int w_File_getExtension(lua_State *L)
+{
+ File *file = luax_checkfile(L, 1);
+ luax_pushstring(L, file->getExtension());
+ return 1;
+}
+
static const luaL_Reg functions[] =
{
{ "getSize", w_File_getSize },
@@ -315,6 +429,8 @@ static const luaL_Reg functions[] =
{ "setBuffer", w_File_setBuffer },
{ "getBuffer", w_File_getBuffer },
{ "getMode", w_File_getMode },
+ { "getFilename", w_File_getFilename },
+ { "getExtension", w_File_getExtension },
{ 0, 0 }
};
diff --git a/src/modules/filesystem/wrap_File.h b/src/modules/filesystem/wrap_File.h
index d4bd65d74..1248083e4 100644
--- a/src/modules/filesystem/wrap_File.h
+++ b/src/modules/filesystem/wrap_File.h
@@ -44,10 +44,13 @@ int w_File_flush(lua_State *L);
int w_File_eof(lua_State *L);
int w_File_tell(lua_State *L);
int w_File_seek(lua_State *L);
+int w_File_lines_i(lua_State *L);
int w_File_lines(lua_State *L);
int w_File_setBuffer(lua_State *L);
int w_File_getBuffer(lua_State *L);
int w_File_getMode(lua_State *L);
+int w_File_getFilename(lua_State *L);
+int w_File_getExtension(lua_State *L);
extern "C" int luaopen_file(lua_State *L);
} // filesystem
diff --git a/src/modules/filesystem/wrap_Filesystem.cpp b/src/modules/filesystem/wrap_Filesystem.cpp
index ce241e11b..cc37dda75 100644
--- a/src/modules/filesystem/wrap_Filesystem.cpp
+++ b/src/modules/filesystem/wrap_Filesystem.cpp
@@ -21,6 +21,7 @@
// LOVE
#include "wrap_Filesystem.h"
#include "wrap_File.h"
+#include "wrap_DroppedFile.h"
#include "wrap_FileData.h"
#include "physfs/Filesystem.h"
@@ -38,7 +39,7 @@ namespace love
namespace filesystem
{
-#define instance() (Module::getInstance(Module::M_FILESYSTEM))
+#define instance() (Module::getInstance(Module::M_FILESYSTEM))
bool hack_setupWriteDirectory()
{
@@ -124,7 +125,7 @@ int w_newFile(lua_State *L)
const char *filename = luaL_checkstring(L, 1);
const char *str = 0;
- File::Mode mode = File::CLOSED;
+ File::Mode mode = File::MODE_CLOSED;
if (lua_isstring(L, 2))
{
@@ -135,7 +136,7 @@ int w_newFile(lua_State *L)
File *t = instance()->newFile(filename);
- if (mode != File::CLOSED)
+ if (mode != File::MODE_CLOSED)
{
try
{
@@ -363,7 +364,7 @@ static int w_write_or_append(lua_State *L, File::Mode mode)
try
{
- if (mode == File::APPEND)
+ if (mode == File::MODE_APPEND)
instance()->append(filename, (const void *) input, len);
else
instance()->write(filename, (const void *) input, len);
@@ -379,12 +380,12 @@ static int w_write_or_append(lua_State *L, File::Mode mode)
int w_write(lua_State *L)
{
- return w_write_or_append(L, File::WRITE);
+ return w_write_or_append(L, File::MODE_WRITE);
}
int w_append(lua_State *L)
{
- return w_write_or_append(L, File::APPEND);
+ return w_write_or_append(L, File::MODE_APPEND);
}
int w_getDirectoryItems(lua_State *L)
@@ -401,7 +402,7 @@ int w_lines(lua_State *L)
file = instance()->newFile(lua_tostring(L, 1));
bool success = false;
- luax_catchexcept(L, [&](){ success = file->open(File::READ); });
+ luax_catchexcept(L, [&](){ success = file->open(File::MODE_READ); });
if (!success)
{
@@ -415,7 +416,7 @@ int w_lines(lua_State *L)
else
return luaL_argerror(L, 1, "expected filename.");
- lua_pushcclosure(L, physfs::Filesystem::lines_i, 1);
+ lua_pushcclosure(L, w_File_lines_i, 1);
return 1;
}
@@ -690,13 +691,14 @@ static const luaL_Reg functions[] =
static const lua_CFunction types[] =
{
luaopen_file,
+ luaopen_droppedfile,
luaopen_filedata,
0
};
extern "C" int luaopen_love_filesystem(lua_State *L)
{
- physfs::Filesystem *instance = instance();
+ Filesystem *instance = instance();
if (instance == nullptr)
{
luax_catchexcept(L, [&](){ instance = new physfs::Filesystem(); });
diff --git a/src/modules/font/BMFontRasterizer.cpp b/src/modules/font/BMFontRasterizer.cpp
index 4cfd1f96b..84403d78e 100644
--- a/src/modules/font/BMFontRasterizer.cpp
+++ b/src/modules/font/BMFontRasterizer.cpp
@@ -20,7 +20,7 @@
// LOVE
#include "BMFontRasterizer.h"
-#include "filesystem/physfs/Filesystem.h"
+#include "filesystem/Filesystem.h"
#include "image/Image.h"
// C++
@@ -188,7 +188,7 @@ void BMFontRasterizer::parseConfig(const std::string &configtext)
// Load the page file from disk into an ImageData, if necessary.
if (images[pageindex].get() == nullptr)
{
- using namespace love::filesystem::physfs;
+ using namespace love::filesystem;
Filesystem *filesystem = Module::getInstance(Module::M_FILESYSTEM);
image::Image *imagemodule = Module::getInstance(Module::M_IMAGE);
diff --git a/src/modules/image/magpie/ImageData.cpp b/src/modules/image/magpie/ImageData.cpp
index 617595ea9..06cafb38a 100644
--- a/src/modules/image/magpie/ImageData.cpp
+++ b/src/modules/image/magpie/ImageData.cpp
@@ -176,7 +176,7 @@ void ImageData::encode(love::filesystem::File *f, ImageData::Format format)
try
{
- f->open(love::filesystem::File::WRITE);
+ f->open(love::filesystem::File::MODE_WRITE);
f->write(encodedimage.data, encodedimage.size);
f->close();
}
diff --git a/src/scripts/boot.lua b/src/scripts/boot.lua
index bd0c942dc..ad140378e 100644
--- a/src/scripts/boot.lua
+++ b/src/scripts/boot.lua
@@ -220,6 +220,12 @@ function love.createhandlers()
resize = function(w, h)
if love.resize then return love.resize(w, h) end
end,
+ filedropped = function (f)
+ if love.filedropped then return love.filedropped(f) end
+ end,
+ directorydropped = function (dir)
+ if love.directorydropped then return love.directorydropped(dir) end
+ end,
}, {
__index = function(self, name)
error("Unknown event: " .. name)
diff --git a/src/scripts/boot.lua.h b/src/scripts/boot.lua.h
index 547d968ed..630bcc242 100644
--- a/src/scripts/boot.lua.h
+++ b/src/scripts/boot.lua.h
@@ -405,6 +405,20 @@ const unsigned char boot_lua[] =
0x74, 0x68, 0x65, 0x6e, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x72,
0x65, 0x73, 0x69, 0x7a, 0x65, 0x28, 0x77, 0x2c, 0x20, 0x68, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a,
0x09, 0x09, 0x65, 0x6e, 0x64, 0x2c, 0x0a,
+ 0x09, 0x09, 0x66, 0x69, 0x6c, 0x65, 0x64, 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x20, 0x3d, 0x20, 0x66, 0x75,
+ 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x66, 0x29, 0x0a,
+ 0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x64, 0x72, 0x6f,
+ 0x70, 0x70, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c,
+ 0x6f, 0x76, 0x65, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x64, 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x28, 0x66, 0x29,
+ 0x20, 0x65, 0x6e, 0x64, 0x0a,
+ 0x09, 0x09, 0x65, 0x6e, 0x64, 0x2c, 0x0a,
+ 0x09, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x64, 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64,
+ 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x64, 0x69, 0x72, 0x29, 0x0a,
+ 0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f,
+ 0x72, 0x79, 0x64, 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x72, 0x65, 0x74,
+ 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79,
+ 0x64, 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x28, 0x64, 0x69, 0x72, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a,
+ 0x09, 0x09, 0x65, 0x6e, 0x64, 0x2c, 0x0a,
0x09, 0x7d, 0x2c, 0x20, 0x7b, 0x0a,
0x09, 0x09, 0x5f, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69,
0x6f, 0x6e, 0x28, 0x73, 0x65, 0x6c, 0x66, 0x2c, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x29, 0x0a,