#include "StdAfx.h" #include #include #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::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::value_type(dwFileNameHash, kNewCache)); } CEterPackManager::SCache* CEterPackManager::__FindCache(DWORD dwFileNameHash) { std::unordered_map::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::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>(); 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 pack; // TODO: allow configurable containers //pack = std::make_shared(c_szName); pack = std::make_shared(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); }