Merge pull request #341 from rh101/vfs-support

Add support for FileStream in ZipUtils and ZipFile
This commit is contained in:
HALX99 2021-04-25 14:21:19 +08:00 committed by GitHub
commit 8b8b015b02
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 166 additions and 1 deletions

View File

@ -511,6 +511,7 @@ struct ZipEntryInfo
class ZipFilePrivate class ZipFilePrivate
{ {
public: public:
std::string zipFileName;
unzFile zipFile; unzFile zipFile;
std::mutex zipFileMtx; std::mutex zipFileMtx;
std::unique_ptr<ourmemory_s> memfs; std::unique_ptr<ourmemory_s> memfs;
@ -520,6 +521,110 @@ public:
FileListContainer fileList; FileListContainer fileList;
}; };
// unzip overrides to support FileStream
long ZipFile_tell_file_func(voidpf opaque, voidpf stream)
{
if (stream == nullptr)
return -1;
auto* fs = (FileStream*)stream;
return fs->tell();
}
long ZipFile_seek_file_func(voidpf opaque, voidpf stream, uint32_t offset, int origin)
{
if (stream == nullptr)
return -1;
auto* fs = (FileStream*)stream;
return fs->seek((long)offset, origin); // must return 0 for success or -1 for error
}
voidpf ZipFile_open_file_func(voidpf opaque, const char* filename, int mode)
{
FileStream::Mode fsMode;
if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER) == ZLIB_FILEFUNC_MODE_READ)
fsMode = FileStream::Mode::READ;
else if (mode & ZLIB_FILEFUNC_MODE_EXISTING)
fsMode = FileStream::Mode::APPEND;
else if (mode & ZLIB_FILEFUNC_MODE_CREATE)
fsMode = FileStream::Mode::WRITE;
else
return nullptr;
return FileUtils::getInstance()->openFileStream(filename, fsMode);
}
voidpf ZipFile_opendisk_file_func(voidpf opaque, voidpf stream, uint32_t number_disk, int mode)
{
if (stream == nullptr)
return nullptr;
auto* zipFileInfo = (ZipFilePrivate*)opaque;
std::string diskFilename = zipFileInfo->zipFileName;
const auto pos = diskFilename.rfind('.', std::string::npos);
if (pos != std::string::npos && pos != 0)
{
const size_t bufferSize = 5;
char extensionBuffer[bufferSize];
snprintf(&extensionBuffer[0], bufferSize, ".z%02u", number_disk + 1);
diskFilename.replace(pos, std::min((size_t)4, zipFileInfo->zipFileName.size() - pos), extensionBuffer);
return ZipFile_open_file_func(opaque, diskFilename.c_str(), mode);
}
return nullptr;
}
uint32_t ZipFile_read_file_func(voidpf opaque, voidpf stream, void* buf, uint32_t size)
{
if (stream == nullptr)
return (uint32_t)-1;
auto* fs = (FileStream*)stream;
return fs->read(buf, size);
}
uint32_t ZipFile_write_file_func(voidpf opaque, voidpf stream, const void* buf, uint32_t size)
{
if (stream == nullptr)
return (uint32_t)-1;
auto* fs = (FileStream*)stream;
return fs->write(buf, size);
}
int ZipFile_close_file_func(voidpf opaque, voidpf stream)
{
if (stream == nullptr)
return -1;
auto* fs = (FileStream*)stream;
return fs->close(); // 0 for success, -1 for error
}
// THis isn't supported by FileStream, so just check if the stream is null and open
int ZipFile_error_file_func(voidpf opaque, voidpf stream)
{
if (stream == nullptr)
{
return -1;
}
auto* fs = (FileStream*)stream;
if (fs->isOpen())
{
return 0;
}
return -1;
}
// End of Overrides
ZipFile *ZipFile::createWithBuffer(const void* buffer, uLong size) ZipFile *ZipFile::createWithBuffer(const void* buffer, uLong size)
{ {
ZipFile *zip = new (std::nothrow) ZipFile(); ZipFile *zip = new (std::nothrow) ZipFile();
@ -534,13 +639,16 @@ ZipFile *ZipFile::createWithBuffer(const void* buffer, uLong size)
ZipFile::ZipFile() ZipFile::ZipFile()
: _data(new ZipFilePrivate) : _data(new ZipFilePrivate)
{ {
fillFunctionOverrides();
_data->zipFile = nullptr; _data->zipFile = nullptr;
} }
ZipFile::ZipFile(const std::string &zipFile, const std::string &filter) ZipFile::ZipFile(const std::string &zipFile, const std::string &filter)
: _data(new ZipFilePrivate) : _data(new ZipFilePrivate)
{ {
_data->zipFile = unzOpen(zipFile.c_str()); fillFunctionOverrides();
_data->zipFileName = zipFile;
_data->zipFile = unzOpen2(zipFile.c_str(), &_functionOverrides);
setFilter(filter); setFilter(filter);
} }
@ -877,4 +985,17 @@ unsigned char* ZipFile::getFileDataFromZip(const std::string& zipFilePath, const
return buffer; return buffer;
} }
void ZipFile::fillFunctionOverrides()
{
_functionOverrides.zopen_file = ZipFile_open_file_func;
_functionOverrides.zopendisk_file = ZipFile_opendisk_file_func;
_functionOverrides.zread_file = ZipFile_read_file_func;
_functionOverrides.zwrite_file = ZipFile_write_file_func;
_functionOverrides.ztell_file = ZipFile_tell_file_func;
_functionOverrides.zseek_file = ZipFile_seek_file_func;
_functionOverrides.zclose_file = ZipFile_close_file_func;
_functionOverrides.zerror_file = ZipFile_error_file_func;
_functionOverrides.opaque = _data;
}
NS_CC_END NS_CC_END

View File

@ -29,6 +29,8 @@ THE SOFTWARE.
#define __SUPPORT_ZIPUTILS_H__ #define __SUPPORT_ZIPUTILS_H__
/// @cond DO_NOT_SHOW /// @cond DO_NOT_SHOW
#include <ioapi.h>
#include "platform/CCPlatformMacros.h" #include "platform/CCPlatformMacros.h"
#include "platform/CCFileUtils.h" #include "platform/CCFileUtils.h"
#include <string> #include <string>
@ -316,6 +318,7 @@ namespace cocos2d
CC_DEPRECATED() static unsigned char* getFileDataFromZip(const std::string& zipFilePath, const std::string& filename, ssize_t* size); CC_DEPRECATED() static unsigned char* getFileDataFromZip(const std::string& zipFilePath, const std::string& filename, ssize_t* size);
private: private:
void fillFunctionOverrides();
/* Only used internal for createWithBuffer() */ /* Only used internal for createWithBuffer() */
ZipFile(); ZipFile();
@ -324,6 +327,7 @@ namespace cocos2d
/** Internal data like zip file pointer / file list array and so on */ /** Internal data like zip file pointer / file list array and so on */
ZipFilePrivate *_data; ZipFilePrivate *_data;
zlib_filefunc_def _functionOverrides{};
}; };
} // end of namespace cocos2d } // end of namespace cocos2d

