Browse Source

Added an optional search order enum ("first" or "last") to love.filesystem.setIdentity and love.filesystem.mount (resolves issue #694)

Alex Szpakowski 12 years ago
parent
commit
7a20bbc6c4

+ 39 - 21
src/modules/filesystem/physfs/Filesystem.cpp

@@ -37,7 +37,7 @@ namespace physfs
 Filesystem::Filesystem()
 Filesystem::Filesystem()
 	: open_count(0)
 	: open_count(0)
 	, buffer(0)
 	, buffer(0)
-	, isInited(false)
+	, initialized(false)
 	, release(false)
 	, release(false)
 	, releaseSet(false)
 	, releaseSet(false)
 {
 {
@@ -45,11 +45,8 @@ Filesystem::Filesystem()
 
 
 Filesystem::~Filesystem()
 Filesystem::~Filesystem()
 {
 {
-	if (isInited)
-	{
-		isInited = false;
+	if (initialized)
 		PHYSFS_deinit();
 		PHYSFS_deinit();
-	}
 }
 }
 
 
 const char *Filesystem::getName() const
 const char *Filesystem::getName() const
@@ -61,7 +58,7 @@ void Filesystem::init(const char *arg0)
 {
 {
 	if (!PHYSFS_init(arg0))
 	if (!PHYSFS_init(arg0))
 		throw Exception(PHYSFS_getLastError());
 		throw Exception(PHYSFS_getLastError());
-	isInited = true;
+	initialized = true;
 }
 }
 
 
 void Filesystem::setRelease(bool release)
 void Filesystem::setRelease(bool release)
@@ -79,9 +76,9 @@ bool Filesystem::isRelease() const
 	return release;
 	return release;
 }
 }
 
 
-bool Filesystem::setIdentity(const char *ident)
+bool Filesystem::setIdentity(const char *ident, SearchOrder searchorder)
 {
 {
-	if (!isInited)
+	if (!initialized)
 		return false;
 		return false;
 
 
 	std::string old_save_path = save_path_full;
 	std::string old_save_path = save_path_full;
@@ -104,15 +101,16 @@ bool Filesystem::setIdentity(const char *ident)
 	// save_path_relative: ./LOVE/game
 	// save_path_relative: ./LOVE/game
 	// save_path_full: C:\Documents and Settings\user\Application Data/LOVE/game
 	// save_path_full: C:\Documents and Settings\user\Application Data/LOVE/game
 
 
+	// We don't want old read-only save paths to accumulate when we set a new
+	// identity.
+	if (!old_save_path.empty())
+		PHYSFS_removeFromSearchPath(old_save_path.c_str());
+
+	bool append = (searchorder == SEARCH_ORDER_LAST);
+
 	// Try to add the save directory to the search path.
 	// Try to add the save directory to the search path.
 	// (No error on fail, it means that the path doesn't exist).
 	// (No error on fail, it means that the path doesn't exist).
-	if (PHYSFS_addToSearchPath(save_path_full.c_str(), 0))
-	{
-		// We don't want old read-only save paths to accumulate when we set a
-		// new identity.
-		if (old_save_path.compare(save_path_full) != 0)
-			PHYSFS_removeFromSearchPath(old_save_path.c_str());
-	}
+	PHYSFS_addToSearchPath(save_path_full.c_str(), append);
 
 
 	return true;
 	return true;
 }
 }
@@ -124,7 +122,7 @@ const char *Filesystem::getIdentity() const
 
 
 bool Filesystem::setSource(const char *source)
 bool Filesystem::setSource(const char *source)
 {
 {
-	if (!isInited)
+	if (!initialized)
 		return false;
 		return false;
 
 
 	// Check whether directory is already set.
 	// Check whether directory is already set.
@@ -143,7 +141,7 @@ bool Filesystem::setSource(const char *source)
 
 
 bool Filesystem::setupWriteDirectory()
 bool Filesystem::setupWriteDirectory()
 {
 {
-	if (!isInited)
+	if (!initialized)
 		return false;
 		return false;
 
 
 	// These must all be set.
 	// These must all be set.
@@ -182,9 +180,9 @@ bool Filesystem::setupWriteDirectory()
 	return true;
 	return true;
 }
 }
 
 
-bool Filesystem::mount(const char *archive, const char *mountpoint)
+bool Filesystem::mount(const char *archive, const char *mountpoint, SearchOrder searchorder)
 {
 {
-	if (!isInited || !archive)
+	if (!initialized || !archive)
 		return false;
 		return false;
 
 
 	// Not allowed for safety reasons.
 	// Not allowed for safety reasons.
@@ -205,12 +203,14 @@ bool Filesystem::mount(const char *archive, const char *mountpoint)
 	realPath += LOVE_PATH_SEPARATOR;
 	realPath += LOVE_PATH_SEPARATOR;
 	realPath += archive;
 	realPath += archive;
 
 
-	return PHYSFS_mount(realPath.c_str(), mountpoint, 0);
+	bool append = (searchorder == SEARCH_ORDER_LAST);
+
+	return PHYSFS_mount(realPath.c_str(), mountpoint, append);
 }
 }
 
 
 bool Filesystem::unmount(const char *archive)
 bool Filesystem::unmount(const char *archive)
 {
 {
-	if (!isInited || !archive)
+	if (!initialized || !archive)
 		return false;
 		return false;
 
 
 	// Not allowed for safety reasons.
 	// Not allowed for safety reasons.
@@ -535,6 +535,24 @@ int64 Filesystem::getSize(const char *filename) const
 	return size;
 	return size;
 }
 }
 
 
+bool Filesystem::getConstant(const char *in, Filesystem::SearchOrder &out)
+{
+	return orders.find(in, out);
+}
+
+bool Filesystem::getConstant(Filesystem::SearchOrder in, const char *&out)
+{
+	return orders.find(in, out);
+}
+
+StringMap<Filesystem::SearchOrder, Filesystem::SEARCH_ORDER_MAX_ENUM>::Entry Filesystem::orderEntries[] =
+{
+	{"first", Filesystem::SEARCH_ORDER_FIRST},
+	{"last", Filesystem::SEARCH_ORDER_LAST},
+};
+
+StringMap<Filesystem::SearchOrder, Filesystem::SEARCH_ORDER_MAX_ENUM> Filesystem::orders(Filesystem::orderEntries, sizeof(Filesystem::orderEntries));
+
 } // physfs
 } // physfs
 } // filesystem
 } // filesystem
 } // love
 } // love

