Add support for unpackaged resources to speed up loads on Android, i.e. so we don't have to decompress entire GPAs to load a single resource.

This commit is contained in:
elasota
2020-10-12 18:03:23 -04:00
parent ec56bdace2
commit 1ecef6f8ef
26 changed files with 674 additions and 252 deletions

View File

@@ -183,7 +183,7 @@ bool GpFileSystem_Win32::FileExists(PortabilityLayer::VirtualDirectory_t virtual
{
wchar_t winPath[MAX_PATH + 1];
if (!ResolvePath(virtualDirectory, path, winPath))
if (!ResolvePath(virtualDirectory, &path, 1, winPath))
return false;
return PathFileExistsW(winPath) != 0;
@@ -193,7 +193,7 @@ bool GpFileSystem_Win32::FileLocked(PortabilityLayer::VirtualDirectory_t virtual
{
wchar_t winPath[MAX_PATH + 1];
if (!ResolvePath(virtualDirectory, path, winPath))
if (!ResolvePath(virtualDirectory, &path, 1, winPath))
{
*exists = false;
return false;
@@ -210,11 +210,11 @@ bool GpFileSystem_Win32::FileLocked(PortabilityLayer::VirtualDirectory_t virtual
return (attribs & FILE_ATTRIBUTE_READONLY) != 0;
}
GpIOStream *GpFileSystem_Win32::OpenFile(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, bool writeAccess, GpFileCreationDisposition_t createDisposition)
GpIOStream *GpFileSystem_Win32::OpenFileNested(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths, bool writeAccess, GpFileCreationDisposition_t createDisposition)
{
wchar_t winPath[MAX_PATH + 1];
if (!ResolvePath(virtualDirectory, path, winPath))
if (!ResolvePath(virtualDirectory, paths, numPaths, winPath))
return false;
const DWORD desiredAccess = writeAccess ? (GENERIC_WRITE | GENERIC_READ) : GENERIC_READ;
@@ -252,7 +252,7 @@ bool GpFileSystem_Win32::DeleteFile(PortabilityLayer::VirtualDirectory_t virtual
{
wchar_t winPath[MAX_PATH + 1];
if (!ResolvePath(virtualDirectory, path, winPath))
if (!ResolvePath(virtualDirectory, &path, 1, winPath))
return false;
if (DeleteFileW(winPath))
@@ -270,11 +270,22 @@ bool GpFileSystem_Win32::DeleteFile(PortabilityLayer::VirtualDirectory_t virtual
return false;
}
PortabilityLayer::HostDirectoryCursor *GpFileSystem_Win32::ScanDirectory(PortabilityLayer::VirtualDirectory_t virtualDirectory)
PortabilityLayer::HostDirectoryCursor *GpFileSystem_Win32::ScanDirectoryNested(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths)
{
wchar_t winPath[MAX_PATH + 2];
if (!ResolvePath(virtualDirectory, "*", winPath))
const char **expandedPaths = static_cast<const char**>(malloc(sizeof(const char*) * (numPaths + 1)));
if (!expandedPaths)
return nullptr;
for (size_t i = 0; i < numPaths; i++)
expandedPaths[i] = paths[i];
expandedPaths[numPaths] = "*";
const bool isPathResolved = ResolvePath(virtualDirectory, expandedPaths, numPaths + 1, winPath);
free(expandedPaths);
if (!isPathResolved)
return nullptr;
WIN32_FIND_DATAW findData;
@@ -306,6 +317,11 @@ bool GpFileSystem_Win32::ValidateFilePathUnicodeChar(uint32_t c) const
return false;
}
bool GpFileSystem_Win32::IsVirtualDirectoryLooseResources(PortabilityLayer::VirtualDirectory_t virtualDir) const
{
return false;
}
bool GpFileSystem_Win32::ValidateFilePath(const char *str, size_t length) const
{
for (size_t i = 0; i < length; i++)
@@ -407,7 +423,7 @@ GpFileSystem_Win32 *GpFileSystem_Win32::GetInstance()
return &ms_instance;
}
bool GpFileSystem_Win32::ResolvePath(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, wchar_t *outPath)
bool GpFileSystem_Win32::ResolvePath(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths, wchar_t *outPath)
{
const wchar_t *baseDir = nullptr;
@@ -445,23 +461,39 @@ bool GpFileSystem_Win32::ResolvePath(PortabilityLayer::VirtualDirectory_t virtua
return false;
const size_t baseDirLen = wcslen(baseDir);
const size_t pathLen = strlen(path);
if (baseDirLen >= MAX_PATH || MAX_PATH - baseDirLen < pathLen)
return false;
memcpy(outPath, baseDir, sizeof(wchar_t) * baseDirLen);
for (size_t i = 0; i < pathLen; i++)
outPath[baseDirLen] = static_cast<wchar_t>(0);
for (size_t i = 0; i < numPaths; i++)
{
char c = path[i];
if (c == '/')
c = '\\';
size_t outDirLen = wcslen(outPath);
outPath[baseDirLen + i] = static_cast<wchar_t>(c);
if (i != 0)
{
if (baseDirLen >= MAX_PATH || MAX_PATH - baseDirLen < 1)
return false;
outPath[outDirLen++] = '\\';
}
const char *path = paths[i];
const size_t pathLen = strlen(path);
if (baseDirLen >= MAX_PATH || MAX_PATH - baseDirLen < pathLen)
return false;
for (size_t j = 0; j < pathLen; j++)
{
char c = path[j];
if (c == '/')
c = '\\';
outPath[outDirLen + j] = static_cast<wchar_t>(c);
}
outPath[outDirLen + pathLen] = static_cast<wchar_t>(0);
}
outPath[baseDirLen + pathLen] = static_cast<wchar_t>(0);
return true;
}

View File

@@ -14,19 +14,21 @@ public:
bool FileExists(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path) override;
bool FileLocked(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, bool *exists) override;
GpIOStream *OpenFile(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, bool writeAccess, GpFileCreationDisposition_t createDisposition) override;
GpIOStream *OpenFileNested(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths, bool writeAccess, GpFileCreationDisposition_t createDisposition) override;
bool DeleteFile(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, bool &existed) override;
PortabilityLayer::HostDirectoryCursor *ScanDirectory(PortabilityLayer::VirtualDirectory_t virtualDirectory) override;
PortabilityLayer::HostDirectoryCursor *ScanDirectoryNested(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths) override;
bool ValidateFilePath(const char *path, size_t sz) const override;
bool ValidateFilePathUnicodeChar(uint32_t ch) const override;
bool IsVirtualDirectoryLooseResources(PortabilityLayer::VirtualDirectory_t virtualDir) const override;
const wchar_t *GetBasePath() const;
static GpFileSystem_Win32 *GetInstance();
private:
bool ResolvePath(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, wchar_t *outPath);
bool ResolvePath(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths, wchar_t *outPath);
std::wstring m_prefsDir;
std::wstring m_scoresDir;