View File

@ -19,14 +19,54 @@ public:
APPEND, APPEND,
}; };
/**
* Open a file
* @param path file to open
* @param mode File open mode, being READ | WRITE | APPEND
* @return true if successful, false if not
*/
virtual bool open(const std::string& path, FileStream::Mode mode) = 0; virtual bool open(const std::string& path, FileStream::Mode mode) = 0;
/**
* Close a file stream
* @return 0 if successful, -1 if not
*/
virtual int close() = 0; virtual int close() = 0;
/**
* Seek to position in a file stream
* @param offset how many bytes to move within the stream
* @param origin SEEK_SET | SEEK_CUR | SEEK_END
* @return 0 if successful, -1 if not
*/
virtual int seek(long offset, int origin) = 0; virtual int seek(long offset, int origin) = 0;
/**
* Read data from file stream
* @param buf pointer to data
* @param size the amount of data to read in bytes
* @return amount of data read successfully, -1 if error
*/
virtual int read(void* buf, unsigned int size) = 0; virtual int read(void* buf, unsigned int size) = 0;
/**
* Write data to file stream
* @param buf pointer to data
* @param size the amount of data to write in bytes
* @return amount of data written successfully, -1 if error
*/
virtual int write(const void* buf, unsigned int size) = 0; virtual int write(const void* buf, unsigned int size) = 0;
/**
* Get the current position in the file stream
* @return current position, -1 if error
*/
virtual int tell() = 0; virtual int tell() = 0;
/**
* Get status of file stream
* @return true if open, false if closed
*/
virtual bool isOpen() const = 0; virtual bool isOpen() const = 0;
virtual operator bool() const { return isOpen(); } virtual operator bool() const { return isOpen(); }