1
0
forked from metin2/client
client/src/EterPack/EterPackManager.cpp

262 lines
5.3 KiB
C++

#include "StdAfx.h"
#include <fstream>
#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\\"
// 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;
}
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(const std::string& fileName, TPackDataPtr& dataPtr)
{
//TimeChecker timeChecker(c_szFileName);
//Logf(1, "Load %s\n", c_szFileName);
if (m_iSearchMode == SEARCH_FILE_FIRST)
{
if (GetFromFile(fileName, dataPtr))
return true;
return GetFromPack(fileName, dataPtr);
}
if (GetFromPack(fileName, dataPtr))
return true;
return GetFromFile(fileName, dataPtr);
}
bool CEterPackManager::Get(const std::string& fileName, std::stringstream& dataStream)
{
CEterPackManager::TPackDataPtr data;
if (!Get(fileName, data))
return false;
// Copy the data from the pack into the file sstream
dataStream.str("");
std::copy(data->begin(), data->end(), std::ostream_iterator<char>(dataStream));
return true;
}
struct FinderLock
{
FinderLock(CRITICAL_SECTION& cs) : p_cs(&cs)
{
EnterCriticalSection(p_cs);
}
~FinderLock()
{
LeaveCriticalSection(p_cs);
}
CRITICAL_SECTION* p_cs;
};
bool CEterPackManager::GetFromPack(const std::string& fileName, TPackDataPtr& dataPtr)
{
FinderLock lock(m_csFinder);
std::string strFileName = ConvertFileName(fileName);
auto pkFileItem = m_FileMap.find(strFileName);
if (pkFileItem == m_FileMap.end()) {
#ifdef _DEBUG
TraceError("CANNOT_FIND_PACK_FILE [%s]", strFileName.c_str());
#endif
return false;
}
auto data = std::make_shared<std::vector<char>>();
if (!pkFileItem->second->getFile(strFileName, data))
return false;
// Set dataPtr to the retreived data pointer
dataPtr = data;
return true;
}
bool CEterPackManager::GetFromFile(const std::string& fileName, TPackDataPtr& dataPtr)
{
// Try to open the file
std::ifstream file(fileName, std::ios::binary);
if (!file.is_open())
return false;
// Read the file's contents
dataPtr = std::make_shared<std::vector<char>>(
std::istreambuf_iterator<char>(file),
std::istreambuf_iterator<char>()
);
return true;
}
bool CEterPackManager::isExistInPack(const char * c_szFileName)
{
std::string strFileName = ConvertFileName(c_szFileName);
auto pkFileItem = m_FileMap.find(strFileName);
if (pkFileItem == m_FileMap.end())
return false;
if (!pkFileItem->second)
return false;
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;
}
if (_access(c_szFileName, 0) == 0)
return true;
return isExistInPack(c_szFileName);
}
bool CEterPackManager::PackExists(const std::string& name, const std::string& container)
{
if (container == "FOLDER") {
return _access(name.c_str(), 0) == 0;
}
else if (container == "ZIP") {
std::string zipName = name + ".zip";
return _access(zipName.c_str(), 0) == 0;
}
throw std::runtime_error("Unexpected container type: " + container + "!");
}
bool CEterPackManager::RegisterPack(const std::string& name, const std::string& container)
{
auto it = m_PackMap.find(name);
if (it != m_PackMap.end())
return true;
try {
bool bReadOnly = true;
std::shared_ptr<FileProvider> pack;
// Determine requested container type
if (container == "FOLDER")
pack = std::make_shared<Folder>(name);
else if (container == "ZIP")
pack = std::make_shared<ZIP>(name + ".zip");
else
throw std::runtime_error("Unexpected container type: " + container + "!");
// Load container data
auto packFiles = pack->listFiles();
for (auto const& fileName : packFiles)
m_FileMap.insert({ fileName, pack });
m_PackMap.insert({ name, pack });
return true;
}
catch (std::exception& e)
{
#ifdef _DEBUG
Tracef("Unable to load file provider '%s': %s\n", name.c_str(), e.what());
#endif
return false;
}
}
void CEterPackManager::SetSearchMode(bool bPackFirst)
{
m_iSearchMode = bPackFirst ? SEARCH_PACK_FIRST : SEARCH_FILE_FIRST;
}
int CEterPackManager::GetSearchMode()
{
return m_iSearchMode;
}
CEterPackManager::CEterPackManager() : m_iSearchMode(SEARCH_FILE_FIRST)
{
InitializeCriticalSection(&m_csFinder);
}
CEterPackManager::~CEterPackManager()
{
DeleteCriticalSection(&m_csFinder);
}
const CEterPackManager::TFileMap& CEterPackManager::GetFileMap() {
return this->m_FileMap;
}