+ 53 - 38
src/modules/filesystem/physfs/Filesystem.h

@@ -31,6 +31,7 @@
 #include "common/Module.h"
 #include "common/Module.h"
 #include "common/config.h"
 #include "common/config.h"
 #include "common/int.h"
 #include "common/int.h"
+#include "common/StringMap.h"
 #include "filesystem/FileData.h"
 #include "filesystem/FileData.h"
 #include "File.h"
 #include "File.h"
 
 
@@ -71,46 +72,19 @@ namespace filesystem
 {
 {
 namespace physfs
 namespace physfs
 {
 {
+
 class Filesystem : public Module
 class Filesystem : public Module
 {
 {
-private:
-
-	// Counts open files.
-	int open_count;
-
-	// Pointer used for file reads.
-	char *buffer;
-
-	// Contains the current working directory (UTF8).
-	std::string cwd;
-
-	// %APPDATA% on Windows.
-	std::string appdata;
-
-	// This name will be used to create the folder
-	// in the appdata/userdata folder.
-	std::string save_identity;
-
-	// Full and relative paths of the game save folder.
-	// (Relative to the %APPDATA% folder, meaning that the
-	// relative string will look something like: ./LOVE/game)
-	std::string save_path_relative, save_path_full;
-
-	// The full path to the source of the game.
-	std::string game_source;
-
-	// Workaround for machines without PhysFS 2.0
-	bool isInited;
-
-	// Allow saving outside of the LOVE_APPDATA_FOLDER
-	// for release 'builds'
-	bool release;
-	bool releaseSet;
-
-protected:
-
 public:
 public:
 
 
+	// love.filesystem.setIdentity("foo", "last")
+	enum SearchOrder
+	{
+		SEARCH_ORDER_FIRST,
+		SEARCH_ORDER_LAST,
+		SEARCH_ORDER_MAX_ENUM
+	};
+
 	Filesystem();
 	Filesystem();
 
 
 	~Filesystem();
 	~Filesystem();
@@ -134,7 +108,7 @@ public:
 	 * @param ident The name of the game. Will be used to
 	 * @param ident The name of the game. Will be used to
 	 * to create the folder in the LOVE data folder.
 	 * to create the folder in the LOVE data folder.
 	 **/
 	 **/
-	bool setIdentity(const char *ident);
+	bool setIdentity(const char *ident, SearchOrder searchorder = SEARCH_ORDER_FIRST);
 	const char *getIdentity() const;
 	const char *getIdentity() const;
 
 
 	/**
 	/**
@@ -143,7 +117,8 @@ public:
 	 * @param source Path to a directory or a .love-file.
 	 * @param source Path to a directory or a .love-file.
 	 **/
 	 **/
 	bool setSource(const char *source);
 	bool setSource(const char *source);
-	bool mount(const char *archive, const char *mountpoint);
+
+	bool mount(const char *archive, const char *mountpoint, SearchOrder searchorder = SEARCH_ORDER_FIRST);
 	bool unmount(const char *archive);
 	bool unmount(const char *archive);
 
 
 	/**
 	/**
@@ -300,6 +275,46 @@ public:
 	 **/
 	 **/
 	static int lines_i(lua_State *L);
 	static int lines_i(lua_State *L);
 
 
+	static bool getConstant(const char *in, SearchOrder &out);
+	static bool getConstant(SearchOrder in, const char *&out);
+
+private:
+
+	// Counts open files.
+	int open_count;
+
+	// Pointer used for file reads.
+	char *buffer;
+
+	// Contains the current working directory (UTF8).
+	std::string cwd;
+
+	// %APPDATA% on Windows.
+	std::string appdata;
+
+	// This name will be used to create the folder
+	// in the appdata/userdata folder.
+	std::string save_identity;
+
+	// Full and relative paths of the game save folder.
+	// (Relative to the %APPDATA% folder, meaning that the
+	// relative string will look something like: ./LOVE/game)
+	std::string save_path_relative, save_path_full;
+
+	// 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 release;
+	bool releaseSet;
+
+	static StringMap<SearchOrder, SEARCH_ORDER_MAX_ENUM>::Entry orderEntries[];
+	static StringMap<SearchOrder, SEARCH_ORDER_MAX_ENUM> orders;
+
 }; // Filesystem
 }; // Filesystem
 
 
 } // physfs
 } // physfs

+ 14 - 2
src/modules/filesystem/physfs/wrap_Filesystem.cpp

@@ -77,7 +77,13 @@ int w_setIdentity(lua_State *L)
 {
 {
 	const char *arg = luaL_checkstring(L, 1);
 	const char *arg = luaL_checkstring(L, 1);
 
 
-	if (!instance->setIdentity(arg))
+	Filesystem::SearchOrder order = Filesystem::SEARCH_ORDER_FIRST;
+	const char *ostr = lua_isnoneornil(L, 2) ? 0 : lua_tostring(L, 2);
+
+	if (ostr && !Filesystem::getConstant(ostr, order))
+		return luaL_error(L, "Invalid filesystem search order: %s", ostr);
+
+	if (!instance->setIdentity(arg, order))
 		return luaL_error(L, "Could not set write directory.");
 		return luaL_error(L, "Could not set write directory.");
 
 
 	return 0;
 	return 0;
@@ -104,7 +110,13 @@ int w_mount(lua_State *L)
 	const char *archive = luaL_checkstring(L, 1);
 	const char *archive = luaL_checkstring(L, 1);
 	const char *mountpoint = luaL_checkstring(L, 2);
 	const char *mountpoint = luaL_checkstring(L, 2);
 
 
-	luax_pushboolean(L, instance->mount(archive, mountpoint));
+	Filesystem::SearchOrder order = Filesystem::SEARCH_ORDER_FIRST;
+	const char *ostr = lua_isnoneornil(L, 3) ? 0 : lua_tostring(L, 3);
+
+	if (ostr && !Filesystem::getConstant(ostr, order))
+		return luaL_error(L, "Invalid filesystem search order: %s", ostr);
+
+	luax_pushboolean(L, instance->mount(archive, mountpoint, order));
 	return 1;
 	return 1;
 }
 }
 
 

+ 5 - 2
src/scripts/boot.lua

@@ -294,6 +294,7 @@ function love.init()
 		},
 		},
 		console = false, -- Only relevant for windows.
 		console = false, -- Only relevant for windows.
 		identity = false,
 		identity = false,
