315 lines
7.2 KiB
C++
315 lines
7.2 KiB
C++
#include "StdAfx.h"
|
|
|
|
#include <io.h>
|
|
#include <assert.h>
|
|
|
|
#include "EterPackManager.h"
|
|
|
|
#include "../eterBase/Debug.h"
|
|
#include "../eterBase/CRC32.h"
|
|
|
|
#include "Folder.h"
|
|
#include "ZIP.h"
|
|
|
|
#define PATH_ABSOLUTE_YMIRWORK1 "d:/ymir work/"
|
|
#define PATH_ABSOLUTE_YMIRWORK2 "d:\\ymir work\\"
|
|
|
|
|
|
void CEterPackManager::SetCacheMode()
|
|
{
|
|
m_isCacheMode=true;
|
|
}
|
|
|
|
void CEterPackManager::SetRelativePathMode()
|
|
{
|
|
m_bTryRelativePath = true;
|
|
}
|
|
|
|
|
|
// StringPath std::string ¹öÀü
|
|
std::string CEterPackManager::ConvertFileName(std::string fileName)
|
|
{
|
|
std::string convertedFileName = fileName;
|
|
stl_lowers(convertedFileName);
|
|
|
|
for (DWORD i = 0; i < convertedFileName.length(); i++)
|
|
{
|
|
if (convertedFileName[i] == '\\')
|
|
convertedFileName[i] = '/';
|
|
}
|
|
|
|
return convertedFileName;
|
|
}
|
|
|
|
bool CEterPackManager::CompareName(const char * c_szDirectoryName, DWORD /*dwLength*/, const char * c_szFileName)
|
|
{
|
|
const char * c_pszSrc = c_szDirectoryName;
|
|
const char * c_pszCmp = c_szFileName;
|
|
|
|
while (*c_pszSrc)
|
|
{
|
|
if (*(c_pszSrc++) != *(c_pszCmp++))
|
|
return false;
|
|
|
|
if (!*c_pszCmp)
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void CEterPackManager::LoadStaticCache(const char* c_szFileName)
|
|
{
|
|
if (!m_isCacheMode)
|
|
return;
|
|
|
|
std::string strFileName = ConvertFileName(c_szFileName);
|
|
|
|
DWORD dwFileNameHash = GetCRC32(strFileName.c_str(), strFileName.length());
|
|
|
|
std::unordered_map<DWORD, SCache>::iterator f = m_kMap_dwNameKey_kCache.find(dwFileNameHash);
|
|
if (m_kMap_dwNameKey_kCache.end() != f)
|
|
return;
|
|
|
|
CMappedFile kMapFile;
|
|
const void* c_pvData;
|
|
if (!Get(kMapFile, c_szFileName, &c_pvData))
|
|
return;
|
|
|
|
SCache kNewCache;
|
|
kNewCache.m_dwBufSize = kMapFile.Size();
|
|
kNewCache.m_abBufData = new BYTE[kNewCache.m_dwBufSize];
|
|
memcpy(kNewCache.m_abBufData, c_pvData, kNewCache.m_dwBufSize);
|
|
m_kMap_dwNameKey_kCache.insert(std::unordered_map<DWORD, SCache>::value_type(dwFileNameHash, kNewCache));
|
|
}
|
|
|
|
CEterPackManager::SCache* CEterPackManager::__FindCache(DWORD dwFileNameHash)
|
|
{
|
|
std::unordered_map<DWORD, SCache>::iterator f=m_kMap_dwNameKey_kCache.find(dwFileNameHash);
|
|
if (m_kMap_dwNameKey_kCache.end()==f)
|
|
return NULL;
|
|
|
|
return &f->second;
|
|
}
|
|
|
|
void CEterPackManager::__ClearCacheMap()
|
|
{
|
|
std::unordered_map<DWORD, SCache>::iterator i;
|
|
|
|
for (i = m_kMap_dwNameKey_kCache.begin(); i != m_kMap_dwNameKey_kCache.end(); ++i)
|
|
delete [] i->second.m_abBufData;
|
|
|
|
m_kMap_dwNameKey_kCache.clear();
|
|
}
|
|
|
|
struct TimeChecker
|
|
{
|
|
TimeChecker(const char* name) : name(name)
|
|
{
|
|
baseTime = timeGetTime();
|
|
}
|
|
~TimeChecker()
|
|
{
|
|
printf("load %s (%d)\n", name, timeGetTime() - baseTime);
|
|
}
|
|
|
|
const char* name;
|
|
DWORD baseTime;
|
|
};
|
|
|
|
bool CEterPackManager::Get(CMappedFile & rMappedFile, const char * c_szFileName, LPCVOID * pData)
|
|
{
|
|
//TimeChecker timeChecker(c_szFileName);
|
|
//Logf(1, "Load %s\n", c_szFileName);
|
|
|
|
if (m_iSearchMode == SEARCH_FILE_FIRST)
|
|
{
|
|
if (GetFromFile(rMappedFile, c_szFileName, pData))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return GetFromPack(rMappedFile, c_szFileName, pData);
|
|
}
|
|
|
|
if (GetFromPack(rMappedFile, c_szFileName, pData))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return GetFromFile(rMappedFile, c_szFileName, pData);
|
|
}
|
|
|
|
struct FinderLock
|
|
{
|
|
FinderLock(CRITICAL_SECTION& cs) : p_cs(&cs)
|
|
{
|
|
EnterCriticalSection(p_cs);
|
|
}
|
|
|
|
~FinderLock()
|
|
{
|
|
LeaveCriticalSection(p_cs);
|
|
}
|
|
|
|
CRITICAL_SECTION* p_cs;
|
|
};
|
|
|
|
bool CEterPackManager::GetFromPack(CMappedFile & rMappedFile, const char * c_szFileName, LPCVOID * pData)
|
|
{
|
|
FinderLock lock(m_csFinder);
|
|
|
|
std::string strFileName = ConvertFileName(c_szFileName);
|
|
|
|
DWORD dwFileNameHash = GetCRC32(strFileName.c_str(), strFileName.length());
|
|
SCache* pkCache = __FindCache(dwFileNameHash);
|
|
|
|
if (pkCache)
|
|
{
|
|
rMappedFile.Link(pkCache->m_dwBufSize, pkCache->m_abBufData);
|
|
return true;
|
|
}
|
|
|
|
auto pkFileItem = m_FileDict.find(dwFileNameHash);
|
|
|
|
if (pkFileItem == m_FileDict.end()) {
|
|
#ifdef _DEBUG
|
|
TraceError("CANNOT_FIND_PACK_FILE [%s]", strFileName.c_str());
|
|
#endif
|
|
|
|
return false;
|
|
}
|
|
|
|
auto data = std::make_shared<std::vector<char>>();
|
|
bool r = pkFileItem->second->getFile(strFileName, data);
|
|
|
|
// Keep the file loaded by always forcing a reference in the smart pointer (temporary hack)
|
|
keepDataReferencedArray.push_back(data);
|
|
|
|
rMappedFile.Link(data->size(), data->data());
|
|
*pData = (LPCVOID *) data->data();
|
|
return r;
|
|
}
|
|
|
|
const time_t g_tCachingInterval = 10; // 10ÃÊ
|
|
|
|
bool CEterPackManager::GetFromFile(CMappedFile & rMappedFile, const char * c_szFileName, LPCVOID * pData)
|
|
{
|
|
#ifndef _DEBUG
|
|
//const char *pcExt = strchr(c_szFileName, '.');
|
|
//if (pcExt &&
|
|
// _strnicmp(pcExt, ".py", 3) == 0 && // python ½ºÅ©¸³Æ® Áß
|
|
// stricmp(c_szFileName, "logininfo.py") != 0 && // ·Î±×ÀÎ Á¤º¸ ÆÄÀÏÀÌ ¾Æ´Ï°í
|
|
// strnicmp(c_szFileName, "locale", 6) != 0
|
|
// )
|
|
//{
|
|
// return false;
|
|
//}
|
|
#endif
|
|
|
|
//if(m_bTryRelativePath) {
|
|
// if (strnicmp(c_szFileName, PATH_ABSOLUTE_YMIRWORK1, strlen(PATH_ABSOLUTE_YMIRWORK1)) == 0 || strnicmp(c_szFileName, PATH_ABSOLUTE_YMIRWORK2, strlen(PATH_ABSOLUTE_YMIRWORK2)) == 0) {
|
|
// if(rMappedFile.Create(c_szFileName+strlen(PATH_ABSOLUTE_YMIRWORK1), pData, 0, 0))
|
|
// {
|
|
// return true;
|
|
// }
|
|
// }
|
|
//}
|
|
|
|
return rMappedFile.Create(c_szFileName, pData, 0, 0) ? true : false;
|
|
}
|
|
|
|
bool CEterPackManager::isExistInPack(const char * c_szFileName)
|
|
{
|
|
std::string strFileName = ConvertFileName(c_szFileName);
|
|
|
|
DWORD dwFileNameHash = GetCRC32(strFileName.c_str(), strFileName.length());
|
|
auto pkFileItem = m_FileDict.find(dwFileNameHash);
|
|
|
|
if (pkFileItem == m_FileDict.end())
|
|
return false;
|
|
|
|
if (pkFileItem->second)
|
|
return pkFileItem->second->fileExists(strFileName.c_str());
|
|
}
|
|
|
|
bool CEterPackManager::isExist(const char * c_szFileName)
|
|
{
|
|
if (m_iSearchMode == SEARCH_PACK_FIRST)
|
|
{
|
|
if (isExistInPack(c_szFileName))
|
|
return true;
|
|
|
|
return _access(c_szFileName, 0) == 0 ? true : false;
|
|
}
|
|
|
|
//if(m_bTryRelativePath) {
|
|
// if (strnicmp(c_szFileName, PATH_ABSOLUTE_YMIRWORK1, strlen(PATH_ABSOLUTE_YMIRWORK1)) == 0 || strnicmp(c_szFileName, PATH_ABSOLUTE_YMIRWORK2, strlen(PATH_ABSOLUTE_YMIRWORK2)) == 0) {
|
|
// if(access(c_szFileName+strlen(PATH_ABSOLUTE_YMIRWORK1), 0) == 0)
|
|
// return true;
|
|
// }
|
|
//}
|
|
|
|
if (_access(c_szFileName, 0) == 0)
|
|
return true;
|
|
|
|
return isExistInPack(c_szFileName);
|
|
}
|
|
|
|
|
|
bool CEterPackManager::RegisterPack(const char * c_szName, const char * c_szDirectory, const BYTE* c_pbIV)
|
|
{
|
|
auto it = m_PackMap.find(c_szName);
|
|
|
|
if (it != m_PackMap.end())
|
|
return true;
|
|
|
|
try {
|
|
bool bReadOnly = true;
|
|
|
|
std::shared_ptr<FileProvider> pack;
|
|
|
|
// TODO: allow configurable containers
|
|
|
|
//pack = std::make_shared<Folder>(c_szName);
|
|
pack = std::make_shared<ZIP>(std::string(c_szName) + ".zip");
|
|
|
|
auto packFiles = pack->listFiles();
|
|
|
|
for (auto const& fileName : packFiles) {
|
|
DWORD dwFileNameHash = GetCRC32(fileName.c_str(), fileName.length());
|
|
m_FileDict.insert({ dwFileNameHash, pack });
|
|
}
|
|
|
|
m_PackMap.insert(TEterPackMap::value_type(c_szName, pack));
|
|
}
|
|
catch (...)
|
|
{
|
|
#ifdef _DEBUG
|
|
Tracef("The eterpack doesn't exist [%s]\n", c_szName);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
void CEterPackManager::SetSearchMode(bool bPackFirst)
|
|
{
|
|
m_iSearchMode = bPackFirst ? SEARCH_PACK_FIRST : SEARCH_FILE_FIRST;
|
|
}
|
|
|
|
int CEterPackManager::GetSearchMode()
|
|
{
|
|
return m_iSearchMode;
|
|
}
|
|
|
|
CEterPackManager::CEterPackManager() : m_bTryRelativePath(false), m_iSearchMode(SEARCH_FILE_FIRST), m_isCacheMode(false)
|
|
{
|
|
InitializeCriticalSection(&m_csFinder);
|
|
}
|
|
|
|
CEterPackManager::~CEterPackManager()
|
|
{
|
|
__ClearCacheMap();
|
|
|
|
DeleteCriticalSection(&m_csFinder);
|
|
}
|