增加List处理功能
This commit is contained in:
@@ -1,8 +1,142 @@
|
||||
#include "libNPK_FileList.h"
|
||||
#include "libNPK_Errors.h"
|
||||
#include "libNPK_Utils.h"
|
||||
|
||||
#include <Shlwapi.h>
|
||||
#include <strsafe.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <map>
|
||||
|
||||
namespace NPK
|
||||
{
|
||||
|
||||
const char LIST_FILE_SPE_CHAR = '|';
|
||||
|
||||
void NPKFileList::clear()
|
||||
{
|
||||
m_fileList.clear();
|
||||
}
|
||||
|
||||
bool NPKFileList::loadListFromFile(const wchar_t* wszListFile, const char* prefix,
|
||||
bool bNpkBase, bool bNpkName, bool bFileOffset, bool bFileSize, bool bFileCRC,
|
||||
bool bEnableDuplicate)
|
||||
{
|
||||
int tokeCounts = 1;
|
||||
tokeCounts += bNpkBase ? 1 : 0;
|
||||
tokeCounts += bNpkName ? 1 : 0;
|
||||
tokeCounts += bFileOffset ? 1 : 0;
|
||||
tokeCounts += bFileSize ? 1 : 0;
|
||||
tokeCounts += bFileCRC ? 1 : 0;
|
||||
|
||||
std::ifstream file(wszListFile);
|
||||
if (!file.is_open())
|
||||
{
|
||||
setLastError(NPK_ERR_FILE_ACCESS);
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t prefixLen = (prefix!= nullptr ? strlen(prefix) : 0);
|
||||
std::string line;
|
||||
while (std::getline(file, line))
|
||||
{
|
||||
if (line.empty()) continue;
|
||||
if (prefix != nullptr)
|
||||
{
|
||||
if (strncmp(prefix, line.c_str(), prefixLen) != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
std::stringstream lineSteam(line);
|
||||
std::vector<std::string> fileData;
|
||||
std::string token;
|
||||
|
||||
while (std::getline(lineSteam, token, LIST_FILE_SPE_CHAR))
|
||||
{
|
||||
fileData.push_back(token);
|
||||
}
|
||||
|
||||
if (fileData.size() != tokeCounts)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
FileItemFullInfo fullInfo;
|
||||
int32_t currentIT = 0;
|
||||
|
||||
//parser key name
|
||||
fullInfo.keyName = fileData[currentIT++];
|
||||
if (bNpkBase) {
|
||||
fullInfo.npkBase = fileData[currentIT++];
|
||||
}
|
||||
if (bNpkName) {
|
||||
fullInfo.npkName = fileData[currentIT++];
|
||||
}
|
||||
if (bFileOffset) {
|
||||
fullInfo.fileOffset = (uint32_t)(_atoi64(fileData[currentIT++].c_str()));
|
||||
}
|
||||
if (bFileSize) {
|
||||
fullInfo.fileSize = (uint32_t)(_atoi64(fileData[currentIT++].c_str()));
|
||||
}
|
||||
if (bFileCRC) {
|
||||
fullInfo.fileCRC = (uint32_t)(_atoi64(fileData[currentIT++].c_str()));
|
||||
}
|
||||
if (!addFileNode(fullInfo, bEnableDuplicate))
|
||||
{
|
||||
file.close();
|
||||
clear();
|
||||
setLastError(NPK_ERR_DUPLICATE_KEYNAME);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
file.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NPKFileList::dumpToLocalFile(const wchar_t* wszListFile,
|
||||
bool bNpkBase, bool bNpkName, bool bFileOffset, bool bFileSize, bool bFileCRC)
|
||||
{
|
||||
std::ofstream file(wszListFile);
|
||||
if (!file.is_open())
|
||||
{
|
||||
setLastError(NPK_ERR_FILE_ACCESS);
|
||||
return false;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < m_fileList.size(); i++)
|
||||
{
|
||||
const FileItemFullInfo& fullInfo = m_fileList[i];
|
||||
|
||||
std::string line = fullInfo.keyName;
|
||||
if (bNpkBase)
|
||||
{
|
||||
line += LIST_FILE_SPE_CHAR + fullInfo.npkBase;
|
||||
}
|
||||
if (bNpkName)
|
||||
{
|
||||
line += LIST_FILE_SPE_CHAR + fullInfo.npkName;
|
||||
}
|
||||
if (bFileOffset)
|
||||
{
|
||||
line += LIST_FILE_SPE_CHAR + std::to_string(fullInfo.fileOffset);
|
||||
}
|
||||
if (bFileSize)
|
||||
{
|
||||
line += LIST_FILE_SPE_CHAR + std::to_string(fullInfo.fileSize);
|
||||
}
|
||||
if (bFileCRC)
|
||||
{
|
||||
line += LIST_FILE_SPE_CHAR + std::to_string(fullInfo.fileCRC);
|
||||
}
|
||||
file << line << std::endl;
|
||||
}
|
||||
file.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
int32_t NPKFileList::getFileCounts(void) const
|
||||
{
|
||||
@@ -19,15 +153,125 @@ bool NPKFileList::getFileItem(int32_t index, FileItemFullInfo* fullInfo) const
|
||||
return true;
|
||||
}
|
||||
|
||||
void NPKFileList::addFileNode(const FileItemFullInfo& fullInfo)
|
||||
bool NPKFileList::getFileItem(const char* szKeyName, FileItemFullInfo* fileItemFullInfo) const
|
||||
{
|
||||
//TODO: check duplicate file name?
|
||||
m_fileList.push_back(fullInfo);
|
||||
auto it = m_hashList.find(szKeyName);
|
||||
if (it == m_hashList.end())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
*fileItemFullInfo = m_fileList[it->second];
|
||||
return true;
|
||||
}
|
||||
|
||||
void NPKFileList::mergeOtherListInto(const IFileList* source)
|
||||
bool NPKFileList::addFileNode(const FileItemFullInfo& fullInfo, bool bEnableDuplicate)
|
||||
{
|
||||
auto currentIT = m_hashList.find(fullInfo.keyName);
|
||||
//check duplicate file name?
|
||||
if (currentIT != m_hashList.end())
|
||||
{
|
||||
if (bEnableDuplicate)
|
||||
{
|
||||
m_fileList[currentIT->second] = fullInfo;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
auto newIT = m_fileList.size();
|
||||
m_fileList.push_back(fullInfo);
|
||||
m_hashList.insert(std::make_pair(fullInfo.keyName, newIT));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NPKFileList::mergeOtherListInto(const IFileList* source, bool bEnableDuplicate)
|
||||
{
|
||||
if (source == nullptr)
|
||||
{
|
||||
setLastError(NPK_ERR_PARAM);
|
||||
return false;
|
||||
}
|
||||
|
||||
int32_t counts = source->getFileCounts();
|
||||
for (int32_t i = 0; i < counts; i++)
|
||||
{
|
||||
FileItemFullInfo fullInfo;
|
||||
source->getFileItem(i, &fullInfo);
|
||||
|
||||
if (!addFileNode(fullInfo, bEnableDuplicate))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NPKFileList::applyToLocalNPKFiles(const wchar_t* wszNPKBase)
|
||||
{
|
||||
if (wszNPKBase == 0 || wszNPKBase[0] == L'\0')
|
||||
{
|
||||
setLastError(NPK_ERR_PARAM);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!PathFileExistsW(wszNPKBase) || !PathIsDirectoryW(wszNPKBase))
|
||||
{
|
||||
setLastError(NPK_ERR_FILE_ACCESS);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool result = true;
|
||||
std::map<std::wstring, std::pair<INPKFile*, IFileList*>> npkFileMap;
|
||||
for (size_t i = 0; i < m_fileList.size(); i++)
|
||||
{
|
||||
FileItemFullInfo& fullInfo = m_fileList[i];
|
||||
|
||||
std::wstring strNPKName = getNPKPathNameFromKeyName(wszNPKBase, fullInfo.keyName.c_str());
|
||||
auto it = npkFileMap.find(strNPKName);
|
||||
if (it == npkFileMap.end())
|
||||
{
|
||||
INPKFile* npkFile = NPK::createNPKFile();
|
||||
if (!(npkFile->openPakFile(strNPKName.c_str())))
|
||||
{
|
||||
result = false;
|
||||
setLastError(NPK_ERR_FILE_ACCESS);
|
||||
break;
|
||||
}
|
||||
IFileList* fullList = npkFile->generateFullInfoList();
|
||||
npkFileMap.insert(std::make_pair(strNPKName, std::make_pair(npkFile, fullList)));
|
||||
it = npkFileMap.find(strNPKName);
|
||||
}
|
||||
|
||||
IFileList* fullList = it->second.second;
|
||||
fullList->getFileItem(fullInfo.keyName.c_str(), &fullInfo);
|
||||
}
|
||||
|
||||
for (auto it = npkFileMap.begin(); it != npkFileMap.end(); ++it)
|
||||
{
|
||||
destoryFileList(it->second.second);
|
||||
it->second.first->closePakFile();
|
||||
}
|
||||
npkFileMap.clear();
|
||||
return result;
|
||||
}
|
||||
|
||||
std::wstring NPKFileList::getNPKPathNameFromKeyName(const wchar_t* wszNPKBase, const char* keyName)
|
||||
{
|
||||
std::wstring strKeyName = convertUtf8StringToWide(keyName);
|
||||
std::string::size_type lastSep = strKeyName.rfind(L'/');
|
||||
if (lastSep != std::string::npos)
|
||||
{
|
||||
strKeyName = strKeyName.substr(0, lastSep);
|
||||
}
|
||||
std::replace(strKeyName.begin(), strKeyName.end(), L'/', L'_');
|
||||
wchar_t wszNPKPathName[1024] = { 0 };
|
||||
StringCchCopyW(wszNPKPathName, 1024, wszNPKBase);
|
||||
PathAppendW(wszNPKPathName, strKeyName.c_str());
|
||||
PathAddExtensionW(wszNPKPathName, L".NPK");
|
||||
return std::wstring(wszNPKPathName);
|
||||
}
|
||||
|
||||
IFileList* createEmptyFileList()
|
||||
|
||||
@@ -2,19 +2,37 @@
|
||||
|
||||
#include "libNPK.h"
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace NPK
|
||||
{
|
||||
class NPKFileList : public IFileList
|
||||
{
|
||||
public:
|
||||
|
||||
public:
|
||||
virtual bool loadListFromFile(const wchar_t* wszListFile, const char* prefix,
|
||||
bool bNpkBase, bool bNpkName, bool bFileOffset, bool bFileSize, bool bFileCRC,
|
||||
bool bEnableDuplicate) override;
|
||||
virtual bool dumpToLocalFile(const wchar_t* wszListFile,
|
||||
bool bNpkBase, bool bNpkName, bool bFileOffset, bool bFileSize, bool bFileCRC);
|
||||
virtual bool mergeOtherListInto(const IFileList* sourceFileList, bool bEnableDuplicate) override;
|
||||
virtual bool applyToLocalNPKFiles(const wchar_t* wszNPKBase) override;
|
||||
|
||||
virtual int32_t getFileCounts(void) const override;
|
||||
virtual bool getFileItem(int32_t index, FileItemFullInfo* fullInfo) const override;
|
||||
virtual void addFileNode(const FileItemFullInfo& fullInfo) override;
|
||||
virtual void mergeOtherListInto(const IFileList* sourceFileList) override;
|
||||
virtual bool getFileItem(const char* szKeyName, FileItemFullInfo* fileItemFullInfo) const override;
|
||||
|
||||
public:
|
||||
bool addFileNode(const FileItemFullInfo& fullInfo, bool bEnableDuplicate);
|
||||
|
||||
private:
|
||||
void clear();
|
||||
std::wstring getNPKPathNameFromKeyName(const wchar_t* wszNPKBase, const char* keyName);
|
||||
|
||||
private:
|
||||
std::vector<FileItemFullInfo> m_fileList;
|
||||
std::unordered_map<std::string, std::vector<FileItemFullInfo>::size_type> m_hashList;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "libEncrypt_SHA256.h"
|
||||
#include "libNPK_FileStream.h"
|
||||
#include "libNPK_Utils.h"
|
||||
#include "libNPK_FileList.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
@@ -302,7 +303,15 @@ IFileList* CNPKFile::generateFullInfoList(void)
|
||||
{
|
||||
fullInfo.fileCRC = 0;
|
||||
}
|
||||
pFileList->addFileNode(fullInfo); // Add file item to the list
|
||||
// Add file item to the list
|
||||
if (!((NPKFileList*)pFileList)->addFileNode(fullInfo, false))
|
||||
{
|
||||
//duplicate key name, error!
|
||||
closeFileStream(pFileStream);
|
||||
destoryFileList(pFileList);
|
||||
setLastError(NPK_ERR_INVALID_FILE_FORMAT, "Duplicate keyname in NPK file");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
return pFileList;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user