mirror of
https://github.com/love2d/love.git
synced 2026-08-19 12:14:20 +02:00
Use new PhysfsIo class for Android AAsset wrapper.
This commit is contained in:
+97
-116
@@ -35,7 +35,7 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "physfs.h"
|
#include "filesystem/physfs/PhysfsIo.h"
|
||||||
|
|
||||||
namespace love
|
namespace love
|
||||||
{
|
{
|
||||||
@@ -390,127 +390,109 @@ static AAssetManager *getAssetManager()
|
|||||||
|
|
||||||
namespace aasset
|
namespace aasset
|
||||||
{
|
{
|
||||||
namespace io
|
|
||||||
{
|
|
||||||
|
|
||||||
struct AssetInfo
|
struct AssetInfo: public love::filesystem::physfs::PhysfsIo<AssetInfo>
|
||||||
{
|
{
|
||||||
|
static const uint32_t version = 0;
|
||||||
|
|
||||||
AAssetManager *assetManager;
|
AAssetManager *assetManager;
|
||||||
AAsset *asset;
|
AAsset *asset;
|
||||||
char *filename;
|
char *filename;
|
||||||
size_t size;
|
size_t size;
|
||||||
|
|
||||||
|
static AssetInfo *fromAAsset(AAssetManager *assetManager, const char *filename, AAsset *asset)
|
||||||
|
{
|
||||||
|
return new AssetInfo(assetManager, filename, asset);
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t read(void* buf, uint64_t len) const
|
||||||
|
{
|
||||||
|
int readed = AAsset_read(asset, buf, (size_t) len);
|
||||||
|
|
||||||
|
PHYSFS_setErrorCode(readed < 0 ? PHYSFS_ERR_OS_ERROR : PHYSFS_ERR_OK);
|
||||||
|
return (PHYSFS_sint64) readed;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t write(const void* buf, uint64_t len) const
|
||||||
|
{
|
||||||
|
LOVE_UNUSED(buf);
|
||||||
|
LOVE_UNUSED(len);
|
||||||
|
|
||||||
|
PHYSFS_setErrorCode(PHYSFS_ERR_READ_ONLY);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t seek(uint64_t offset) const
|
||||||
|
{
|
||||||
|
int64_t success = AAsset_seek64(asset, (off64_t) offset, SEEK_SET) != -1;
|
||||||
|
|
||||||
|
PHYSFS_setErrorCode(success ? PHYSFS_ERR_OK : PHYSFS_ERR_OS_ERROR);
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t tell() const
|
||||||
|
{
|
||||||
|
off64_t len = AAsset_getLength64(asset);
|
||||||
|
off64_t remain = AAsset_getRemainingLength64(asset);
|
||||||
|
|
||||||
|
return len - remain;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t length() const
|
||||||
|
{
|
||||||
|
return AAsset_getLength64(asset);
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t flush() const
|
||||||
|
{
|
||||||
|
// Do nothing
|
||||||
|
PHYSFS_setErrorCode(PHYSFS_ERR_OK);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
AssetInfo *duplicate() const
|
||||||
|
{
|
||||||
|
AAsset *newAsset = AAssetManager_open(assetManager, filename, AASSET_MODE_RANDOM);
|
||||||
|
|
||||||
|
if (newAsset == nullptr)
|
||||||
|
{
|
||||||
|
PHYSFS_setErrorCode(PHYSFS_ERR_OS_ERROR);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
AAsset_seek64(asset, tell(), SEEK_SET);
|
||||||
|
return fromAAsset(assetManager, filename, asset);
|
||||||
|
}
|
||||||
|
|
||||||
|
~AssetInfo() override
|
||||||
|
{
|
||||||
|
AAsset_close(asset);
|
||||||
|
delete[] filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
PHYSFS_sint64 write(PHYSFS_Io *io, const void *buf, PHYSFS_uint64 len)
|
|
||||||
{
|
|
||||||
LOVE_UNUSED(io);
|
|
||||||
LOVE_UNUSED(buf);
|
|
||||||
LOVE_UNUSED(len);
|
|
||||||
|
|
||||||
PHYSFS_setErrorCode(PHYSFS_ERR_READ_ONLY);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
PHYSFS_setErrorCode(success ? PHYSFS_ERR_OK : PHYSFS_ERR_OS_ERROR);
|
|
||||||
return success;
|
|
||||||
}
|
|
||||||
|
|
||||||
PHYSFS_sint64 tell(PHYSFS_Io *io)
|
|
||||||
{
|
|
||||||
AAsset *asset = ((AssetInfo *) io->opaque)->asset;
|
|
||||||
off64_t len = AAsset_getLength64(asset);
|
|
||||||
off64_t remain = AAsset_getRemainingLength64(asset);
|
|
||||||
|
|
||||||
return len - remain;
|
|
||||||
}
|
|
||||||
|
|
||||||
PHYSFS_sint64 length(PHYSFS_Io *io)
|
|
||||||
{
|
|
||||||
AAsset *asset = ((AssetInfo *) io->opaque)->asset;
|
|
||||||
return AAsset_getLength64(asset);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Forward declaration
|
|
||||||
PHYSFS_Io *fromAAsset(AAssetManager *assetManager, const char *filename, AAsset *asset);
|
|
||||||
|
|
||||||
PHYSFS_Io *duplicate(PHYSFS_Io *io)
|
|
||||||
{
|
|
||||||
AssetInfo *assetInfo = (AssetInfo *) io->opaque;
|
|
||||||
AAsset *asset = AAssetManager_open(assetInfo->assetManager, assetInfo->filename, AASSET_MODE_RANDOM);
|
|
||||||
|
|
||||||
if (asset == nullptr)
|
|
||||||
{
|
|
||||||
PHYSFS_setErrorCode(PHYSFS_ERR_OS_ERROR);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
AAsset_seek64(asset, tell(io), SEEK_SET);
|
|
||||||
return fromAAsset(assetInfo->assetManager, assetInfo->filename, asset);
|
|
||||||
}
|
|
||||||
|
|
||||||
void destroy(PHYSFS_Io *io)
|
|
||||||
{
|
|
||||||
AssetInfo *assetInfo = (AssetInfo *) io->opaque;
|
|
||||||
AAsset_close(assetInfo->asset);
|
|
||||||
delete[] assetInfo->filename;
|
|
||||||
delete assetInfo;
|
|
||||||
delete io;
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
// 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;
|
|
||||||
|
|
||||||
return io;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void *openArchive(PHYSFS_Io *io, const char *name, int forWrite, int *claimed)
|
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;
|
return nullptr;
|
||||||
|
|
||||||
// It's our archive
|
// It's our archive
|
||||||
*claimed = 1;
|
*claimed = 1;
|
||||||
AAssetManager *assetManager = getAssetManager();
|
AAssetManager *assetManager = getAssetManager();
|
||||||
|
|
||||||
if (io::fileTree.empty())
|
if (fileTree.empty())
|
||||||
{
|
{
|
||||||
// AAssetDir_getNextFileName intentionally excludes directories, so
|
// AAssetDir_getNextFileName intentionally excludes directories, so
|
||||||
// we have to use JNI that calls AssetManager.list() recursively.
|
// 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);
|
jstring jstr = (jstring) env->GetObjectArrayElement(list, i);
|
||||||
const char *str = env->GetStringUTFChars(jstr, nullptr);
|
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->ReleaseStringUTFChars(jstr, str);
|
||||||
env->DeleteLocalRef(jstr);
|
env->DeleteLocalRef(jstr);
|
||||||
@@ -557,9 +539,9 @@ PHYSFS_EnumerateCallbackResult enumerate(
|
|||||||
|
|
||||||
if (path[0] != 0)
|
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);
|
PHYSFS_setErrorCode(PHYSFS_ERR_NOT_FOUND);
|
||||||
return PHYSFS_ENUM_ERROR;
|
return PHYSFS_ENUM_ERROR;
|
||||||
@@ -617,7 +599,7 @@ PHYSFS_Io *openRead(void *opaque, const char *name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
PHYSFS_setErrorCode(PHYSFS_ERR_OK);
|
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)
|
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)
|
int stat(void *opaque, const char *name, PHYSFS_Stat *out)
|
||||||
{
|
{
|
||||||
|
using FileTreeIterator = std::unordered_map<std::string, PHYSFS_FileType>::iterator;
|
||||||
LOVE_UNUSED(opaque);
|
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->filetype = result->second;
|
||||||
out->modtime = -1;
|
out->modtime = -1;
|
||||||
@@ -657,11 +640,9 @@ int stat(void *opaque, const char *name, PHYSFS_Stat *out)
|
|||||||
PHYSFS_setErrorCode(PHYSFS_ERR_OK);
|
PHYSFS_setErrorCode(PHYSFS_ERR_OK);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
PHYSFS_setErrorCode(PHYSFS_ERR_NOT_FOUND);
|
||||||
PHYSFS_setErrorCode(PHYSFS_ERR_NOT_FOUND);
|
return 0;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void closeArchive(void *opaque)
|
void closeArchive(void *opaque)
|
||||||
@@ -763,7 +744,7 @@ bool checkFusedGame(void **physfsIO_Out)
|
|||||||
AAsset *asset = AAssetManager_open(assetManager, "game.love", AASSET_MODE_RANDOM);
|
AAsset *asset = AAssetManager_open(assetManager, "game.love", AASSET_MODE_RANDOM);
|
||||||
if (asset)
|
if (asset)
|
||||||
{
|
{
|
||||||
io = aasset::io::fromAAsset(assetManager, "game.love", asset);
|
io = aasset::AssetInfo::fromAAsset(assetManager, "game.love", asset);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ struct PhysfsIo : PHYSFS_Io
|
|||||||
protected:
|
protected:
|
||||||
|
|
||||||
PhysfsIo()
|
PhysfsIo()
|
||||||
: PHYSFS_Io()
|
: PHYSFS_Io()
|
||||||
{
|
{
|
||||||
// Direct initialization of PHYSFS_Io members in the initializer list
|
// Direct initialization of PHYSFS_Io members in the initializer list
|
||||||
// doesn't work in VS2013.
|
// doesn't work in VS2013.
|
||||||
|
|||||||
Reference in New Issue
Block a user