+		identityorder = "first",
 		release = false,
 		release = false,
 	}
 	}
 
 
@@ -381,8 +382,10 @@ function love.init()
 
 
 	if love.filesystem then
 	if love.filesystem then
 		love.filesystem.setRelease(c.release and is_fused_game)
 		love.filesystem.setRelease(c.release and is_fused_game)
-		if c.identity then love.filesystem.setIdentity(c.identity) end
-		if love.filesystem.exists("main.lua") then require("main") end
+		love.filesystem.setIdentity(c.identity or love.filesystem.getIdentity(), c.identityorder)
+		if love.filesystem.exists("main.lua") then
+			require("main")
+		end
 	end
 	end
 
 
 	if no_game_code then
 	if no_game_code then

+ 11 - 6
src/scripts/boot.lua.h

@@ -509,6 +509,8 @@ const unsigned char boot_lua[] =
 	0x66, 0x6f, 0x72, 0x20, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x2e, 0x0a,
 	0x66, 0x6f, 0x72, 0x20, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x2e, 0x0a,
 	0x09, 0x09, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x20, 0x3d, 0x20, 0x66, 0x61, 0x6c, 0x73, 0x65, 
 	0x09, 0x09, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x20, 0x3d, 0x20, 0x66, 0x61, 0x6c, 0x73, 0x65, 
 	0x2c, 0x0a,
 	0x2c, 0x0a,
