m2-client/src/EterPack/EterPackManager.cpp

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);
}