Skip to content

Commit

Permalink
Merge pull request #17073 from hrydgard/replacer-use-vfs
Browse files Browse the repository at this point in the history
Use VFS for file access in the texture replacer
  • Loading branch information
hrydgard committed Mar 8, 2023
2 parents 9b2eda3 + 306fdde commit 625d93a
Show file tree
Hide file tree
Showing 7 changed files with 158 additions and 283 deletions.
15 changes: 12 additions & 3 deletions Common/File/VFS/DirectoryReader.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#include <cstdio>

#include "Common/Common.h"
#include "Common/Log.h"
#include "Common/File/VFS/DirectoryReader.h"
Expand Down Expand Up @@ -44,8 +46,13 @@ class DirectoryReaderOpenFile : public VFSOpenFile {
};

VFSFileReference *DirectoryReader::GetFile(const char *path) {
Path filePath = path_ / path;
if (!File::Exists(filePath)) {
return nullptr;
}

DirectoryReaderFileReference *reference = new DirectoryReaderFileReference();
reference->path = path_ / path;
reference->path = filePath;
return reference;
}

Expand All @@ -59,13 +66,15 @@ void DirectoryReader::ReleaseFile(VFSFileReference *vfsReference) {
delete reference;
}

VFSOpenFile *DirectoryReader::OpenFileForRead(VFSFileReference *vfsReference) {
VFSOpenFile *DirectoryReader::OpenFileForRead(VFSFileReference *vfsReference, size_t *size) {
DirectoryReaderFileReference *reference = (DirectoryReaderFileReference *)vfsReference;
FILE *file = File::OpenCFile(reference->path, "rb");
if (!file) {
return nullptr;
}

fseek(file, 0, SEEK_END);
*size = ftell(file);
fseek(file, 0, SEEK_SET);
DirectoryReaderOpenFile *openFile = new DirectoryReaderOpenFile();
openFile->file = file;
return openFile;
Expand Down
2 changes: 1 addition & 1 deletion Common/File/VFS/DirectoryReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class DirectoryReader : public VFSBackend {
bool GetFileInfo(VFSFileReference *vfsReference, File::FileInfo *fileInfo) override;
void ReleaseFile(VFSFileReference *vfsReference) override;

VFSOpenFile *OpenFileForRead(VFSFileReference *vfsReference) override;
VFSOpenFile *OpenFileForRead(VFSFileReference *vfsReference, size_t *size) override;
void Rewind(VFSOpenFile *vfsOpenFile) override;
size_t Read(VFSOpenFile *vfsOpenFile, void *buffer, size_t length) override;
void CloseFile(VFSOpenFile *vfsOpenFile) override;
Expand Down
4 changes: 3 additions & 1 deletion Common/File/VFS/VFS.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,9 @@ class VFSBackend : public VFSInterface {
virtual bool GetFileInfo(VFSFileReference *vfsReference, File::FileInfo *fileInfo) = 0;
virtual void ReleaseFile(VFSFileReference *vfsReference) = 0;

virtual VFSOpenFile *OpenFileForRead(VFSFileReference *vfsReference) = 0;
// Must write the size of the file to *size. Both backends can do this efficiently here,
// avoiding a call to GetFileInfo.
virtual VFSOpenFile *OpenFileForRead(VFSFileReference *vfsReference, size_t *size) = 0;
virtual void Rewind(VFSOpenFile *vfsOpenFile) = 0;
virtual size_t Read(VFSOpenFile *vfsOpenFile, void *buffer, size_t length) = 0;
virtual void CloseFile(VFSOpenFile *vfsOpenFile) = 0;
Expand Down
47 changes: 25 additions & 22 deletions Common/File/VFS/ZipFileReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,25 +15,6 @@
#include "Common/File/VFS/ZipFileReader.h"
#include "Common/StringUtils.h"

static uint8_t *ReadFromZip(zip *archive, const char* filename, size_t *size) {
// Figure out the file size first.
struct zip_stat zstat;
zip_file *file = zip_fopen(archive, filename, ZIP_FL_NOCASE|ZIP_FL_UNCHANGED);
if (!file) {
ERROR_LOG(IO, "Error opening %s from ZIP", filename);
return 0;
}
zip_stat(archive, filename, ZIP_FL_NOCASE|ZIP_FL_UNCHANGED, &zstat);

uint8_t *contents = new uint8_t[zstat.size + 1];
zip_fread(file, contents, zstat.size);
zip_fclose(file);
contents[zstat.size] = 0;

*size = zstat.size;
return contents;
}

ZipFileReader *ZipFileReader::Create(const Path &zipFile, const char *inZipPath) {
int error = 0;
zip *zip_file;
Expand Down Expand Up @@ -69,7 +50,21 @@ uint8_t *ZipFileReader::ReadFile(const char *path, size_t *size) {
snprintf(temp_path, sizeof(temp_path), "%s%s", inZipPath_, path);

std::lock_guard<std::mutex> guard(lock_);
return ReadFromZip(zip_file_, temp_path, size);
// Figure out the file size first.
struct zip_stat zstat;
zip_stat(zip_file_, temp_path, ZIP_FL_NOCASE | ZIP_FL_UNCHANGED, &zstat);
zip_file *file = zip_fopen(zip_file_, temp_path, ZIP_FL_NOCASE | ZIP_FL_UNCHANGED);
if (!file) {
ERROR_LOG(IO, "Error opening %s from ZIP", temp_path);
return 0;
}
uint8_t *contents = new uint8_t[zstat.size + 1];
zip_fread(file, contents, zstat.size);
zip_fclose(file);
contents[zstat.size] = 0;

*size = zstat.size;
return contents;
}

bool ZipFileReader::GetFileListing(const char *orig_path, std::vector<File::FileInfo> *listing, const char *filter = 0) {
Expand Down Expand Up @@ -238,21 +233,29 @@ void ZipFileReader::ReleaseFile(VFSFileReference *vfsReference) {
delete reference;
}

VFSOpenFile *ZipFileReader::OpenFileForRead(VFSFileReference *vfsReference) {
VFSOpenFile *ZipFileReader::OpenFileForRead(VFSFileReference *vfsReference, size_t *size) {
ZipFileReaderFileReference *reference = (ZipFileReaderFileReference *)vfsReference;
ZipFileReaderOpenFile *openFile = new ZipFileReaderOpenFile();
openFile->reference = reference;
*size = 0;
// We only allow one file to be open for read concurrently. It's possible that this can be improved,
// especially if we only access by index like this.
lock_.lock();
openFile->zf = zip_fopen_index(zip_file_, reference->zi, 0);
zip_stat_t zstat;
if (zip_stat_index(zip_file_, reference->zi, 0, &zstat) != 0) {
lock_.unlock();
return nullptr;
}

openFile->zf = zip_fopen_index(zip_file_, reference->zi, 0);
if (!openFile->zf) {
WARN_LOG(G3D, "File with index %d not found in zip", reference->zi);
lock_.unlock();
return nullptr;
}

*size = zstat.size;
// Intentionally leaving the mutex locked, will be closed in CloseFile.
return openFile;
}

Expand Down
2 changes: 1 addition & 1 deletion Common/File/VFS/ZipFileReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class ZipFileReader : public VFSBackend {
bool GetFileInfo(VFSFileReference *vfsReference, File::FileInfo *fileInfo) override;
void ReleaseFile(VFSFileReference *vfsReference) override;

VFSOpenFile *OpenFileForRead(VFSFileReference *vfsReference) override;
VFSOpenFile *OpenFileForRead(VFSFileReference *vfsReference, size_t *size) override;
void Rewind(VFSOpenFile *vfsOpenFile) override;
size_t Read(VFSOpenFile *vfsOpenFile, void *buffer, size_t length) override;
void CloseFile(VFSOpenFile *vfsOpenFile) override;
Expand Down
Loading

0 comments on commit 625d93a

Please sign in to comment.