+	0x09, 0x09, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x20, 0x3d, 0x20, 
+	0x22, 0x66, 0x69, 0x72, 0x73, 0x74, 0x22, 0x2c, 0x0a,
 	0x09, 0x09, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x20, 0x3d, 0x20, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x0a,
 	0x09, 0x09, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x20, 0x3d, 0x20, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x0a,
 	0x09, 0x7d, 0x0a,
 	0x09, 0x7d, 0x0a,
 	0x09, 0x2d, 0x2d, 0x20, 0x49, 0x66, 0x20, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x20, 0x66, 0x69, 0x6c, 0x65, 
 	0x09, 0x2d, 0x2d, 0x20, 0x49, 0x66, 0x20, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x20, 0x66, 0x69, 0x6c, 0x65, 
@@ -652,14 +654,17 @@ const unsigned char boot_lua[] =
 	0x73, 0x65, 0x74, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x28, 0x63, 0x2e, 0x72, 0x65, 0x6c, 0x65, 0x61, 
 	0x73, 0x65, 0x74, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x28, 0x63, 0x2e, 0x72, 0x65, 0x6c, 0x65, 0x61, 
 	0x73, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x73, 0x5f, 0x66, 0x75, 0x73, 0x65, 0x64, 0x5f, 0x67, 0x61, 
 	0x73, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x73, 0x5f, 0x66, 0x75, 0x73, 0x65, 0x64, 0x5f, 0x67, 0x61, 
 	0x6d, 0x65, 0x29, 0x0a,
 	0x6d, 0x65, 0x29, 0x0a,
-	0x09, 0x09, 0x69, 0x66, 0x20, 0x63, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x20, 0x74, 0x68, 
-	0x65, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 
-	0x2e, 0x73, 0x65, 0x74, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x28, 0x63, 0x2e, 0x69, 0x64, 0x65, 
-	0x6e, 0x74, 0x69, 0x74, 0x79, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a,
+	0x09, 0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x2e, 
+	0x73, 0x65, 0x74, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x28, 0x63, 0x2e, 0x69, 0x64, 0x65, 0x6e, 
+	0x74, 0x69, 0x74, 0x79, 0x20, 0x6f, 0x72, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 
+	0x79, 0x73, 0x74, 0x65, 0x6d, 0x2e, 0x67, 0x65, 0x74, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x28, 
+	0x29, 0x2c, 0x20, 0x63, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x6f, 0x72, 0x64, 0x65, 0x72, 
+	0x29, 0x0a,
 	0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 
 	0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 
 	0x65, 0x6d, 0x2e, 0x65, 0x78, 0x69, 0x73, 0x74, 0x73, 0x28, 0x22, 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x6c, 0x75, 
 	0x65, 0x6d, 0x2e, 0x65, 0x78, 0x69, 0x73, 0x74, 0x73, 0x28, 0x22, 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x6c, 0x75, 
-	0x61, 0x22, 0x29, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x28, 0x22, 
-	0x6d, 0x61, 0x69, 0x6e, 0x22, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a,
+	0x61, 0x22, 0x29, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
+	0x09, 0x09, 0x09, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x28, 0x22, 0x6d, 0x61, 0x69, 0x6e, 0x22, 0x29, 0x0a,
+	0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
 	0x09, 0x65, 0x6e, 0x64, 0x0a,
 	0x09, 0x65, 0x6e, 0x64, 0x0a,
 	0x09, 0x69, 0x66, 0x20, 0x6e, 0x6f, 0x5f, 0x67, 0x61, 0x6d, 0x65, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x74, 
 	0x09, 0x69, 0x66, 0x20, 0x6e, 0x6f, 0x5f, 0x67, 0x61, 0x6d, 0x65, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x74, 
 	0x68, 0x65, 0x6e, 0x0a,
 	0x68, 0x65, 0x6e, 0x0a,