mirror of https://github.com/axmolengine/axmol.git
Merge pull request #342 from rh101/vfs-support
Ensure FileStream is used for file access where possible
This commit is contained in:
commit
5664291631
|
@ -183,7 +183,8 @@ bool FontFreeType::createFontObject(const std::string &fontName, float fontSize)
|
||||||
std::unique_ptr<FT_StreamRec> fts(new FT_StreamRec());
|
std::unique_ptr<FT_StreamRec> fts(new FT_StreamRec());
|
||||||
fts->read = ft_stream_read_callback;
|
fts->read = ft_stream_read_callback;
|
||||||
fts->close = ft_stream_close_callback;
|
fts->close = ft_stream_close_callback;
|
||||||
fts->size = fs->seek(0, SEEK_END);
|
fs->seek(0, SEEK_END);
|
||||||
|
fts->size = fs->tell();
|
||||||
fs->seek(0, SEEK_SET);
|
fs->seek(0, SEEK_SET);
|
||||||
|
|
||||||
fts->descriptor.pointer = fs;
|
fts->descriptor.pointer = fs;
|
||||||
|
|
|
@ -68,7 +68,7 @@ protected:
|
||||||
AudioDecoderOgg();
|
AudioDecoderOgg();
|
||||||
~AudioDecoderOgg();
|
~AudioDecoderOgg();
|
||||||
|
|
||||||
FileStream* _fileStream;
|
FileStream* _fileStream = nullptr;
|
||||||
OggVorbis_File _vf;
|
OggVorbis_File _vf;
|
||||||
|
|
||||||
friend class AudioDecoderManager;
|
friend class AudioDecoderManager;
|
||||||
|
|
|
@ -61,7 +61,7 @@ namespace cocos2d {
|
||||||
|
|
||||||
static int minimp3_seek_r(uint64_t position, void* user_data)
|
static int minimp3_seek_r(uint64_t position, void* user_data)
|
||||||
{
|
{
|
||||||
return ((FileStream*)user_data)->seek(position, SEEK_SET) >= 0 ? 0 : -1;
|
return ((FileStream*)user_data)->seek(position, SEEK_SET) < 0 ? -1 : 0;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
static bool __mp3Inited = false;
|
static bool __mp3Inited = false;
|
||||||
|
|
|
@ -44,8 +44,7 @@ namespace cocos2d {
|
||||||
|
|
||||||
static int ov_fseek_r(void * handle, ogg_int64_t offset, int whence)
|
static int ov_fseek_r(void * handle, ogg_int64_t offset, int whence)
|
||||||
{
|
{
|
||||||
auto n = ((FileStream*)handle)->seek(offset, whence);
|
return ((FileStream*)handle)->seek(offset, whence) < 0 ? -1 : 0;
|
||||||
return n >= 0 ? 0 : -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static long ov_ftell_r(void * handle)
|
static long ov_ftell_r(void * handle)
|
||||||
|
|
|
@ -141,7 +141,7 @@ namespace cocos2d {
|
||||||
ALOGW("The wav format %d doesn't supported currently!", (int)fmtInfo.AudioFormat);
|
ALOGW("The wav format %d doesn't supported currently!", (int)fmtInfo.AudioFormat);
|
||||||
fileStream->close();
|
fileStream->close();
|
||||||
assert(false);
|
assert(false);
|
||||||
return false;;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return wav_scan_chunk(wavf, WAV_DATA_ID, &h->PcmData, nullptr, 0);
|
return wav_scan_chunk(wavf, WAV_DATA_ID, &h->PcmData, nullptr, 0);
|
||||||
|
@ -154,7 +154,8 @@ namespace cocos2d {
|
||||||
|
|
||||||
static int wav_seek(WAV_FILE* wavf, int offset)
|
static int wav_seek(WAV_FILE* wavf, int offset)
|
||||||
{
|
{
|
||||||
auto newOffset = wavf->Stream->seek(wavf->PcmDataOffset + offset, SEEK_SET);
|
wavf->Stream->seek(wavf->PcmDataOffset + offset, SEEK_SET);
|
||||||
|
const auto newOffset = wavf->Stream->tell();
|
||||||
return newOffset >= wavf->PcmDataOffset ? newOffset - wavf->PcmDataOffset : -1;
|
return newOffset >= wavf->PcmDataOffset ? newOffset - wavf->PcmDataOffset : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1491,8 +1491,8 @@ void Console::commandUpload(int fd)
|
||||||
static std::string writablePath = FileUtils::getInstance()->getWritablePath();
|
static std::string writablePath = FileUtils::getInstance()->getWritablePath();
|
||||||
std::string filepath = writablePath + std::string(buf);
|
std::string filepath = writablePath + std::string(buf);
|
||||||
|
|
||||||
FILE* fp = fopen(filepath.c_str(), "wb");
|
auto* fs = FileUtils::getInstance()->openFileStream(filepath, FileStream::Mode::WRITE);
|
||||||
if(!fp)
|
if(!fs)
|
||||||
{
|
{
|
||||||
const char err[] = "can't create file!\n";
|
const char err[] = "can't create file!\n";
|
||||||
Console::Utility::sendToConsole(fd, err, strlen(err));
|
Console::Utility::sendToConsole(fd, err, strlen(err));
|
||||||
|
@ -1517,11 +1517,12 @@ void Console::commandUpload(int fd)
|
||||||
int dt = base64Decode(in, 4, &decode);
|
int dt = base64Decode(in, 4, &decode);
|
||||||
if (dt > 0)
|
if (dt > 0)
|
||||||
{
|
{
|
||||||
fwrite(decode, dt, 1, fp);
|
fs->write(decode, dt);
|
||||||
}
|
}
|
||||||
free(decode);
|
free(decode);
|
||||||
}
|
}
|
||||||
fclose(fp);
|
fs->close();
|
||||||
|
delete fs;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Console::commandVersion(int fd, const std::string& /*args*/)
|
void Console::commandVersion(int fd, const std::string& /*args*/)
|
||||||
|
|
|
@ -154,7 +154,8 @@ public:
|
||||||
_checksumFileName = filename + ".chksum";
|
_checksumFileName = filename + ".chksum";
|
||||||
|
|
||||||
_fsMd5 = FileUtils::getInstance()->openFileStream(_checksumFileName, FileStream::Mode::WRITE);
|
_fsMd5 = FileUtils::getInstance()->openFileStream(_checksumFileName, FileStream::Mode::WRITE);
|
||||||
if (_fsMd5->seek(0, SEEK_END) != sizeof(md5_state_s)) {
|
_fsMd5->seek(0, SEEK_END);
|
||||||
|
if (_fsMd5->tell() != sizeof(md5_state_s)) {
|
||||||
md5_init(&_md5State);
|
md5_init(&_md5State);
|
||||||
} else {
|
} else {
|
||||||
_fsMd5->seek(0, SEEK_SET);
|
_fsMd5->seek(0, SEEK_SET);
|
||||||
|
@ -819,10 +820,10 @@ void DownloaderCURL::_onDownloadFinished(TaskWrapper&& wrapper, int checkState)
|
||||||
|
|
||||||
if (checkState & kCheckSumStateSucceed) // No need download
|
if (checkState & kCheckSumStateSucceed) // No need download
|
||||||
{
|
{
|
||||||
FileStream* fsOrigin =
|
auto* fsOrigin = pFileUtils->openFileStream(coTask._fileName, FileStream::Mode::READ);
|
||||||
FileUtils::getInstance()->openFileStream(coTask._fileName, FileStream::Mode::READ);
|
|
||||||
if (fsOrigin) {
|
if (fsOrigin) {
|
||||||
task.progressInfo.totalBytesExpected = fsOrigin->seek(0, SEEK_END);
|
fsOrigin->seek(0, SEEK_END);
|
||||||
|
task.progressInfo.totalBytesExpected = fsOrigin->tell();
|
||||||
task.progressInfo.bytesReceived = task.progressInfo.totalBytesExpected;
|
task.progressInfo.bytesReceived = task.progressInfo.totalBytesExpected;
|
||||||
task.progressInfo.totalBytesReceived = task.progressInfo.totalBytesExpected;
|
task.progressInfo.totalBytesReceived = task.progressInfo.totalBytesExpected;
|
||||||
task.progressInfo.speedInBytes = task.progressInfo.totalBytesExpected;
|
task.progressInfo.speedInBytes = task.progressInfo.totalBytesExpected;
|
||||||
|
|
|
@ -409,7 +409,7 @@ void HttpClient::enableCookies(const char* cookieFile)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_cookieFilename = (FileUtils::getInstance()->getWritablePath() + "cookieFile.txt");
|
_cookieFilename = (FileUtils::getInstance()->getNativeWritableAbsolutePath() + "cookieFile.txt");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -497,20 +497,17 @@ void FileUtils::writeDataToFile(Data data, const std::string& fullPath, std::fun
|
||||||
|
|
||||||
bool FileUtils::writeBinaryToFile(const void* data, size_t dataSize, const std::string& fullPath)
|
bool FileUtils::writeBinaryToFile(const void* data, size_t dataSize, const std::string& fullPath)
|
||||||
{
|
{
|
||||||
const char* mode = "wb";
|
|
||||||
|
|
||||||
CCASSERT(!fullPath.empty() && dataSize > 0, "Invalid parameters.");
|
CCASSERT(!fullPath.empty() && dataSize > 0, "Invalid parameters.");
|
||||||
|
|
||||||
auto fileutils = FileUtils::getInstance();
|
auto* fileUtils = FileUtils::getInstance();
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
auto* fileStream = fileUtils->openFileStream(fullPath, FileStream::Mode::WRITE);
|
||||||
// Read the file from hardware
|
// Read the file from hardware
|
||||||
FILE* fp = fopen(fullPath.c_str(), mode);
|
CC_BREAK_IF(!fileStream);
|
||||||
CC_BREAK_IF(!fp);
|
|
||||||
fwrite(data, dataSize, 1, fp);
|
|
||||||
|
|
||||||
fclose(fp);
|
|
||||||
|
|
||||||
|
fileStream->write(data, dataSize);
|
||||||
|
delete fileStream;
|
||||||
return true;
|
return true;
|
||||||
} while (0);
|
} while (0);
|
||||||
|
|
||||||
|
@ -571,40 +568,51 @@ FileUtils::Status FileUtils::getContents(const std::string& filename, ResizableB
|
||||||
if (filename.empty())
|
if (filename.empty())
|
||||||
return Status::NotExists;
|
return Status::NotExists;
|
||||||
|
|
||||||
auto fs = FileUtils::getInstance();
|
auto fileUtils = FileUtils::getInstance();
|
||||||
|
|
||||||
std::string fullPath = fs->fullPathForFilename(filename);
|
const auto fullPath = fileUtils->fullPathForFilename(filename);
|
||||||
if (fullPath.empty())
|
|
||||||
return Status::NotExists;
|
|
||||||
|
|
||||||
FILE *fp = fopen(fullPath.c_str(), "rb");
|
auto* fileStream = fileUtils->openFileStream(fullPath, FileStream::Mode::READ);
|
||||||
if (!fp)
|
if (!fileStream)
|
||||||
return Status::OpenFailed;
|
return Status::OpenFailed;
|
||||||
|
|
||||||
struct AutoFileHandle {
|
if (fileStream->seek(0, SEEK_END) != 0)
|
||||||
void operator()(FILE* fp) {
|
{
|
||||||
fclose(fp);
|
delete fileStream;
|
||||||
}
|
return Status::ObtainSizeFailed;
|
||||||
};
|
}
|
||||||
std::unique_ptr<FILE, AutoFileHandle> autohandle(fp);
|
|
||||||
|
|
||||||
struct stat statBuf;
|
const auto size = fileStream->tell();
|
||||||
if (fstat(fileno(fp), &statBuf) == -1)
|
if (size == 0)
|
||||||
return Status::ReadFailed;
|
{
|
||||||
|
delete fileStream;
|
||||||
|
return Status::OK;
|
||||||
|
}
|
||||||
|
|
||||||
if (!(statBuf.st_mode & S_IFREG))
|
if (size < 0)
|
||||||
return Status::NotRegularFileType;
|
{
|
||||||
|
delete fileStream;
|
||||||
|
return Status::ObtainSizeFailed;
|
||||||
|
}
|
||||||
|
|
||||||
size_t size = statBuf.st_size;
|
if (size > ULONG_MAX)
|
||||||
|
{
|
||||||
|
delete fileStream;
|
||||||
|
return Status::TooLarge;
|
||||||
|
}
|
||||||
|
|
||||||
buffer->resize(size);
|
buffer->resize(size);
|
||||||
size_t readsize = fread(buffer->buffer(), 1, statBuf.st_size, fp);
|
|
||||||
|
|
||||||
if (readsize < size) {
|
fileStream->seek(0, SEEK_SET);
|
||||||
buffer->resize(readsize);
|
|
||||||
|
const auto sizeRead = fileStream->read(buffer->buffer(), size);
|
||||||
|
if (sizeRead < size) {
|
||||||
|
buffer->resize(sizeRead);
|
||||||
|
delete fileStream;
|
||||||
return Status::ReadFailed;
|
return Status::ReadFailed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
delete fileStream;
|
||||||
return Status::OK;
|
return Status::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -151,7 +151,8 @@ int PosixFileStream::close()
|
||||||
|
|
||||||
int PosixFileStream::seek(long offset, int origin)
|
int PosixFileStream::seek(long offset, int origin)
|
||||||
{
|
{
|
||||||
return static_cast<int>(_iof->seek(_handle, offset, origin));
|
const auto result = _iof->seek(_handle, offset, origin); // this returns -1 for error, and resulting offset on success
|
||||||
|
return result < 0 ? -1 : 0; // return 0 for success
|
||||||
}
|
}
|
||||||
|
|
||||||
int PosixFileStream::read(void* buf, unsigned int size)
|
int PosixFileStream::read(void* buf, unsigned int size)
|
||||||
|
|
|
@ -345,11 +345,10 @@ public:
|
||||||
std::string lowerCasePath = fontPath;
|
std::string lowerCasePath = fontPath;
|
||||||
std::transform(lowerCasePath.begin(), lowerCasePath.end(), lowerCasePath.begin(), ::tolower);
|
std::transform(lowerCasePath.begin(), lowerCasePath.end(), lowerCasePath.begin(), ::tolower);
|
||||||
if ( lowerCasePath.find(".ttf") != std::string::npos ) {
|
if ( lowerCasePath.find(".ttf") != std::string::npos ) {
|
||||||
fontPath = cocos2d::FileUtils::getInstance()->fullPathForFilename(fontPath.c_str());
|
fontPath = cocos2d::FileUtils::getInstance()->fullPathForFilename(fontPath);
|
||||||
|
auto* fileStream = cocos2d::FileUtils::getInstance()->openFileStream(fontPath, FileStream::Mode::READ);
|
||||||
FILE *f = fopen(fontPath.c_str(), "r");
|
if ( fileStream ) {
|
||||||
if ( f ) {
|
delete fileStream;
|
||||||
fclose(f);
|
|
||||||
fontCache.insert(std::pair<std::string, std::string>(family_name, fontPath));
|
fontCache.insert(std::pair<std::string, std::string>(family_name, fontPath));
|
||||||
return fontPath;
|
return fontPath;
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,6 +50,116 @@ using namespace cocos2d::network;
|
||||||
#define BUFFER_SIZE 8192
|
#define BUFFER_SIZE 8192
|
||||||
#define MAX_FILENAME 512
|
#define MAX_FILENAME 512
|
||||||
|
|
||||||
|
class AssetManagerZipFileInfo
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
std::string zipFileName{};
|
||||||
|
};
|
||||||
|
|
||||||
|
// unzip overrides to support FileStream
|
||||||
|
long AssetManager_tell_file_func(voidpf opaque, voidpf stream)
|
||||||
|
{
|
||||||
|
if (stream == nullptr)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
auto* fs = (FileStream*)stream;
|
||||||
|
|
||||||
|
return fs->tell();
|
||||||
|
}
|
||||||
|
|
||||||
|
long AssetManager_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 AssetManager_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 AssetManager_opendisk_file_func(voidpf opaque, voidpf stream, uint32_t number_disk, int mode)
|
||||||
|
{
|
||||||
|
if (stream == nullptr)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
const auto zipFileInfo = static_cast<AssetManagerZipFileInfo*>(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 AssetManager_open_file_func(opaque, diskFilename.c_str(), mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t AssetManager_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 AssetManager_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 AssetManager_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 AssetManager_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
|
||||||
|
|
||||||
// Implementation of AssetsManager
|
// Implementation of AssetsManager
|
||||||
|
|
||||||
AssetsManager::AssetsManager(const char* packageUrl/* =nullptr */, const char* versionFileUrl/* =nullptr */, const char* storagePath/* =nullptr */)
|
AssetsManager::AssetsManager(const char* packageUrl/* =nullptr */, const char* versionFileUrl/* =nullptr */, const char* storagePath/* =nullptr */)
|
||||||
|
@ -259,7 +369,17 @@ bool AssetsManager::uncompress()
|
||||||
{
|
{
|
||||||
// Open the zip file
|
// Open the zip file
|
||||||
string outFileName = _storagePath + TEMP_PACKAGE_FILE_NAME;
|
string outFileName = _storagePath + TEMP_PACKAGE_FILE_NAME;
|
||||||
unzFile zipfile = unzOpen(outFileName.c_str());
|
|
||||||
|
zlib_filefunc_def zipFunctionOverrides;
|
||||||
|
fillZipFunctionOverrides(zipFunctionOverrides);
|
||||||
|
|
||||||
|
AssetManagerZipFileInfo zipFileInfo;
|
||||||
|
zipFileInfo.zipFileName = outFileName;
|
||||||
|
|
||||||
|
zipFunctionOverrides.opaque = &zipFileInfo;
|
||||||
|
|
||||||
|
// Open the zip file
|
||||||
|
unzFile zipfile = unzOpen2(outFileName.c_str(), &zipFunctionOverrides);
|
||||||
if (! zipfile)
|
if (! zipfile)
|
||||||
{
|
{
|
||||||
CCLOG("can not open downloaded zip file %s", outFileName.c_str());
|
CCLOG("can not open downloaded zip file %s", outFileName.c_str());
|
||||||
|
@ -330,10 +450,9 @@ bool AssetsManager::uncompress()
|
||||||
while(index != std::string::npos)
|
while(index != std::string::npos)
|
||||||
{
|
{
|
||||||
const string dir=_storagePath+fileNameStr.substr(0,index);
|
const string dir=_storagePath+fileNameStr.substr(0,index);
|
||||||
|
|
||||||
FILE *out = fopen(dir.c_str(), "r");
|
auto* fsOut = FileUtils::getInstance()->openFileStream(dir, FileStream::Mode::READ);
|
||||||
|
if (!fsOut)
|
||||||
if(!out)
|
|
||||||
{
|
{
|
||||||
if (!FileUtils::getInstance()->createDirectory(dir))
|
if (!FileUtils::getInstance()->createDirectory(dir))
|
||||||
{
|
{
|
||||||
|
@ -348,13 +467,12 @@ bool AssetsManager::uncompress()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fclose(out);
|
delete fsOut;
|
||||||
}
|
}
|
||||||
|
|
||||||
startIndex=index+1;
|
startIndex=index+1;
|
||||||
|
|
||||||
index=fileNameStr.find('/',startIndex);
|
index=fileNameStr.find('/',startIndex);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Entry is a file, so extract it.
|
// Entry is a file, so extract it.
|
||||||
|
@ -368,8 +486,8 @@ bool AssetsManager::uncompress()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a file to store current file.
|
// Create a file to store current file.
|
||||||
FILE *out = fopen(fullPath.c_str(), "wb");
|
auto* fsOut = FileUtils::getInstance()->openFileStream(fullPath, FileStream::Mode::WRITE);
|
||||||
if (! out)
|
if (!fsOut)
|
||||||
{
|
{
|
||||||
CCLOG("can not open destination file %s", fullPath.c_str());
|
CCLOG("can not open destination file %s", fullPath.c_str());
|
||||||
unzCloseCurrentFile(zipfile);
|
unzCloseCurrentFile(zipfile);
|
||||||
|
@ -387,16 +505,17 @@ bool AssetsManager::uncompress()
|
||||||
CCLOG("can not read zip file %s, error code is %d", fileName, error);
|
CCLOG("can not read zip file %s, error code is %d", fileName, error);
|
||||||
unzCloseCurrentFile(zipfile);
|
unzCloseCurrentFile(zipfile);
|
||||||
unzClose(zipfile);
|
unzClose(zipfile);
|
||||||
|
delete fsOut;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (error > 0)
|
if (error > 0)
|
||||||
{
|
{
|
||||||
fwrite(readBuffer, error, 1, out);
|
fsOut->write(readBuffer, error);
|
||||||
}
|
}
|
||||||
} while(error > 0);
|
} while(error > 0);
|
||||||
|
|
||||||
fclose(out);
|
delete fsOut;
|
||||||
}
|
}
|
||||||
|
|
||||||
unzCloseCurrentFile(zipfile);
|
unzCloseCurrentFile(zipfile);
|
||||||
|
@ -510,4 +629,17 @@ AssetsManager* AssetsManager::create(const char* packageUrl, const char* version
|
||||||
return manager;
|
return manager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AssetsManager::fillZipFunctionOverrides(zlib_filefunc_def& zipFunctionOverrides)
|
||||||
|
{
|
||||||
|
zipFunctionOverrides.zopen_file = AssetManager_open_file_func;
|
||||||
|
zipFunctionOverrides.zopendisk_file = AssetManager_opendisk_file_func;
|
||||||
|
zipFunctionOverrides.zread_file = AssetManager_read_file_func;
|
||||||
|
zipFunctionOverrides.zwrite_file = AssetManager_write_file_func;
|
||||||
|
zipFunctionOverrides.ztell_file = AssetManager_tell_file_func;
|
||||||
|
zipFunctionOverrides.zseek_file = AssetManager_seek_file_func;
|
||||||
|
zipFunctionOverrides.zclose_file = AssetManager_close_file_func;
|
||||||
|
zipFunctionOverrides.zerror_file = AssetManager_error_file_func;
|
||||||
|
zipFunctionOverrides.opaque = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
NS_CC_EXT_END
|
NS_CC_EXT_END
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#ifndef __AssetsManager__
|
#ifndef __AssetsManager__
|
||||||
#define __AssetsManager__
|
#define __AssetsManager__
|
||||||
|
|
||||||
|
#include <ioapi.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
@ -169,6 +170,7 @@ protected:
|
||||||
bool uncompress();
|
bool uncompress();
|
||||||
void setSearchPath();
|
void setSearchPath();
|
||||||
void downloadAndUncompress();
|
void downloadAndUncompress();
|
||||||
|
void fillZipFunctionOverrides(zlib_filefunc_def& zipFunctionOverrides);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
//! The path to store downloaded resources.
|
//! The path to store downloaded resources.
|
||||||
|
|
|
@ -53,6 +53,116 @@ NS_CC_EXT_BEGIN
|
||||||
const std::string AssetsManagerEx::VERSION_ID = "@version";
|
const std::string AssetsManagerEx::VERSION_ID = "@version";
|
||||||
const std::string AssetsManagerEx::MANIFEST_ID = "@manifest";
|
const std::string AssetsManagerEx::MANIFEST_ID = "@manifest";
|
||||||
|
|
||||||
|
class AssetManagerExZipFileInfo
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
std::string zipFileName{};
|
||||||
|
};
|
||||||
|
|
||||||
|
// unzip overrides to support FileStream
|
||||||
|
long AssetManagerEx_tell_file_func(voidpf opaque, voidpf stream)
|
||||||
|
{
|
||||||
|
if (stream == nullptr)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
auto* fs = (FileStream*)stream;
|
||||||
|
|
||||||
|
return fs->tell();
|
||||||
|
}
|
||||||
|
|
||||||
|
long AssetManagerEx_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 AssetManagerEx_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 AssetManagerEx_opendisk_file_func(voidpf opaque, voidpf stream, uint32_t number_disk, int mode)
|
||||||
|
{
|
||||||
|
if (stream == nullptr)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
const auto zipFileInfo = static_cast<AssetManagerExZipFileInfo*>(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 AssetManagerEx_open_file_func(opaque, diskFilename.c_str(), mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t AssetManagerEx_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 AssetManagerEx_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 AssetManagerEx_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 AssetManagerEx_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
|
||||||
|
|
||||||
// Implementation of AssetsManagerEx
|
// Implementation of AssetsManagerEx
|
||||||
|
|
||||||
AssetsManagerEx::AssetsManagerEx(const std::string& manifestUrl, const std::string& storagePath)
|
AssetsManagerEx::AssetsManagerEx(const std::string& manifestUrl, const std::string& storagePath)
|
||||||
|
@ -314,9 +424,17 @@ bool AssetsManagerEx::decompress(const std::string &zip)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const std::string rootPath = zip.substr(0, pos+1);
|
const std::string rootPath = zip.substr(0, pos+1);
|
||||||
|
|
||||||
|
zlib_filefunc_def zipFunctionOverrides;
|
||||||
|
fillZipFunctionOverrides(zipFunctionOverrides);
|
||||||
|
|
||||||
|
AssetManagerExZipFileInfo zipFileInfo;
|
||||||
|
zipFileInfo.zipFileName = zip;
|
||||||
|
|
||||||
|
zipFunctionOverrides.opaque = &zipFileInfo;
|
||||||
|
|
||||||
// Open the zip file
|
// Open the zip file
|
||||||
unzFile zipfile = unzOpen(zip.c_str());
|
unzFile zipfile = unzOpen2(zip.c_str(), &zipFunctionOverrides);
|
||||||
if (! zipfile)
|
if (! zipfile)
|
||||||
{
|
{
|
||||||
CCLOG("AssetsManagerEx : can not open downloaded zip file %s\n", zip.c_str());
|
CCLOG("AssetsManagerEx : can not open downloaded zip file %s\n", zip.c_str());
|
||||||
|
@ -392,8 +510,8 @@ bool AssetsManagerEx::decompress(const std::string &zip)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a file to store current file.
|
// Create a file to store current file.
|
||||||
FILE *out = fopen(fullPath.c_str(), "wb");
|
auto* fsOut = FileUtils::getInstance()->openFileStream(fullPath, FileStream::Mode::WRITE);
|
||||||
if (!out)
|
if (!fsOut)
|
||||||
{
|
{
|
||||||
CCLOG("AssetsManagerEx : can not create decompress destination file %s (errno: %d)\n", fullPath.c_str(), errno);
|
CCLOG("AssetsManagerEx : can not create decompress destination file %s (errno: %d)\n", fullPath.c_str(), errno);
|
||||||
unzCloseCurrentFile(zipfile);
|
unzCloseCurrentFile(zipfile);
|
||||||
|
@ -409,7 +527,7 @@ bool AssetsManagerEx::decompress(const std::string &zip)
|
||||||
if (error < 0)
|
if (error < 0)
|
||||||
{
|
{
|
||||||
CCLOG("AssetsManagerEx : can not read zip file %s, error code is %d\n", fileName, error);
|
CCLOG("AssetsManagerEx : can not read zip file %s, error code is %d\n", fileName, error);
|
||||||
fclose(out);
|
delete fsOut;
|
||||||
unzCloseCurrentFile(zipfile);
|
unzCloseCurrentFile(zipfile);
|
||||||
unzClose(zipfile);
|
unzClose(zipfile);
|
||||||
return false;
|
return false;
|
||||||
|
@ -417,11 +535,11 @@ bool AssetsManagerEx::decompress(const std::string &zip)
|
||||||
|
|
||||||
if (error > 0)
|
if (error > 0)
|
||||||
{
|
{
|
||||||
fwrite(readBuffer, error, 1, out);
|
fsOut->write(readBuffer, error);
|
||||||
}
|
}
|
||||||
} while(error > 0);
|
} while(error > 0);
|
||||||
|
|
||||||
fclose(out);
|
delete fsOut;
|
||||||
}
|
}
|
||||||
|
|
||||||
unzCloseCurrentFile(zipfile);
|
unzCloseCurrentFile(zipfile);
|
||||||
|
@ -530,7 +648,7 @@ void AssetsManagerEx::downloadVersion()
|
||||||
{
|
{
|
||||||
_updateState = State::DOWNLOADING_VERSION;
|
_updateState = State::DOWNLOADING_VERSION;
|
||||||
// Download version file asynchronously
|
// Download version file asynchronously
|
||||||
_downloader->createDownloadFileTask(versionUrl, _tempVersionPath, VERSION_ID);
|
_downloader->createDownloadFileTask(versionUrl, _tempVersionPath, "", VERSION_ID);
|
||||||
}
|
}
|
||||||
// No version file found
|
// No version file found
|
||||||
else
|
else
|
||||||
|
@ -598,7 +716,7 @@ void AssetsManagerEx::downloadManifest()
|
||||||
{
|
{
|
||||||
_updateState = State::DOWNLOADING_MANIFEST;
|
_updateState = State::DOWNLOADING_MANIFEST;
|
||||||
// Download version file asynchronously
|
// Download version file asynchronously
|
||||||
_downloader->createDownloadFileTask(manifestUrl, _tempManifestPath, MANIFEST_ID);
|
_downloader->createDownloadFileTask(manifestUrl, _tempManifestPath, "", MANIFEST_ID);
|
||||||
}
|
}
|
||||||
// No manifest file found
|
// No manifest file found
|
||||||
else
|
else
|
||||||
|
@ -1147,7 +1265,7 @@ void AssetsManagerEx::queueDowload()
|
||||||
_currConcurrentTask++;
|
_currConcurrentTask++;
|
||||||
DownloadUnit& unit = _downloadUnits[key];
|
DownloadUnit& unit = _downloadUnits[key];
|
||||||
_fileUtils->createDirectory(basename(unit.storagePath));
|
_fileUtils->createDirectory(basename(unit.storagePath));
|
||||||
_downloader->createDownloadFileTask(unit.srcUrl, unit.storagePath, unit.customId);
|
_downloader->createDownloadFileTask(unit.srcUrl, unit.storagePath, "", unit.customId);
|
||||||
|
|
||||||
_tempManifest->setAssetDownloadState(key, Manifest::DownloadState::DOWNLOADING);
|
_tempManifest->setAssetDownloadState(key, Manifest::DownloadState::DOWNLOADING);
|
||||||
}
|
}
|
||||||
|
@ -1176,4 +1294,17 @@ void AssetsManagerEx::onDownloadUnitsFinished()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AssetsManagerEx::fillZipFunctionOverrides(zlib_filefunc_def& zipFunctionOverrides)
|
||||||
|
{
|
||||||
|
zipFunctionOverrides.zopen_file = AssetManagerEx_open_file_func;
|
||||||
|
zipFunctionOverrides.zopendisk_file = AssetManagerEx_opendisk_file_func;
|
||||||
|
zipFunctionOverrides.zread_file = AssetManagerEx_read_file_func;
|
||||||
|
zipFunctionOverrides.zwrite_file = AssetManagerEx_write_file_func;
|
||||||
|
zipFunctionOverrides.ztell_file = AssetManagerEx_tell_file_func;
|
||||||
|
zipFunctionOverrides.zseek_file = AssetManagerEx_seek_file_func;
|
||||||
|
zipFunctionOverrides.zclose_file = AssetManagerEx_close_file_func;
|
||||||
|
zipFunctionOverrides.zerror_file = AssetManagerEx_error_file_func;
|
||||||
|
zipFunctionOverrides.opaque = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
NS_CC_EXT_END
|
NS_CC_EXT_END
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#ifndef __AssetsManagerEx__
|
#ifndef __AssetsManagerEx__
|
||||||
#define __AssetsManagerEx__
|
#define __AssetsManagerEx__
|
||||||
|
|
||||||
|
#include <ioapi.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
@ -219,7 +220,8 @@ private:
|
||||||
|
|
||||||
// Called when one DownloadUnits finished
|
// Called when one DownloadUnits finished
|
||||||
void onDownloadUnitsFinished();
|
void onDownloadUnitsFinished();
|
||||||
|
void fillZipFunctionOverrides(zlib_filefunc_def &zipFunctionOverrides);
|
||||||
|
|
||||||
//! The event of the current AssetsManagerEx in event dispatcher
|
//! The event of the current AssetsManagerEx in event dispatcher
|
||||||
std::string _eventName;
|
std::string _eventName;
|
||||||
|
|
||||||
|
@ -263,7 +265,7 @@ private:
|
||||||
|
|
||||||
//! Remote manifest
|
//! Remote manifest
|
||||||
Manifest *_remoteManifest = nullptr;
|
Manifest *_remoteManifest = nullptr;
|
||||||
|
|
||||||
//! Whether user have requested to update
|
//! Whether user have requested to update
|
||||||
enum class UpdateEntry : char
|
enum class UpdateEntry : char
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue