Browse Source

Use new PhysfsIo class for Android AAsset wrapper.

Miku AuahDark 2 years ago
parent
commit
e9c564e989
2 changed files with 82 additions and 101 deletions
  1. 81 100
      src/common/android.cpp
  2. 1 1
      src/modules/filesystem/physfs/PhysfsIo.h

+ 81 - 100
src/common/android.cpp

@@ -35,7 +35,7 @@
 #include <sys/types.h>
 #include <unistd.h>
 
-#include "physfs.h"
+#include "filesystem/physfs/PhysfsIo.h"
 
 namespace love
 {
@@ -390,127 +390,109 @@ static AAssetManager *getAssetManager()
 
 namespace aasset
 {
-namespace io
-{
 
-struct AssetInfo
+struct AssetInfo: public love::filesystem::physfs::PhysfsIo<AssetInfo>
 {
+	static const uint32_t version = 0;
+
 	AAssetManager *assetManager;
 	AAsset *asset;
 	char *filename;
 	size_t size;
-};
-
-static std::unordered_map<std::string, PHYSFS_FileType> fileTree;
-
-PHYSFS_sint64 read(PHYSFS_Io *io, void *buf, PHYSFS_uint64 len)
-{
-	AAsset *asset = ((AssetInfo *) io->opaque)->asset;
-	int readed = AAsset_read(asset, buf, (size_t) len);
 
-	PHYSFS_setErrorCode(readed < 0 ? PHYSFS_ERR_OS_ERROR : PHYSFS_ERR_OK);
-	return (PHYSFS_sint64) readed;
-}
+	static AssetInfo *fromAAsset(AAssetManager *assetManager, const char *filename, AAsset *asset)
+	{
+		return new AssetInfo(assetManager, filename, asset);
+	}
 
-PHYSFS_sint64 write(PHYSFS_Io *io, const void *buf, PHYSFS_uint64 len)
-{
-	LOVE_UNUSED(io);
-	LOVE_UNUSED(buf);
-	LOVE_UNUSED(len);
+	int64_t read(void* buf, uint64_t len) const
+	{
+		int readed = AAsset_read(asset, buf, (size_t) len);
 
-	PHYSFS_setErrorCode(PHYSFS_ERR_READ_ONLY);
-	return -1;
-}
+		PHYSFS_setErrorCode(readed < 0 ? PHYSFS_ERR_OS_ERROR : PHYSFS_ERR_OK);
+		return (PHYSFS_sint64) readed;
+	}
 
-int seek(PHYSFS_Io *io, PHYSFS_uint64 offset)
-{
-	AAsset *asset = ((AssetInfo *) io->opaque)->asset;
-	int success = AAsset_seek64(asset, (off64_t) offset, SEEK_SET) != -1;
+	int64_t write(const void* buf, uint64_t len) const
+	{
+		LOVE_UNUSED(buf);
+		LOVE_UNUSED(len);
 
-	PHYSFS_setErrorCode(success ? PHYSFS_ERR_OK : PHYSFS_ERR_OS_ERROR);
-	return success;
-}
+		PHYSFS_setErrorCode(PHYSFS_ERR_READ_ONLY);
+		return -1;
+	}
 
-PHYSFS_sint64 tell(PHYSFS_Io *io)
-{
-	AAsset *asset = ((AssetInfo *) io->opaque)->asset;
-	off64_t len = AAsset_getLength64(asset);
-	off64_t remain = AAsset_getRemainingLength64(asset);
+	int64_t seek(uint64_t offset) const
+	{
+		int64_t success = AAsset_seek64(asset, (off64_t) offset, SEEK_SET) != -1;
 
-	return len - remain;
-}
+		PHYSFS_setErrorCode(success ? PHYSFS_ERR_OK : PHYSFS_ERR_OS_ERROR);
+		return success;
+	}
 
-PHYSFS_sint64 length(PHYSFS_Io *io)
-{
-	AAsset *asset = ((AssetInfo *) io->opaque)->asset;
-	return AAsset_getLength64(asset);
-}
+	int64_t tell() const
+	{
+		off64_t len = AAsset_getLength64(asset);
+		off64_t remain = AAsset_getRemainingLength64(asset);
 
-// Forward declaration
-PHYSFS_Io *fromAAsset(AAssetManager *assetManager, const char *filename, AAsset *asset);
+		return len - remain;
+	}
 
-PHYSFS_Io *duplicate(PHYSFS_Io *io)
-{
-	AssetInfo *assetInfo = (AssetInfo *) io->opaque;
-	AAsset *asset = AAssetManager_open(assetInfo->assetManager, assetInfo->filename, AASSET_MODE_RANDOM);
+	int64_t length() const
+	{
+		return AAsset_getLength64(asset);
+	}
 
-	if (asset == nullptr)
+	int64_t flush() const
 	{
-		PHYSFS_setErrorCode(PHYSFS_ERR_OS_ERROR);
-		return nullptr;
+		// Do nothing
+		PHYSFS_setErrorCode(PHYSFS_ERR_OK);
+		return 1;
 	}
 
-	AAsset_seek64(asset, tell(io), SEEK_SET);
-	return fromAAsset(assetInfo->assetManager, assetInfo->filename, asset);
-}
+	AssetInfo *duplicate() const
+	{
+		AAsset *newAsset = AAssetManager_open(assetManager, filename, AASSET_MODE_RANDOM);
 
-void destroy(PHYSFS_Io *io)
-{
-	AssetInfo *assetInfo = (AssetInfo *) io->opaque;
-	AAsset_close(assetInfo->asset);
-	delete[] assetInfo->filename;
-	delete assetInfo;
-	delete io;
-}
+		if (newAsset == nullptr)
+		{
+			PHYSFS_setErrorCode(PHYSFS_ERR_OS_ERROR);
+			return nullptr;
+		}
 
-PHYSFS_Io *fromAAsset(AAssetManager *assetManager, const char *filename, AAsset *asset)
-{
-	// Create AssetInfo
-	AssetInfo *assetInfo = new (std::nothrow) AssetInfo();
-	assetInfo->assetManager = assetManager;
-	assetInfo->asset = asset;
-	assetInfo->size = strlen(filename) + 1;
-	assetInfo->filename = new (std::nothrow) char[assetInfo->size];
-	memcpy(assetInfo->filename, filename, assetInfo->size);
+		AAsset_seek64(asset, tell(), SEEK_SET);
+		return fromAAsset(assetManager, filename, asset);
+	}
 
-	// Create PHYSFS_Io
-	PHYSFS_Io *io = new (std::nothrow) PHYSFS_Io();
-	io->version = 0;
-	io->opaque = assetInfo;
-	io->read = read;
-	io->write = write;
-	io->seek = seek;
-	io->tell = tell;
-	io->length = length;
-	io->duplicate = duplicate;
-	io->flush = nullptr;
-	io->destroy = destroy;
+	~AssetInfo() override
+	{
+		AAsset_close(asset);
+		delete[] filename;
+	}
 
-	return io;
-}
+private:
+	AssetInfo(AAssetManager *assetManager, const char *filename, AAsset *asset)
+	: assetManager(assetManager)
+	, asset(asset)
+	, size(strlen(filename) + 1)
+	{
+		this->filename = new (std::nothrow) char[size];
+		memcpy(this->filename, filename, size);
+	}
+};
 
-}
+static std::unordered_map<std::string, PHYSFS_FileType> fileTree;
 
 void *openArchive(PHYSFS_Io *io, const char *name, int forWrite, int *claimed)
 {
-	if (io->opaque == nullptr || memcmp(io->opaque, "ASET", 4) != 0)
+	if (forWrite || io->opaque == nullptr || memcmp(io->opaque, "ASET", 4) != 0)
 		return nullptr;
 
 	// It's our archive
 	*claimed = 1;
 	AAssetManager *assetManager = getAssetManager();
 
-	if (io::fileTree.empty())
+	if (fileTree.empty())
 	{
 		// AAssetDir_getNextFileName intentionally excludes directories, so
 		// we have to use JNI that calls AssetManager.list() recursively.
@@ -526,7 +508,7 @@ void *openArchive(PHYSFS_Io *io, const char *name, int forWrite, int *claimed)
 			jstring jstr = (jstring) env->GetObjectArrayElement(list, i);
 			const char *str = env->GetStringUTFChars(jstr, nullptr);
 
-			io::fileTree[str + 1] = str[0] == 'd' ? PHYSFS_FILETYPE_DIRECTORY : PHYSFS_FILETYPE_REGULAR;
+			fileTree[str + 1] = str[0] == 'd' ? PHYSFS_FILETYPE_DIRECTORY : PHYSFS_FILETYPE_REGULAR;
 
 			env->ReleaseStringUTFChars(jstr, str);
 			env->DeleteLocalRef(jstr);
@@ -557,9 +539,9 @@ PHYSFS_EnumerateCallbackResult enumerate(
 
 	if (path[0] != 0)
 	{
-		FileTreeIterator result = io::fileTree.find(path);
+		FileTreeIterator result = fileTree.find(path);
 
-		if (result == io::fileTree.end() || result->second != PHYSFS_FILETYPE_DIRECTORY)
+		if (result == fileTree.end() || result->second != PHYSFS_FILETYPE_DIRECTORY)
 		{
 			PHYSFS_setErrorCode(PHYSFS_ERR_NOT_FOUND);
 			return PHYSFS_ENUM_ERROR;
@@ -617,7 +599,7 @@ PHYSFS_Io *openRead(void *opaque, const char *name)
 	}
 
 	PHYSFS_setErrorCode(PHYSFS_ERR_OK);
-	return io::fromAAsset(assetManager, name, file);
+	return AssetInfo::fromAAsset(assetManager, name, file);
 }
 
 PHYSFS_Io *openWriteAppend(void *opaque, const char *name)
@@ -642,11 +624,12 @@ int removeMkdir(void *opaque, const char *name)
 
 int stat(void *opaque, const char *name, PHYSFS_Stat *out)
 {
+	using FileTreeIterator = std::unordered_map<std::string, PHYSFS_FileType>::iterator;
 	LOVE_UNUSED(opaque);
 
-	auto result = io::fileTree.find(name);
+	FileTreeIterator result = fileTree.find(name);
 
-	if (result != io::fileTree.end())
+	if (result != fileTree.end())
 	{
 		out->filetype = result->second;
 		out->modtime = -1;
@@ -657,11 +640,9 @@ int stat(void *opaque, const char *name, PHYSFS_Stat *out)
 		PHYSFS_setErrorCode(PHYSFS_ERR_OK);
 		return 1;
 	}
-	else
-	{
-		PHYSFS_setErrorCode(PHYSFS_ERR_NOT_FOUND);
-		return 0;
-	}
+
+	PHYSFS_setErrorCode(PHYSFS_ERR_NOT_FOUND);
+	return 0;
 }
 
 void closeArchive(void *opaque)
@@ -763,7 +744,7 @@ bool checkFusedGame(void **physfsIO_Out)
 	AAsset *asset = AAssetManager_open(assetManager, "game.love", AASSET_MODE_RANDOM);
 	if (asset)
 	{
-		io = aasset::io::fromAAsset(assetManager, "game.love", asset);
+		io = aasset::AssetInfo::fromAAsset(assetManager, "game.love", asset);
 		return true;
 	}
 

+ 1 - 1
src/modules/filesystem/physfs/PhysfsIo.h

@@ -40,7 +40,7 @@ struct PhysfsIo : PHYSFS_Io
 protected:
 
 	PhysfsIo()
-		: PHYSFS_Io()
+	: PHYSFS_Io()
 	{
 		// Direct initialization of PHYSFS_Io members in the initializer list
 		// doesn't work in VS2013.