Skip to content
Browse files

Merge pull request #1562 from mingulov/apk

Android: Access to files from APK is boosted
  • Loading branch information...
2 parents fb756e2 + f73568d commit 68fc88887a0505c803ed246ee68bf48d35fb5e09 @minggo minggo committed
View
14 cocos2dx/platform/android/CCFileUtils.cpp
@@ -24,6 +24,7 @@ THE SOFTWARE.
#define __CC_PLATFORM_FILEUTILS_CPP__
#include "platform/CCFileUtilsCommon_cpp.h"
+#include "support/zip_support/ZipUtils.h"
using namespace std;
@@ -32,17 +33,17 @@ NS_CC_BEGIN
#include "platform/CCCommon.h"
#include "jni/Java_org_cocos2dx_lib_Cocos2dxHelper.h"
-// record the resource path
-static string s_strResourcePath = "";
-
static CCFileUtils* s_pFileUtils = NULL;
+// record the zip on the resource path
+static ZipFile *s_pZipFile = NULL;
CCFileUtils* CCFileUtils::sharedFileUtils()
{
if (s_pFileUtils == NULL)
{
s_pFileUtils = new CCFileUtils();
- s_strResourcePath = getApkPath();
+ std::string resourcePath = getApkPath();
+ s_pZipFile = new ZipFile(resourcePath, "assets/");
}
return s_pFileUtils;
}
@@ -54,6 +55,7 @@ void CCFileUtils::purgeFileUtils()
s_pFileUtils->purgeCachedEntries();
}
+ CC_SAFE_DELETE(s_pZipFile);
CC_SAFE_DELETE(s_pFileUtils);
}
@@ -94,13 +96,13 @@ unsigned char* CCFileUtils::getFileData(const char* pszFileName, const char* psz
fullPath.insert(0, m_obDirectory.c_str());
fullPath.insert(0, "assets/");
- pData = CCFileUtils::getFileDataFromZip(s_strResourcePath.c_str(), fullPath.c_str(), pSize);
+ pData = s_pZipFile->getFileData(fullPath, pSize);
if (! pData && m_obDirectory.size() > 0)
{
// search from root
pathWithoutDirectory.insert(0, "assets/");
- pData = CCFileUtils::getFileDataFromZip(s_strResourcePath.c_str(), pathWithoutDirectory.c_str(), pSize);
+ pData = s_pZipFile->getFileData(pathWithoutDirectory, pSize);
}
}
else
View
141 cocos2dx/support/zip_support/ZipUtils.cpp
@@ -28,9 +28,13 @@ THE SOFTWARE.
#include "ZipUtils.h"
#include "ccMacros.h"
#include "platform/CCFileUtils.h"
+#include "unzip.h"
+#include <map>
NS_CC_BEGIN
+// --------------------- ZipUtils ---------------------
+
// memory in iPhone is precious
// Should buffer factor be 1.5 instead of 2 ?
#define BUFFER_INC_FACTOR (2)
@@ -280,4 +284,141 @@ int ZipUtils::ccInflateCCZFile(const char *path, unsigned char **out)
return len;
}
+// --------------------- ZipFile ---------------------
+// from unzip.cpp
+#define UNZ_MAXFILENAMEINZIP 256
+
+struct ZipEntryInfo
+{
+ unz_file_pos pos;
+ uLong uncompressed_size;
+};
+
+class ZipFilePrivate
+{
+public:
+ unzFile zipFile;
+
+ // std::unordered_map is faster if available on the platform
+ typedef std::map<std::string, struct ZipEntryInfo> FileListContainer;
+ FileListContainer fileList;
+};
+
+ZipFile::ZipFile(const std::string &zipFile, const std::string &filter)
+ : m_data(new ZipFilePrivate)
+{
+ m_data->zipFile = unzOpen(zipFile.c_str());
+ if (m_data->zipFile)
+ {
+ setFilter(filter);
+ }
+}
+
+ZipFile::~ZipFile()
+{
+ if (m_data && m_data->zipFile)
+ {
+ unzClose(m_data->zipFile);
+ }
+ CC_SAFE_DELETE(m_data);
+}
+
+bool ZipFile::setFilter(const std::string &filter)
+{
+ bool ret = false;
+ do
+ {
+ CC_BREAK_IF(!m_data);
+ CC_BREAK_IF(!m_data->zipFile);
+
+ // clear existing file list
+ m_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(m_data->zipFile, &fileInfo,
+ szCurrentFileName, sizeof(szCurrentFileName) - 1);
+ while (err == UNZ_OK)
+ {
+ unz_file_pos posInfo;
+ int posErr = unzGetFilePos(m_data->zipFile, &posInfo);
+ if (posErr == UNZ_OK)
+ {
+ std::string currentFileName = szCurrentFileName;
+ // cache info about filtered files only (like 'assets/')
+ if (filter.empty()
+ || currentFileName.substr(0, filter.length()) == filter)
+ {
+ ZipEntryInfo entry;
+ entry.pos = posInfo;
+ entry.uncompressed_size = (uLong)fileInfo.uncompressed_size;
+ m_data->fileList[currentFileName] = entry;
+ }
+ }
+ // next file - also get the information about it
+ err = unzGoToNextFile64(m_data->zipFile, &fileInfo,
+ szCurrentFileName, sizeof(szCurrentFileName) - 1);
+ }
+ ret = true;
+
+ } while(false);
+
+ return ret;
+}
+
+bool ZipFile::fileExists(const std::string &fileName) const
+{
+ bool ret = false;
+ do
+ {
+ CC_BREAK_IF(!m_data);
+
+ ret = m_data->fileList.find(fileName) != m_data->fileList.end();
+ } while(false);
+
+ return ret;
+}
+
+unsigned char *ZipFile::getFileData(const std::string &fileName, unsigned long *pSize)
+{
+ unsigned char * pBuffer = NULL;
+ if (pSize)
+ {
+ *pSize = 0;
+ }
+
+ do
+ {
+ CC_BREAK_IF(!m_data->zipFile);
+ CC_BREAK_IF(fileName.empty());
+
+ ZipFilePrivate::FileListContainer::const_iterator it = m_data->fileList.find(fileName);
+ CC_BREAK_IF(it == m_data->fileList.end());
+
+ ZipEntryInfo fileInfo = it->second;
+
+ int nRet = unzGoToFilePos(m_data->zipFile, &fileInfo.pos);
+ CC_BREAK_IF(UNZ_OK != nRet);
+
+ nRet = unzOpenCurrentFile(m_data->zipFile);
+ CC_BREAK_IF(UNZ_OK != nRet);
+
+ pBuffer = new unsigned char[fileInfo.uncompressed_size];
+ int nSize = 0;
+ nSize = unzReadCurrentFile(m_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(m_data->zipFile);
+ } while (0);
+
+ return pBuffer;
+}
+
NS_CC_END
View
66 cocos2dx/support/zip_support/ZipUtils.h
@@ -24,6 +24,8 @@ THE SOFTWARE.
#ifndef __SUPPORT_ZIPUTILS_H__
#define __SUPPORT_ZIPUTILS_H__
+#include <string>
+
namespace cocos2d
{
/* XXX: pragma pack ??? */
@@ -91,6 +93,68 @@ namespace cocos2d
unsigned int outLenghtHint);
};
+ // forward declaration
+ class ZipFilePrivate;
+
+ /**
+ * Zip file - reader helper class.
+ *
+ * It will cache the file list of a particular zip file with positions inside an archive,
+ * so it would be much faster to read some particular files or to check their existance.
+ *
+ * @since v2.0.5
+ */
+ class ZipFile
+ {
+ public:
+ /**
+ * Constructor, open zip file and store file list.
+ *
+ * @param zipFile Zip file name
+ * @param filter The first part of file names, which should be accessible.
+ * For example, "assets/". Other files will be missed.
+ *
+ * @since v2.0.5
+ */
+ ZipFile(const std::string &zipFile, const std::string &filter = std::string());
+ virtual ~ZipFile();
+
+ /**
+ * Regenerate accessible file list based on a new filter string.
+ *
+ * @param filter New filter string (first part of files names)
+ * @return true whenever zip file is open successfully and it is possible to locate
+ * at least the first file, false otherwise
+ *
+ * @since v2.0.5
+ */
+ bool setFilter(const std::string &filter);
+
+ /**
+ * Check does a file exists or not in zip file
+ *
+ * @param fileName File to be checked on existance
+ * @return true whenever file exists, false otherwise
+ *
+ * @since v2.0.5
+ */
+ bool fileExists(const std::string &fileName) const;
+
+ /**
+ * Get resource file data from a zip file.
+ * @param fileName File name
+ * @param[out] pSize If the file read operation succeeds, it will be the data size, otherwise 0.
+ * @return Upon success, a pointer to the data is returned, otherwise NULL.
+ * @warning Recall: you are responsible for calling delete[] on any Non-NULL pointer returned.
+ *
+ * @since v2.0.5
+ */
+ unsigned char *getFileData(const std::string &fileName, unsigned long *pSize);
+
+ private:
+ /** Internal data like zip file pointer / file list array and so on */
+ ZipFilePrivate *m_data;
+ };
} // end of namespace cocos2d
-#endif // __PLATFORM_WOPHONE_ZIPUTILS_H__
+#endif // __SUPPORT_ZIPUTILS_H__
View
44 cocos2dx/support/zip_support/unzip.cpp
@@ -1172,11 +1172,16 @@ int ZEXPORT unzGetCurrentFileInfo (unzFile file,
}
return err;
}
+
/*
- Set the current file of the zipfile to the first file.
+ Set the current file of the zipfile to the first file
+ with retrieving an information about the file.
return UNZ_OK if there is no problem
*/
-int ZEXPORT unzGoToFirstFile (unzFile file)
+int ZEXPORT unzGoToFirstFile64 (unzFile file,
+ unz_file_info64 *pfile_info,
+ char *szFileName,
+ uLong fileNameBufferSize)
{
int err=UNZ_OK;
unz64_s* s;
@@ -1187,17 +1192,32 @@ int ZEXPORT unzGoToFirstFile (unzFile file)
s->num_file=0;
err=unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info,
&s->cur_file_info_internal,
- NULL,0,NULL,0,NULL,0);
+ szFileName,fileNameBufferSize,NULL,0,NULL,0);
s->current_file_ok = (err == UNZ_OK);
+ if (pfile_info)
+ *pfile_info = s->cur_file_info;
return err;
}
/*
- Set the current file of the zipfile to the next file.
+ Set the current file of the zipfile to the first file.
+ return UNZ_OK if there is no problem
+*/
+int ZEXPORT unzGoToFirstFile (unzFile file)
+{
+ return unzGoToFirstFile64(file, NULL, NULL, 0);
+}
+
+/*
+ Set the current file of the zipfile to the next file
+ with retrieving an information about the file.
return UNZ_OK if there is no problem
return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
*/
-int ZEXPORT unzGoToNextFile (unzFile file)
+int ZEXPORT unzGoToNextFile64 (unzFile file,
+ unz_file_info64 *pfile_info,
+ char *szFileName,
+ uLong fileNameBufferSize)
{
unz64_s* s;
int err;
@@ -1216,11 +1236,23 @@ int ZEXPORT unzGoToNextFile (unzFile file)
s->num_file++;
err = unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info,
&s->cur_file_info_internal,
- NULL,0,NULL,0,NULL,0);
+ szFileName,fileNameBufferSize,NULL,0,NULL,0);
s->current_file_ok = (err == UNZ_OK);
+ if (pfile_info)
+ *pfile_info = s->cur_file_info;
return err;
}
+/*
+ Set the current file of the zipfile to the next file.
+ return UNZ_OK if there is no problem
+ return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
+*/
+int ZEXPORT unzGoToNextFile (unzFile file)
+{
+ return unzGoToNextFile64(file, NULL, NULL, 0);
+}
+
/*
Try locate the file szFileName in the zipfile.
View
22 cocos2dx/support/zip_support/unzip.h
@@ -225,11 +225,22 @@ int ZEXPORT unzGetGlobalComment OF((unzFile file,
/* Unzip package allow you browse the directory of the zipfile */
int ZEXPORT unzGoToFirstFile OF((unzFile file));
+
/*
Set the current file of the zipfile to the first file.
return UNZ_OK if there is no problem
*/
+int ZEXPORT unzGoToFirstFile64 OF((unzFile file,
+ unz_file_info64 *pfile_info,
+ char *szFileName,
+ uLong fileNameBufferSize));
+/*
+ Set the current file of the zipfile to the first file
+ with retrieving an information about the file.
+ return UNZ_OK if there is no problem
+*/
+
int ZEXPORT unzGoToNextFile OF((unzFile file));
/*
Set the current file of the zipfile to the next file.
@@ -237,6 +248,17 @@ int ZEXPORT unzGoToNextFile OF((unzFile file));
return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
*/
+int ZEXPORT unzGoToNextFile64 OF((unzFile file,
+ unz_file_info64 *pfile_info,
+ char *szFileName,
+ uLong fileNameBufferSize));
+/*
+ Set the current file of the zipfile to the next file
+ with retrieving an information about the file.
+ return UNZ_OK if there is no problem
+ return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
+*/
+
int ZEXPORT unzLocateFile OF((unzFile file,
const char *szFileName,
int iCaseSensitivity));

0 comments on commit 68fc888

Please sign in to comment.
Something went wrong with that request. Please try again.