mirror of https://github.com/axmolengine/axmol.git
fixed #2124: make CCImage::initWithIamgeFileThreadSafe() thread safe
This commit is contained in:
parent
25806536a2
commit
e9d8595617
|
@ -33,6 +33,10 @@ THE SOFTWARE.
|
|||
#include "png.h"
|
||||
#include "jpeglib.h"
|
||||
#include "tiffio.h"
|
||||
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
|
||||
#include "platform/android/CCFileUtilsAndroid.h"
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
#include <ctype.h>
|
||||
|
||||
|
@ -136,7 +140,12 @@ bool CCImage::initWithImageFileThreadSafe(const char *fullpath, EImageFormat ima
|
|||
{
|
||||
bool bRet = false;
|
||||
unsigned long nSize = 0;
|
||||
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
|
||||
CCFileUtilsAndroid *fileUitls = (CCFileUtilsAndroid*)CCFileUtils::sharedFileUtils();
|
||||
unsigned char *pBuffer = fileUitls->getFileDataForAsync(fullpath, "rb", &nSize);
|
||||
#else
|
||||
unsigned char *pBuffer = CCFileUtils::sharedFileUtils()->getFileData(fullpath, "rb", &nSize);
|
||||
#endif
|
||||
if (pBuffer != NULL && nSize > 0)
|
||||
{
|
||||
bRet = initWithImageData(pBuffer, nSize, imageType);
|
||||
|
|
|
@ -111,29 +111,45 @@ bool CCFileUtilsAndroid::isAbsolutePath(const std::string& strPath)
|
|||
|
||||
unsigned char* CCFileUtilsAndroid::getFileData(const char* pszFileName, const char* pszMode, unsigned long * pSize)
|
||||
{
|
||||
unsigned char * pData = 0;
|
||||
return doGetFileData(pszFileName, pszMode, pSize, false);
|
||||
}
|
||||
|
||||
unsigned char* CCFileUtilsAndroid::getFileDataForAsync(const char* pszFileName, const char* pszMode, unsigned long * pSize)
|
||||
{
|
||||
return doGetFileData(pszFileName, pszMode, pSize, true);
|
||||
}
|
||||
|
||||
unsigned char* CCFileUtilsAndroid::doGetFileData(const char* pszFileName, const char* pszMode, unsigned long * pSize, bool forAsync)
|
||||
{
|
||||
unsigned char * pData = 0;
|
||||
|
||||
if ((! pszFileName) || (! pszMode) || 0 == strlen(pszFileName))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
string fullPath = fullPathForFilename(pszFileName);
|
||||
|
||||
|
||||
if (fullPath[0] != '/')
|
||||
{
|
||||
//CCLOG("GETTING FILE RELATIVE DATA: %s", pszFileName);
|
||||
pData = s_pZipFile->getFileData(fullPath.c_str(), pSize);
|
||||
if (forAsync)
|
||||
{
|
||||
pData = s_pZipFile->getFileData(fullPath.c_str(), pSize, s_pZipFile->_dataThread);
|
||||
}
|
||||
else
|
||||
{
|
||||
pData = s_pZipFile->getFileData(fullPath.c_str(), pSize);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
do
|
||||
do
|
||||
{
|
||||
// read rrom other path than user set it
|
||||
//CCLOG("GETTING FILE ABSOLUTE DATA: %s", pszFileName);
|
||||
FILE *fp = fopen(fullPath.c_str(), pszMode);
|
||||
CC_BREAK_IF(!fp);
|
||||
|
||||
|
||||
unsigned long size;
|
||||
fseek(fp,0,SEEK_END);
|
||||
size = ftell(fp);
|
||||
|
@ -141,21 +157,21 @@ unsigned char* CCFileUtilsAndroid::getFileData(const char* pszFileName, const ch
|
|||
pData = new unsigned char[size];
|
||||
size = fread(pData,sizeof(unsigned char), size,fp);
|
||||
fclose(fp);
|
||||
|
||||
|
||||
if (pSize)
|
||||
{
|
||||
*pSize = size;
|
||||
}
|
||||
} while (0);
|
||||
}
|
||||
} while (0);
|
||||
}
|
||||
|
||||
|
||||
if (! pData)
|
||||
{
|
||||
std::string msg = "Get data from file(";
|
||||
msg.append(pszFileName).append(") failed!");
|
||||
CCLOG(msg.c_str());
|
||||
}
|
||||
|
||||
|
||||
return pData;
|
||||
}
|
||||
|
||||
|
|
|
@ -52,6 +52,14 @@ public:
|
|||
virtual std::string getWritablePath();
|
||||
virtual bool isFileExist(const std::string& strFilePath);
|
||||
virtual bool isAbsolutePath(const std::string& strPath);
|
||||
|
||||
/** This function is android specific. It is used for CCTextureCache::addImageAsync().
|
||||
Don't use it in your codes.
|
||||
*/
|
||||
unsigned char* getFileDataForAsync(const char* pszFileName, const char* pszMode, unsigned long * pSize);
|
||||
|
||||
private:
|
||||
unsigned char* doGetFileData(const char* pszFileName, const char* pszMode, unsigned long * pSize, bool forAsync);
|
||||
};
|
||||
|
||||
// end of platform group
|
||||
|
|
|
@ -456,9 +456,11 @@ public:
|
|||
|
||||
ZipFile::ZipFile(const std::string &zipFile, const std::string &filter)
|
||||
: _data(new ZipFilePrivate)
|
||||
, _dataThread(new ZipFilePrivate)
|
||||
{
|
||||
_data->zipFile = unzOpen(zipFile.c_str());
|
||||
if (_data->zipFile)
|
||||
_dataThread->zipFile = unzOpen(zipFile.c_str());
|
||||
if (_data->zipFile && _dataThread->zipFile)
|
||||
{
|
||||
setFilter(filter);
|
||||
}
|
||||
|
@ -470,31 +472,36 @@ ZipFile::~ZipFile()
|
|||
{
|
||||
unzClose(_data->zipFile);
|
||||
}
|
||||
if (_dataThread && _dataThread->zipFile)
|
||||
{
|
||||
unzClose(_dataThread);
|
||||
}
|
||||
CC_SAFE_DELETE(_data);
|
||||
CC_SAFE_DELETE(_dataThread);
|
||||
}
|
||||
|
||||
bool ZipFile::setFilter(const std::string &filter)
|
||||
bool ZipFile::setFilter(const std::string &filter, ZipFilePrivate *data)
|
||||
{
|
||||
bool ret = false;
|
||||
do
|
||||
{
|
||||
CC_BREAK_IF(!_data);
|
||||
CC_BREAK_IF(!_data->zipFile);
|
||||
CC_BREAK_IF(!data);
|
||||
CC_BREAK_IF(!data->zipFile);
|
||||
|
||||
// clear existing file list
|
||||
_data->fileList.clear();
|
||||
data->fileList.clear();
|
||||
|
||||
// UNZ_MAXFILENAMEINZIP + 1 - it is done so in unzLocateFile
|
||||
char szCurrentFileName[UNZ_MAXFILENAMEINZIP + 1];
|
||||
unz_file_info64 fileInfo;
|
||||
|
||||
// go through all files and store position information about the required files
|
||||
int err = unzGoToFirstFile64(_data->zipFile, &fileInfo,
|
||||
int err = unzGoToFirstFile64(data->zipFile, &fileInfo,
|
||||
szCurrentFileName, sizeof(szCurrentFileName) - 1);
|
||||
while (err == UNZ_OK)
|
||||
{
|
||||
unz_file_pos posInfo;
|
||||
int posErr = unzGetFilePos(_data->zipFile, &posInfo);
|
||||
int posErr = unzGetFilePos(data->zipFile, &posInfo);
|
||||
if (posErr == UNZ_OK)
|
||||
{
|
||||
std::string currentFileName = szCurrentFileName;
|
||||
|
@ -505,11 +512,11 @@ bool ZipFile::setFilter(const std::string &filter)
|
|||
ZipEntryInfo entry;
|
||||
entry.pos = posInfo;
|
||||
entry.uncompressed_size = (uLong)fileInfo.uncompressed_size;
|
||||
_data->fileList[currentFileName] = entry;
|
||||
data->fileList[currentFileName] = entry;
|
||||
}
|
||||
}
|
||||
// next file - also get the information about it
|
||||
err = unzGoToNextFile64(_data->zipFile, &fileInfo,
|
||||
err = unzGoToNextFile64(data->zipFile, &fileInfo,
|
||||
szCurrentFileName, sizeof(szCurrentFileName) - 1);
|
||||
}
|
||||
ret = true;
|
||||
|
@ -519,6 +526,11 @@ bool ZipFile::setFilter(const std::string &filter)
|
|||
return ret;
|
||||
}
|
||||
|
||||
bool ZipFile::setFilter(const std::string &filter)
|
||||
{
|
||||
return (setFilter(filter, _data) && setFilter(filter, _dataThread));
|
||||
}
|
||||
|
||||
bool ZipFile::fileExists(const std::string &fileName) const
|
||||
{
|
||||
bool ret = false;
|
||||
|
@ -533,6 +545,11 @@ bool ZipFile::fileExists(const std::string &fileName) const
|
|||
}
|
||||
|
||||
unsigned char *ZipFile::getFileData(const std::string &fileName, unsigned long *pSize)
|
||||
{
|
||||
return getFileData(fileName, pSize, _data);
|
||||
}
|
||||
|
||||
unsigned char *ZipFile::getFileData(const std::string &fileName, unsigned long *pSize, ZipFilePrivate *data)
|
||||
{
|
||||
unsigned char * pBuffer = NULL;
|
||||
if (pSize)
|
||||
|
@ -542,29 +559,29 @@ unsigned char *ZipFile::getFileData(const std::string &fileName, unsigned long *
|
|||
|
||||
do
|
||||
{
|
||||
CC_BREAK_IF(!_data->zipFile);
|
||||
CC_BREAK_IF(!data->zipFile);
|
||||
CC_BREAK_IF(fileName.empty());
|
||||
|
||||
ZipFilePrivate::FileListContainer::const_iterator it = _data->fileList.find(fileName);
|
||||
CC_BREAK_IF(it == _data->fileList.end());
|
||||
ZipFilePrivate::FileListContainer::const_iterator it = data->fileList.find(fileName);
|
||||
CC_BREAK_IF(it == data->fileList.end());
|
||||
|
||||
ZipEntryInfo fileInfo = it->second;
|
||||
|
||||
int nRet = unzGoToFilePos(_data->zipFile, &fileInfo.pos);
|
||||
int nRet = unzGoToFilePos(data->zipFile, &fileInfo.pos);
|
||||
CC_BREAK_IF(UNZ_OK != nRet);
|
||||
|
||||
nRet = unzOpenCurrentFile(_data->zipFile);
|
||||
nRet = unzOpenCurrentFile(data->zipFile);
|
||||
CC_BREAK_IF(UNZ_OK != nRet);
|
||||
|
||||
pBuffer = new unsigned char[fileInfo.uncompressed_size];
|
||||
int CC_UNUSED nSize = unzReadCurrentFile(_data->zipFile, pBuffer, fileInfo.uncompressed_size);
|
||||
int CC_UNUSED nSize = unzReadCurrentFile(data->zipFile, pBuffer, fileInfo.uncompressed_size);
|
||||
CCAssert(nSize == 0 || nSize == (int)fileInfo.uncompressed_size, "the file size is wrong");
|
||||
|
||||
if (pSize)
|
||||
{
|
||||
*pSize = fileInfo.uncompressed_size;
|
||||
}
|
||||
unzCloseCurrentFile(_data->zipFile);
|
||||
unzCloseCurrentFile(data->zipFile);
|
||||
} while (0);
|
||||
|
||||
return pBuffer;
|
||||
|
|
|
@ -27,6 +27,10 @@ THE SOFTWARE.
|
|||
#include <string>
|
||||
#include "CCPlatformDefine.h"
|
||||
|
||||
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
|
||||
#include "platform/android/CCFileUtilsAndroid.h"
|
||||
#endif
|
||||
|
||||
namespace cocos2d
|
||||
{
|
||||
/* XXX: pragma pack ??? */
|
||||
|
@ -166,6 +170,10 @@ namespace cocos2d
|
|||
class ZipFile
|
||||
{
|
||||
public:
|
||||
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
|
||||
friend class CCFileUtilsAndroid;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Constructor, open zip file and store file list.
|
||||
*
|
||||
|
@ -211,8 +219,13 @@ namespace cocos2d
|
|||
unsigned char *getFileData(const std::string &fileName, unsigned long *pSize);
|
||||
|
||||
private:
|
||||
bool setFilter(const std::string &filer, ZipFilePrivate *data);
|
||||
unsigned char *getFileData(const std::string &fileName, unsigned long *pSize, ZipFilePrivate *data);
|
||||
|
||||
/** Internal data like zip file pointer / file list array and so on */
|
||||
ZipFilePrivate *_data;
|
||||
/** Another data used not in main thread */
|
||||
ZipFilePrivate *_dataThread;
|
||||
};
|
||||
} // end of namespace cocos2d
|
||||
#endif // __SUPPORT_ZIPUTILS_H__
|
||||
|
|
Loading…
Reference in New Issue