增加Lua导出和FileList
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
#include "libNPK_FileList.h"
|
||||
|
||||
namespace NPK
|
||||
{
|
||||
|
||||
|
||||
int32_t NPKFileList::getFileCounts(void) const
|
||||
{
|
||||
return (int32_t)m_fileList.size();
|
||||
}
|
||||
|
||||
bool NPKFileList::getFileItem(int32_t index, FileItemFullInfo* fullInfo) const
|
||||
{
|
||||
if(index< 0 || index >= getFileCounts())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
*fullInfo = m_fileList[index];
|
||||
return true;
|
||||
}
|
||||
|
||||
void NPKFileList::addFileNode(const FileItemFullInfo& fullInfo)
|
||||
{
|
||||
//TODO: check duplicate file name?
|
||||
m_fileList.push_back(fullInfo);
|
||||
}
|
||||
|
||||
void NPKFileList::mergeOtherListInto(const IFileList* source)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
IFileList* createEmptyFileList()
|
||||
{
|
||||
return new NPKFileList();
|
||||
}
|
||||
|
||||
// destroy a file list
|
||||
void destoryFileList(IFileList* fileList)
|
||||
{
|
||||
delete ((NPKFileList*)fileList);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include "libNPK.h"
|
||||
#include <vector>
|
||||
|
||||
namespace NPK
|
||||
{
|
||||
class NPKFileList : public IFileList
|
||||
{
|
||||
public:
|
||||
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;
|
||||
|
||||
private:
|
||||
std::vector<FileItemFullInfo> m_fileList;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -7,12 +7,12 @@
|
||||
namespace NPK
|
||||
{
|
||||
|
||||
CFileStream::CFileStream(CNPKFile* pNPKFile, HANDLE hFile, const INPKFile::FileNode& fileNode)
|
||||
CFileStream::CFileStream(CNPKFile* pNPKFile, HANDLE hFile, const FileItemBaseInfo& baseFileInfo)
|
||||
: m_pNPKFile(pNPKFile)
|
||||
, m_hFileandle(hFile)
|
||||
, m_fileName(fileNode.fileName)
|
||||
, m_fileOffset(fileNode.fileOffset)
|
||||
, m_fileSize(fileNode.fileSize)
|
||||
, m_fileName(baseFileInfo.keyName)
|
||||
, m_fileOffset(baseFileInfo.fileOffset)
|
||||
, m_fileSize(baseFileInfo.fileSize)
|
||||
, m_currentOffset(0)
|
||||
{
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ protected:
|
||||
bool m_crc32Calculated = false;
|
||||
|
||||
private:
|
||||
CFileStream(CNPKFile* pNPKFile, HANDLE hFile, const INPKFile::FileNode& fileNode);
|
||||
CFileStream(CNPKFile* pNPKFile, HANDLE hFile, const FileItemBaseInfo& baseFileInfo);
|
||||
virtual ~CFileStream();
|
||||
|
||||
friend IFileStream* CNPKFile::openFileStream(const char* szFileName);
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "libNPK_Errors.h"
|
||||
#include "libEncrypt_SHA256.h"
|
||||
#include "libNPK_FileStream.h"
|
||||
#include "libNPK_Utils.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
@@ -20,13 +21,20 @@ CNPKFile::CNPKFile()
|
||||
|
||||
CNPKFile::~CNPKFile()
|
||||
{
|
||||
|
||||
if (m_hPakFile != NULL)
|
||||
{
|
||||
::CloseHandle(m_hPakFile);
|
||||
m_hPakFile = NULL;
|
||||
}
|
||||
m_nFileCounts = 0;
|
||||
m_fileList.clear();
|
||||
m_hashFileList.clear();
|
||||
}
|
||||
|
||||
bool CNPKFile::openPakFile(const char* szPackFileName)
|
||||
bool CNPKFile::openPakFile(const wchar_t* wszNpkPathName)
|
||||
{
|
||||
assert(szPackFileName);
|
||||
if (!szPackFileName || szPackFileName[0] == 0)
|
||||
assert(wszNpkPathName);
|
||||
if (!wszNpkPathName || wszNpkPathName[0] == 0)
|
||||
{
|
||||
setLastError(NPK_ERR_PARAM);
|
||||
return false;
|
||||
@@ -35,10 +43,15 @@ bool CNPKFile::openPakFile(const char* szPackFileName)
|
||||
//close current pak file if it is open
|
||||
closePakFile();
|
||||
|
||||
m_strPackFileName = szPackFileName;
|
||||
wchar_t wszNpkBaseName[1024] = { 0 };
|
||||
StringCchCopyW(wszNpkBaseName, 1024, wszNpkPathName);
|
||||
PathRemoveFileSpecW(wszNpkBaseName);
|
||||
|
||||
m_strPackBaseName = convertWideStringToUtf8(wszNpkBaseName);
|
||||
m_strPackFileName = convertWideStringToUtf8(::PathFindFileNameW(wszNpkPathName));
|
||||
|
||||
//open the pak file
|
||||
m_hPakFile = ::CreateFile(szPackFileName,
|
||||
m_hPakFile = ::CreateFileW(wszNpkPathName,
|
||||
GENERIC_READ,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
0,
|
||||
@@ -48,7 +61,8 @@ bool CNPKFile::openPakFile(const char* szPackFileName)
|
||||
|
||||
if (m_hPakFile == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
setLastError(NPK_ERR_FILE_ACCESS, "File=%s, WinErr=%d", szPackFileName, ::GetLastError());
|
||||
setLastError(NPK_ERR_FILE_ACCESS, "File=%s, WinErr=%d",
|
||||
convertWideStringToUtf8(wszNpkPathName).c_str(), ::GetLastError());
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -67,7 +81,8 @@ bool CNPKFile::openPakFile(const char* szPackFileName)
|
||||
//Check NPK Magic Header
|
||||
if(memcmp(fileHeader.szFileHeadMagic, kNPKFileHeaderMagic, kNPKFileHeaderMagicSize) != 0)
|
||||
{
|
||||
setLastError(NPK_ERR_INVALID_FILE_FORMAT, "File=%s, Magic=%s", szPackFileName, fileHeader.szFileHeadMagic);
|
||||
setLastError(NPK_ERR_INVALID_FILE_FORMAT, "File=%s, Magic=%s",
|
||||
convertWideStringToUtf8(wszNpkPathName).c_str(), fileHeader.szFileHeadMagic);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -94,7 +109,7 @@ bool CNPKFile::openPakFile(const char* szPackFileName)
|
||||
fileInfo.szFileName[j] ^= kNPKFileNameXorCode[j];
|
||||
}
|
||||
|
||||
m_fileList[i].fileName = fileInfo.szFileName;
|
||||
m_fileList[i].keyName = fileInfo.szFileName;
|
||||
m_fileList[i].fileOffset = fileInfo.fileOffset;
|
||||
m_fileList[i].fileSize = fileInfo.fileSize;
|
||||
}
|
||||
@@ -177,8 +192,8 @@ void CNPKFile::buildHashFileList()
|
||||
m_hashFileList.clear();
|
||||
for (int32_t i = 0; i < m_nFileCounts; i++)
|
||||
{
|
||||
const FileNode& fileNode = m_fileList[i];
|
||||
m_hashFileList[fileNode.fileName] = i;
|
||||
const FileItemBaseInfo& baseInfo = m_fileList[i];
|
||||
m_hashFileList[baseInfo.keyName] = i;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -194,13 +209,13 @@ bool CNPKFile::closePakFile(void)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CNPKFile::getFileNode(int32_t index, INPKFile::FileNode& fileNode) const
|
||||
bool CNPKFile::getFileItemBaseInfo(int32_t index, FileItemBaseInfo* baseInfo) const
|
||||
{
|
||||
if (index < 0 || index >= getFileCount())
|
||||
if (index < 0 || index >= getFileCounts())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
fileNode = m_fileList[index];
|
||||
*baseInfo = m_fileList[index];
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -231,13 +246,13 @@ IFileStream* CNPKFile::openFileStream(const char* szFileName)
|
||||
fileIndex = it->second;
|
||||
}
|
||||
|
||||
if (fileIndex < 0 || fileIndex >= getFileCount())
|
||||
if (fileIndex < 0 || fileIndex >= getFileCounts())
|
||||
{
|
||||
setLastError(NPK_ERR_FILE_NOT_FOUND, "File=%s, FileIndex=%d, not found in NPK file", szFileName, fileIndex);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
FileNode& fileNode = m_fileList[fileIndex];
|
||||
FileItemBaseInfo& fileNode = m_fileList[fileIndex];
|
||||
CFileStream* pFileStream = new CFileStream(this, m_hPakFile, fileNode);
|
||||
|
||||
return pFileStream;
|
||||
@@ -251,6 +266,47 @@ void CNPKFile::closeFileStream(IFileStream* fileStream)
|
||||
}
|
||||
}
|
||||
|
||||
IFileList* CNPKFile::generateFullInfoList(void)
|
||||
{
|
||||
if (m_hPakFile == NULL)
|
||||
{
|
||||
setLastError(NPK_ERR_INVALID_STATE, "NPK file is not opened");
|
||||
return nullptr;
|
||||
}
|
||||
IFileList* pFileList = createEmptyFileList();
|
||||
if (!pFileList)
|
||||
{
|
||||
setLastError(NPK_ERR_NEW_FAILED, "Failed to create empty file list");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
for (int32_t i = 0; i < m_nFileCounts; i++)
|
||||
{
|
||||
const FileItemBaseInfo& baseInfo = m_fileList[i];
|
||||
|
||||
FileItemFullInfo fullInfo;
|
||||
fullInfo.keyName = baseInfo.keyName;
|
||||
fullInfo.npkName = m_strPackFileName;
|
||||
fullInfo.npkBase = m_strPackBaseName;
|
||||
fullInfo.fileSize = baseInfo.fileSize;
|
||||
fullInfo.fileOffset = baseInfo.fileOffset;
|
||||
|
||||
IFileStream* pFileStream = openFileStream(baseInfo.keyName.c_str());
|
||||
if (pFileStream)
|
||||
{
|
||||
fullInfo.fileCRC = pFileStream->crc32();
|
||||
closeFileStream(pFileStream);
|
||||
pFileStream = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
fullInfo.fileCRC = 0;
|
||||
}
|
||||
pFileList->addFileNode(fullInfo); // Add file item to the list
|
||||
}
|
||||
return pFileList;
|
||||
}
|
||||
|
||||
INPKFile* createNPKFile()
|
||||
{
|
||||
return new CNPKFile();
|
||||
|
||||
@@ -28,30 +28,33 @@ public:
|
||||
} FileInfo;
|
||||
|
||||
public:
|
||||
virtual bool openPakFile(const char* szPackFileName) override;
|
||||
virtual bool openPakFile(const wchar_t* wszNpkPathName) override;
|
||||
|
||||
virtual bool closePakFile(void) override;
|
||||
|
||||
virtual int32_t getFileCount(void) const override {
|
||||
virtual int32_t getFileCounts(void) const override {
|
||||
return m_nFileCounts;
|
||||
}
|
||||
|
||||
virtual bool getFileNode(int32_t index, FileNode& fileNode) const override;
|
||||
virtual bool getFileItemBaseInfo(int32_t index, FileItemBaseInfo* baseInfo) const override;
|
||||
|
||||
virtual IFileStream* openFileStream(const char* szFileName) override;
|
||||
|
||||
virtual void closeFileStream(IFileStream* fileStream) override;
|
||||
|
||||
virtual IFileList* generateFullInfoList(void);
|
||||
|
||||
private:
|
||||
bool checkPakFileHash(void);
|
||||
void buildHashFileList(void);
|
||||
|
||||
private:
|
||||
std::string m_strPackFileName;
|
||||
std::string m_strPackBaseName; //utf8
|
||||
std::string m_strPackFileName; //utf8
|
||||
HANDLE m_hPakFile = NULL;
|
||||
int32_t m_nFileCounts = 0;
|
||||
|
||||
typedef std::vector<FileNode> FileList;
|
||||
typedef std::vector<FileItemBaseInfo> FileList;
|
||||
FileList m_fileList;
|
||||
|
||||
typedef std::unordered_map<std::string, int32_t> FileHashList;
|
||||
|
||||
@@ -109,6 +109,52 @@ std::wstring convertAnsiStringToWide(const char* szSource)
|
||||
return strReturn;
|
||||
}
|
||||
|
||||
std::string convertWideStringToUtf8(const wchar_t* source)
|
||||
{
|
||||
const static int DEFAULT_CHAR_BUF_SIZE = 1024;
|
||||
char DEFAULT_CHAR_BUF[DEFAULT_CHAR_BUF_SIZE] = { 0 };
|
||||
|
||||
if(source==nullptr || source[0]==L'\0')
|
||||
return std::string();
|
||||
|
||||
int targetLen = WideCharToMultiByte(CP_UTF8, 0, source, -1, nullptr, 0, nullptr, nullptr);
|
||||
if (targetLen == 0)
|
||||
return std::string();
|
||||
|
||||
char* szTemp = 0;
|
||||
|
||||
if (targetLen >= DEFAULT_CHAR_BUF_SIZE)
|
||||
szTemp = new char[targetLen];
|
||||
else
|
||||
szTemp = DEFAULT_CHAR_BUF;
|
||||
|
||||
WideCharToMultiByte(CP_UTF8, 0, source, -1, szTemp, targetLen, nullptr, nullptr);
|
||||
|
||||
return std::string(szTemp);
|
||||
}
|
||||
|
||||
std::wstring convertUtf8StringToWide(const char* source)
|
||||
{
|
||||
const static int DEFAULT_WCHAR_BUF_SIZE = 1024;
|
||||
wchar_t DEFAULT_WCHAR_BUF[DEFAULT_WCHAR_BUF_SIZE] = { 0 };
|
||||
|
||||
if (source == nullptr || source[0] == '\0')
|
||||
return std::wstring();
|
||||
|
||||
int targetLen = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, source, -1, nullptr, 0);
|
||||
if (targetLen == 0)
|
||||
return std::wstring();
|
||||
|
||||
wchar_t* wszTemp = 0;
|
||||
if (targetLen >= DEFAULT_WCHAR_BUF_SIZE)
|
||||
wszTemp = new wchar_t[targetLen];
|
||||
else
|
||||
wszTemp = DEFAULT_WCHAR_BUF;
|
||||
|
||||
int result = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, source, -1, wszTemp, targetLen);
|
||||
return std::wstring(wszTemp);
|
||||
}
|
||||
|
||||
uint8_t* readFileToBuffer(const char* filename, int64_t& outSize)
|
||||
{
|
||||
FILE* file = nullptr;
|
||||
|
||||
Reference in New Issue
Block a user