From 1238a08662f2de1e0186593f999d74c297812b74 Mon Sep 17 00:00:00 2001 From: rh101 Date: Sun, 25 Apr 2021 02:39:47 +1000 Subject: [PATCH 1/7] Add support for FileStream in ZipUtils and ZipFile --- cocos/base/ZipUtils.cpp | 127 +++++++++++++++++++++++++++++++++++++++- cocos/base/ZipUtils.h | 4 ++ 2 files changed, 130 insertions(+), 1 deletion(-) diff --git a/cocos/base/ZipUtils.cpp b/cocos/base/ZipUtils.cpp index 903231acd5..86da37c365 100644 --- a/cocos/base/ZipUtils.cpp +++ b/cocos/base/ZipUtils.cpp @@ -511,6 +511,7 @@ struct ZipEntryInfo class ZipFilePrivate { public: + std::string zipFileName; unzFile zipFile; std::mutex zipFileMtx; std::unique_ptr memfs; @@ -520,6 +521,114 @@ public: 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; + + const std::string fsFilename = (char*)filename; + + return FileUtils::getInstance()->openFileStream(fsFilename, fsMode); +} + +voidpf ZipFile_opendisk_file_func(voidpf opaque, voidpf stream, uint32_t number_disk, int mode) +{ + voidpf ret = nullptr; + + 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) + { + auto* extensionBuffer = new char[5]; + snprintf(&extensionBuffer[0], 5, ".z%02u", number_disk + 1); + diskFilename.replace(pos, 4, extensionBuffer); + delete[] extensionBuffer; + ret = ZipFile_open_file_func(opaque, diskFilename.c_str(), mode); + } + + return ret; +} + +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 *zip = new (std::nothrow) ZipFile(); @@ -534,13 +643,16 @@ ZipFile *ZipFile::createWithBuffer(const void* buffer, uLong size) ZipFile::ZipFile() : _data(new ZipFilePrivate) { + fillFunctionOverrides(); _data->zipFile = nullptr; } ZipFile::ZipFile(const std::string &zipFile, const std::string &filter) : _data(new ZipFilePrivate) { - _data->zipFile = unzOpen(zipFile.c_str()); + fillFunctionOverrides(); + _data->zipFileName = zipFile; + _data->zipFile = unzOpen2(zipFile.c_str(), &_functionOverrides); setFilter(filter); } @@ -877,4 +989,17 @@ unsigned char* ZipFile::getFileDataFromZip(const std::string& zipFilePath, const 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 diff --git a/cocos/base/ZipUtils.h b/cocos/base/ZipUtils.h index 8bc861f4ee..956609fd55 100644 --- a/cocos/base/ZipUtils.h +++ b/cocos/base/ZipUtils.h @@ -29,6 +29,8 @@ THE SOFTWARE. #define __SUPPORT_ZIPUTILS_H__ /// @cond DO_NOT_SHOW +#include + #include "platform/CCPlatformMacros.h" #include "platform/CCFileUtils.h" #include @@ -316,6 +318,7 @@ namespace cocos2d CC_DEPRECATED() static unsigned char* getFileDataFromZip(const std::string& zipFilePath, const std::string& filename, ssize_t* size); private: + void fillFunctionOverrides(); /* Only used internal for createWithBuffer() */ ZipFile(); @@ -324,6 +327,7 @@ namespace cocos2d /** Internal data like zip file pointer / file list array and so on */ ZipFilePrivate *_data; + zlib_filefunc_def _functionOverrides; }; } // end of namespace cocos2d From 72bc0bf818525ac6a38cd1cd3109495bac70c6b5 Mon Sep 17 00:00:00 2001 From: rh101 Date: Sun, 25 Apr 2021 02:43:03 +1000 Subject: [PATCH 2/7] Removed redundant code --- cocos/base/ZipUtils.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/cocos/base/ZipUtils.cpp b/cocos/base/ZipUtils.cpp index 86da37c365..9521855eb1 100644 --- a/cocos/base/ZipUtils.cpp +++ b/cocos/base/ZipUtils.cpp @@ -554,9 +554,7 @@ voidpf ZipFile_open_file_func(voidpf opaque, const char* filename, int mode) else return nullptr; - const std::string fsFilename = (char*)filename; - - return FileUtils::getInstance()->openFileStream(fsFilename, fsMode); + return FileUtils::getInstance()->openFileStream(filename, fsMode); } voidpf ZipFile_opendisk_file_func(voidpf opaque, voidpf stream, uint32_t number_disk, int mode) From f68521c4d001efdbd07dbe881d825a4bae78b868 Mon Sep 17 00:00:00 2001 From: rh101 Date: Sun, 25 Apr 2021 02:45:04 +1000 Subject: [PATCH 3/7] Minor code cleanup --- cocos/base/ZipUtils.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/cocos/base/ZipUtils.cpp b/cocos/base/ZipUtils.cpp index 9521855eb1..4dc823290c 100644 --- a/cocos/base/ZipUtils.cpp +++ b/cocos/base/ZipUtils.cpp @@ -559,8 +559,6 @@ voidpf ZipFile_open_file_func(voidpf opaque, const char* filename, int mode) voidpf ZipFile_opendisk_file_func(voidpf opaque, voidpf stream, uint32_t number_disk, int mode) { - voidpf ret = nullptr; - if (stream == nullptr) return nullptr; @@ -575,10 +573,10 @@ voidpf ZipFile_opendisk_file_func(voidpf opaque, voidpf stream, uint32_t number_ snprintf(&extensionBuffer[0], 5, ".z%02u", number_disk + 1); diskFilename.replace(pos, 4, extensionBuffer); delete[] extensionBuffer; - ret = ZipFile_open_file_func(opaque, diskFilename.c_str(), mode); + return ZipFile_open_file_func(opaque, diskFilename.c_str(), mode); } - return ret; + return nullptr; } uint32_t ZipFile_read_file_func(voidpf opaque, voidpf stream, void* buf, uint32_t size) From 2cdd6881669b59eae3f495d15a3ab54c088d9752 Mon Sep 17 00:00:00 2001 From: rh101 Date: Sun, 25 Apr 2021 02:47:21 +1000 Subject: [PATCH 4/7] Initialise member variable --- cocos/base/ZipUtils.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos/base/ZipUtils.h b/cocos/base/ZipUtils.h index 956609fd55..664a5333e8 100644 --- a/cocos/base/ZipUtils.h +++ b/cocos/base/ZipUtils.h @@ -327,7 +327,7 @@ namespace cocos2d /** Internal data like zip file pointer / file list array and so on */ ZipFilePrivate *_data; - zlib_filefunc_def _functionOverrides; + zlib_filefunc_def _functionOverrides{}; }; } // end of namespace cocos2d From 521e2cad4cdfe4d5828a260a574f60fc7f7943b0 Mon Sep 17 00:00:00 2001 From: rh101 Date: Sun, 25 Apr 2021 12:15:56 +1000 Subject: [PATCH 5/7] Verify the amount of string space we have to replace the zip extension --- cocos/base/ZipUtils.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/cocos/base/ZipUtils.cpp b/cocos/base/ZipUtils.cpp index 4dc823290c..68a2186ba5 100644 --- a/cocos/base/ZipUtils.cpp +++ b/cocos/base/ZipUtils.cpp @@ -569,9 +569,10 @@ voidpf ZipFile_opendisk_file_func(voidpf opaque, voidpf stream, uint32_t number_ if (pos != std::string::npos && pos != 0) { - auto* extensionBuffer = new char[5]; - snprintf(&extensionBuffer[0], 5, ".z%02u", number_disk + 1); - diskFilename.replace(pos, 4, extensionBuffer); + 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); delete[] extensionBuffer; return ZipFile_open_file_func(opaque, diskFilename.c_str(), mode); } From ed177ce0848b16377432a65c7cd6e7d97f891838 Mon Sep 17 00:00:00 2001 From: rh101 Date: Sun, 25 Apr 2021 14:42:42 +1000 Subject: [PATCH 6/7] Removed incorrect delete statement --- cocos/base/ZipUtils.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/cocos/base/ZipUtils.cpp b/cocos/base/ZipUtils.cpp index 68a2186ba5..d9c14b5b1d 100644 --- a/cocos/base/ZipUtils.cpp +++ b/cocos/base/ZipUtils.cpp @@ -573,7 +573,6 @@ voidpf ZipFile_opendisk_file_func(voidpf opaque, voidpf stream, uint32_t number_ 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); - delete[] extensionBuffer; return ZipFile_open_file_func(opaque, diskFilename.c_str(), mode); } From 3d8884721f697c6c3213f838c560b5df191b4f9e Mon Sep 17 00:00:00 2001 From: rh101 Date: Sun, 25 Apr 2021 15:27:25 +1000 Subject: [PATCH 7/7] Add function comments to detail the expected parameters and return values of a FileStream --- cocos/platform/CCFileStream.h | 40 +++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/cocos/platform/CCFileStream.h b/cocos/platform/CCFileStream.h index 68df1831d8..83cf790430 100644 --- a/cocos/platform/CCFileStream.h +++ b/cocos/platform/CCFileStream.h @@ -19,14 +19,54 @@ public: 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; + + /** + * Close a file stream + * @return 0 if successful, -1 if not + */ 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; + + /** + * 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; + /** + * 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; + + /** + * Get the current position in the file stream + * @return current position, -1 if error + */ virtual int tell() = 0; + + /** + * Get status of file stream + * @return true if open, false if closed + */ virtual bool isOpen() const = 0; virtual operator bool() const { return isOpen(); }