diff --git a/cocos/base/ZipUtils.cpp b/cocos/base/ZipUtils.cpp index 0adb96ea996c..22d5c29305e0 100644 --- a/cocos/base/ZipUtils.cpp +++ b/cocos/base/ZipUtils.cpp @@ -43,6 +43,7 @@ #include "base/ccMacros.h" #include "platform/CCFileUtils.h" #include +#include // minizip 1.2.0 is same with other platforms #define unzGoToFirstFile64(A,B,C,D) unzGoToFirstFile2(A,B,C,D, NULL, 0, NULL, 0) @@ -511,6 +512,7 @@ class ZipFilePrivate { public: unzFile zipFile; + std::mutex zipFileMtx; std::unique_ptr memfs; // std::unordered_map is faster if available on the platform @@ -655,10 +657,12 @@ unsigned char *ZipFile::getFileData(const std::string &fileName, ssize_t *size) CC_BREAK_IF(!_data->zipFile); CC_BREAK_IF(fileName.empty()); - ZipFilePrivate::FileListContainer::const_iterator it = _data->fileList.find(fileName); + ZipFilePrivate::FileListContainer::iterator it = _data->fileList.find(fileName); CC_BREAK_IF(it == _data->fileList.end()); - ZipEntryInfo fileInfo = it->second; + ZipEntryInfo& fileInfo = it->second; + + std::unique_lock lck(_data->zipFileMtx); int nRet = unzGoToFilePos(_data->zipFile, &fileInfo.pos); CC_BREAK_IF(UNZ_OK != nRet); @@ -688,11 +692,13 @@ bool ZipFile::getFileData(const std::string &fileName, ResizableBuffer* buffer) CC_BREAK_IF(!_data->zipFile); CC_BREAK_IF(fileName.empty()); - ZipFilePrivate::FileListContainer::const_iterator it = _data->fileList.find(fileName); + ZipFilePrivate::FileListContainer::iterator it = _data->fileList.find(fileName); CC_BREAK_IF(it == _data->fileList.end()); - ZipEntryInfo fileInfo = it->second; + ZipEntryInfo& fileInfo = it->second; + std::unique_lock lck(_data->zipFileMtx); + int nRet = unzGoToFilePos(_data->zipFile, &fileInfo.pos); CC_BREAK_IF(UNZ_OK != nRet); @@ -757,4 +763,77 @@ bool ZipFile::initWithBuffer(const void *buffer, uLong size) return true; } +bool ZipFile::zfopen(const std::string& fileName, ZipFileStream* zfs) +{ + if (!zfs) return false; + auto it = _data->fileList.find(fileName); + if (it != _data->fileList.end()) { + zfs->entry = &it->second; + zfs->offset = 0; + return true; + } + zfs->entry = nullptr; + zfs->offset = -1; + return false; +} + +int ZipFile::zfread(ZipFileStream* zfs, void* buf, unsigned int size) +{ + int n = 0; + do { + CC_BREAK_IF(zfs == nullptr || zfs->offset >= zfs->entry->uncompressed_size); + + std::unique_lock lck(_data->zipFileMtx); + + int nRet = unzGoToFilePos(_data->zipFile, &zfs->entry->pos); + CC_BREAK_IF(UNZ_OK != nRet); + + nRet = unzOpenCurrentFile(_data->zipFile); + unzSeek64(_data->zipFile, zfs->offset, SEEK_SET); + n = unzReadCurrentFile(_data->zipFile, buf, size); + if (n > 0) + zfs->offset += n; + + unzCloseCurrentFile(_data->zipFile); + + } while (false); + + return n; +} + +long ZipFile::zfseek(ZipFileStream* zfs, long offset, int origin) +{ + long result = -1; + if (zfs != nullptr) { + switch (origin) { + case SEEK_SET: + result = offset; + break; + case SEEK_CUR: + result = zfs->offset + offset; + break; + case SEEK_END: + result = (long)zfs->entry->uncompressed_size + offset; + break; + default:; + } + + if (result >= 0) { + zfs->offset = result; + } + else + result = -1; + } + + return result; +} +void ZipFile::zfclose(ZipFileStream* zfs) +{ + if (zfs != nullptr && zfs->entry != nullptr) { + zfs->entry = nullptr; + zfs->offset = -1; + } +} + + NS_CC_END diff --git a/cocos/base/ZipUtils.h b/cocos/base/ZipUtils.h index ab8851a88b81..edd8870c3229 100644 --- a/cocos/base/ZipUtils.h +++ b/cocos/base/ZipUtils.h @@ -207,9 +207,15 @@ typedef struct unz_file_info_s unz_file_info; }; // forward declaration + struct ZipEntryInfo; class ZipFilePrivate; struct unz_file_info_s; + struct ZipFileStream + { + ZipEntryInfo* entry; + long offset; + }; /** * Zip file - reader helper class. * @@ -285,8 +291,17 @@ typedef struct unz_file_info_s unz_file_info; std::string getFirstFilename(); std::string getNextFilename(); - + static ZipFile *createWithBuffer(const void* buffer, unsigned long size); + + /** + * zipFile Streaming support, !!!important, the file in zip must no compress level, otherwise + * stream seek doesn't work. + */ + bool zfopen(const std::string& fileName, ZipFileStream* zfs); + int zfread(ZipFileStream* zfs, void* buf, unsigned int size); + long zfseek(ZipFileStream* zfs, long offset, int origin); + void zfclose(ZipFileStream* zfs); private: /* Only used internal for createWithBuffer() */ diff --git a/cocos/platform/PXFileStream.cpp b/cocos/platform/PXFileStream.cpp index c5667502af91..7e0e479dc44c 100644 --- a/cocos/platform/PXFileStream.cpp +++ b/cocos/platform/PXFileStream.cpp @@ -30,49 +30,49 @@ NS_CC_BEGIN - struct PXIoF { - int(*read)(PXFileHandle& handle, void*, unsigned int); - long(*seek)(PXFileHandle& handle, long, int); - int(*close)(PXFileHandle& handle); - }; +struct PXIoF { + int(*read)(PXFileHandle& handle, void*, unsigned int); + long(*seek)(PXFileHandle& handle, long, int); + int(*close)(PXFileHandle& handle); +}; static int pfs_posix_open(const std::string& path, int mode, PXFileHandle& handle) { switch (mode) { - case PXFileStream::kModeReadOnly: - handle._fd = posix_open(path.c_str(), O_READ_FLAGS); - break; - case PXFileStream::kModeWrite: - handle._fd = posix_open(path.c_str(), O_WRITE_FLAGS); - break; - case PXFileStream::kModeAppend: - handle._fd = posix_open(path.c_str(), O_APPEND_FLAGS); - break; - default: - handle._fd = -1; + case PXFileStream::kModeReadOnly: + handle._fd = posix_open(path.c_str(), O_READ_FLAGS); + break; + case PXFileStream::kModeWrite: + handle._fd = posix_open(path.c_str(), O_WRITE_FLAGS); + break; + case PXFileStream::kModeAppend: + handle._fd = posix_open(path.c_str(), O_APPEND_FLAGS); + break; + default: + handle._fd = -1; } return handle._fd; } - // posix standard wrappers - static int pfs_posix_read(PXFileHandle& handle, void* buf, unsigned int size){ return posix_read(handle._fd, buf, size); } - static long pfs_posix_seek(PXFileHandle& handle, long offst, int origin){ return posix_lseek(handle._fd, offst, origin); } - static int pfs_posix_close(PXFileHandle& handle) { - int fd = handle._fd; - if (fd != -1) { - handle._fd = -1; - return posix_close(fd); - } - return 0; - } - static PXIoF pfs_posix_iof = { - pfs_posix_read, - pfs_posix_seek, - pfs_posix_close - }; +// posix standard wrappers +static int pfs_posix_read(PXFileHandle& handle, void* buf, unsigned int size) { return posix_read(handle._fd, buf, size); } +static long pfs_posix_seek(PXFileHandle& handle, long offst, int origin) { return posix_lseek(handle._fd, offst, origin); } +static int pfs_posix_close(PXFileHandle& handle) { + int fd = handle._fd; + if (fd != -1) { + handle._fd = -1; + return posix_close(fd); + } + return 0; +} +static PXIoF pfs_posix_iof = { + pfs_posix_read, + pfs_posix_seek, + pfs_posix_close +}; #if CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID - // android AssetManager wrappers +// android AssetManager wrappers static int pfs_asset_read(PXFileHandle& handle, void* buf, unsigned int size) { return AAsset_read(handle._asset, buf, size); } static long pfs_asset_seek(PXFileHandle& handle, long offst, int origin) { return AAsset_seek(handle._asset, offst, origin); } static int pfs_asset_close(PXFileHandle& handle) { @@ -89,13 +89,10 @@ static PXIoF pfs_asset_iof = { }; // android obb -static int pfs_obb_read(PXFileHandle& handle, void* buf, unsigned int size) { return FileUtilsAndroid::getObbFile()->uzfsRead(handle._uzfs, buf, size); } -static long pfs_obb_seek(PXFileHandle& handle, long offst, int origin) { return FileUtilsAndroid::getObbFile()->uzfsSeek(handle._uzfs, offst, origin); } +static int pfs_obb_read(PXFileHandle& handle, void* buf, unsigned int size) { return FileUtilsAndroid::getObbFile()->zfread(&handle._zfs, buf, size); } +static long pfs_obb_seek(PXFileHandle& handle, long offset, int origin) { return FileUtilsAndroid::getObbFile()->zfseek(&handle._zfs, offset, origin); } static int pfs_obb_close(PXFileHandle& handle) { - if (handle._uzfs != nullptr) { - FileUtilsAndroid::getObbFile()->uzfsClose(handle._uzfs); - handle._uzfs = nullptr; - } + FileUtilsAndroid::getObbFile()->zfclose(&handle._zfs); return 0; } static PXIoF pfs_obb_iof = { @@ -133,13 +130,13 @@ bool PXFileStream::open(const std::string& path, int mode) } auto obb = FileUtilsAndroid::getObbFile(); - if(obb != nullptr && (_handle._uzfs = obb->uzfsOpen(relativePath)) != nullptr){ + if (obb != nullptr && obb->zfopen(relativePath, &_handle._zfs)) { this->_iof = &pfs_obb_iof; return true; } else { - AAssetManager *asMgr = FileUtilsAndroid::getAssetManager(); - AAsset *asset = AAssetManager_open(asMgr, relativePath.c_str(), AASSET_MODE_UNKNOWN); + AAssetManager* asMgr = FileUtilsAndroid::getAssetManager(); + AAsset* asset = AAssetManager_open(asMgr, relativePath.c_str(), AASSET_MODE_UNKNOWN); if (asset == nullptr) return false; diff --git a/cocos/platform/PXFileStream.h b/cocos/platform/PXFileStream.h index e47cede660d0..d82b4cce5f35 100644 --- a/cocos/platform/PXFileStream.h +++ b/cocos/platform/PXFileStream.h @@ -20,6 +20,7 @@ #include #include #include +#include "base/ZipUtils.h" #endif NS_CC_BEGIN @@ -29,7 +30,7 @@ union PXFileHandle { int _fd = -1; #if CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID AAsset* _asset; - UnzFileStream* _uzfs; + ZipFileStream _zfs; #endif }; diff --git a/cocos/platform/android/CCFileUtils-android.cpp b/cocos/platform/android/CCFileUtils-android.cpp index e53bbf37ae9d..7580c64c03db 100644 --- a/cocos/platform/android/CCFileUtils-android.cpp +++ b/cocos/platform/android/CCFileUtils-android.cpp @@ -192,8 +192,8 @@ bool FileUtilsAndroid::isFileExistInternal(const std::string& strFilePath) const } else { - struct stat64 st; - if (0 == ::stat64(strFilePath.c_str(), &st)) + struct stat st; + if (::stat(strFilePath.c_str(), &st) == 0) bFound = S_ISREG(st.st_mode); } return bFound; diff --git a/external/config.json b/external/config.json index 0c82ddd5f9b4..87a9c1e3fc88 100644 --- a/external/config.json +++ b/external/config.json @@ -1,6 +1,6 @@ { - "version": "deps-10", - "zip_file_size": "105242860", + "version": "v11", + "zip_file_size": "105241257", "repo_name": "engine-v5-3rd", "repo_parent": "https://github.com/simdsoft/", "move_dirs": {