*
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
#ifndef ENTRY_INFO_H__
|
||||
#define ENTRY_INFO_H__
|
||||
#include "PakTypes.h"
|
||||
|
||||
#define MAX_ENTRY_NAME_LENGTH 0x100
|
||||
|
||||
typedef struct entry_info
|
||||
{
|
||||
int fileSize;
|
||||
tchar fileName[MAX_ENTRY_NAME_LENGTH];
|
||||
}entry_info;
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
#include "../../../LString.h"
|
||||
|
||||
#define MAX_ENTRY_NAME_LENGTH 0x100
|
||||
|
||||
typedef struct FileEntry
|
||||
{
|
||||
int parentIndex;
|
||||
int fileSize;
|
||||
int fileOffset;
|
||||
tchar name[MAX_ENTRY_NAME_LENGTH];
|
||||
}FileEntry, *PFileEntry, **LPFileEntry;
|
||||
@@ -0,0 +1,6 @@
|
||||
#define MAX_ENTRY_NAME_LENGTH 0x100
|
||||
|
||||
typedef struct FolderEntry
|
||||
{
|
||||
wchar_t name[MAX_ENTRY_NAME_LENGTH];
|
||||
}FolderEntry;
|
||||
@@ -0,0 +1,312 @@
|
||||
#include "PakFile.h"
|
||||
#include <assert.h>
|
||||
#include "../../../log/CLog.h"
|
||||
namespace LifeCore
|
||||
{
|
||||
PakFile::PakFile(void)
|
||||
:openEntriesCount(0)
|
||||
{
|
||||
currentMode = PM_IDLE;
|
||||
memset(&openEntries[0], 0, sizeof(OpenEntryInfo) * PAK_MAX_OPEN_ENTRY);
|
||||
}
|
||||
|
||||
PakFile::~PakFile(void)
|
||||
{
|
||||
}
|
||||
|
||||
int PakFile::Open(IDataStream* source)
|
||||
{
|
||||
curEntryId = 0;
|
||||
pFile = source;
|
||||
//
|
||||
// pFile = CreateFileA(path.c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if(pFile->Length() == 0)
|
||||
{
|
||||
//write default header to created file
|
||||
header.version = PAK_VERSION;
|
||||
header.whiteSpacesCount = 0;
|
||||
header.filesCount = 0;
|
||||
header.foldersCount = 0;
|
||||
header.lastFolderId = 0;
|
||||
header.dataChunkLength = 0;
|
||||
header.extraDataOffset = sizeof(PakHeader);
|
||||
|
||||
pFile->Seek(header.extraDataOffset);
|
||||
// SetFilePointer(pFile, header.extraDataOffset, NULL, FILE_BEGIN);
|
||||
|
||||
freeFileSlots = 16;
|
||||
hFiles = (FileEntry*)malloc(sizeof(FileEntry) * 16);
|
||||
tmpEntry = hFiles;
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD numWrite = 0;
|
||||
//read file header
|
||||
numWrite = pFile->Read(&header,sizeof(PakHeader));
|
||||
//ReadFile(pFile,&header,sizeof(PakHeader), &numWrite, NULL);
|
||||
|
||||
if(header.version != PAK_VERSION)
|
||||
{
|
||||
//CloseHandle(pFile);
|
||||
//pFile->Close();
|
||||
return PAK_BAD_FILE;
|
||||
}
|
||||
|
||||
pFile->Seek(header.extraDataOffset);
|
||||
|
||||
//read folder entries
|
||||
int cntAlloc;
|
||||
cntAlloc = header.foldersCount > 0 ? header.foldersCount : 16;
|
||||
freeFolderSlots = header.foldersCount > 0 ? 0 : 16;
|
||||
hFolders = (FolderEntry*)malloc(sizeof(FolderEntry) * cntAlloc);
|
||||
|
||||
pFile->Read(hFolders, sizeof(FolderEntry) * header.foldersCount);
|
||||
//ReadFile(pFile, hFolders, sizeof(FolderEntry) * header.foldersCount, &numWrite, NULL);
|
||||
|
||||
//read file entries
|
||||
cntAlloc = header.filesCount > 0 ? header.filesCount : 16;
|
||||
freeFileSlots = header.filesCount > 0 ? 0 : 16;
|
||||
hFiles = (FileEntry*)malloc(sizeof(FileEntry) * cntAlloc);
|
||||
|
||||
pFile->Read(hFiles, sizeof(FileEntry) * header.filesCount);
|
||||
//ReadFile(pFile, hFiles, sizeof(FileEntry) * header.filesCount, &numWrite, NULL);
|
||||
|
||||
tmpEntry = hFiles;
|
||||
}
|
||||
return PAK_OK;
|
||||
}
|
||||
|
||||
void PakFile::DumpExtraData()
|
||||
{
|
||||
pFile->Seek(sizeof(PakHeader) + header.dataChunkLength);
|
||||
if(header.foldersCount > 0){
|
||||
pFile->Write(hFolders, sizeof(FolderEntry) * header.foldersCount);
|
||||
}
|
||||
|
||||
if(header.filesCount > 0)
|
||||
{
|
||||
pFile->Write(hFiles, sizeof(FileEntry) * header.filesCount);
|
||||
}
|
||||
}
|
||||
|
||||
void PakFile::DumpHeader()
|
||||
{
|
||||
DWORD numWrite = 0;
|
||||
pFile->Seek(0);
|
||||
//SetFilePointer(pFile, 0, NULL, FILE_BEGIN);
|
||||
//WriteFile(pFile, &header, sizeof(PakHeader), &numWrite, NULL);
|
||||
numWrite = pFile->Write(&header, sizeof(PakHeader));
|
||||
}
|
||||
|
||||
void PakFile::NewFolderEntry(const String& path)
|
||||
{
|
||||
CLog::me()->Write(path);
|
||||
/*FolderEntry newEntry;
|
||||
memset(newEntry.name,0,sizeof(wchar_t) * MAX_ENTRY_NAME_LENGTH);
|
||||
path.copy(newEntry.name, path.length());
|
||||
FolderCollection[path] = newEntry;
|
||||
header.foldersCount++;*/
|
||||
}
|
||||
PakEntryHandle PakFile::fopen(const String& name)
|
||||
{
|
||||
if(openEntriesCount >= PAK_MAX_OPEN_ENTRY)
|
||||
return -1;
|
||||
|
||||
if(LocateEntry(name) != PAK_OK)
|
||||
return -1;
|
||||
|
||||
openEntries[openEntriesCount].entry = tmpEntry;
|
||||
openEntries[openEntriesCount].position = 0;
|
||||
|
||||
openEntriesCount++;
|
||||
|
||||
return openEntriesCount - 1;
|
||||
}
|
||||
int PakFile::fread(PakEntryHandle entry, void* buffer, int length)
|
||||
{
|
||||
if(entry < 0 || entry >= PAK_MAX_OPEN_ENTRY)
|
||||
return -1;
|
||||
|
||||
OpenEntryInfo* info = &openEntries[entry];
|
||||
|
||||
int maxCnt = info->entry->fileSize - info->position;
|
||||
if(!length || !maxCnt)
|
||||
return 0;
|
||||
if(length > maxCnt)
|
||||
length = maxCnt;
|
||||
|
||||
//SetFilePointer(pFile, info->entry->fileOffset + info->position, NULL, FILE_BEGIN);
|
||||
pFile->Seek(info->entry->fileOffset + info->position);
|
||||
|
||||
DWORD numWrite = 0;
|
||||
numWrite = pFile->Read(buffer, length);
|
||||
//ReadFile(pFile, buffer, length, &numWrite, NULL);
|
||||
curFilePosition +=numWrite;
|
||||
info->position += numWrite;
|
||||
return numWrite;
|
||||
}
|
||||
int PakFile::fwrite(PakEntryHandle entry, const void* buffer, int length)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(entry);
|
||||
UNREFERENCED_PARAMETER(buffer);
|
||||
UNREFERENCED_PARAMETER(length);
|
||||
return 0;
|
||||
}
|
||||
void PakFile::fclose(PakEntryHandle entry)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(entry);
|
||||
}
|
||||
int PakFile::fget_size(PakEntryHandle entry)
|
||||
{
|
||||
if(entry < 0 || entry >= PAK_MAX_OPEN_ENTRY)
|
||||
throw "PAK entry is invalid! Can not seek";
|
||||
|
||||
return openEntries[entry].entry->fileSize;
|
||||
}
|
||||
void PakFile::fseek(PakEntryHandle entry, int position)
|
||||
{
|
||||
if(entry < 0 || entry >= PAK_MAX_OPEN_ENTRY)
|
||||
throw "PAK entry is invalid! Can not seek";
|
||||
|
||||
if(openEntries[entry].entry->fileSize < position || position < 0)
|
||||
throw "Invalid PAK position specified! Fseek()";
|
||||
|
||||
openEntries[entry].position = position;
|
||||
}
|
||||
int PakFile::ftell(PakEntryHandle entry)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
if(entry < 0 || entry >= PAK_MAX_OPEN_ENTRY)
|
||||
return -1;
|
||||
#endif
|
||||
return openEntries[entry].position;
|
||||
}
|
||||
void PakFile::NewFileEntry(const String& path)
|
||||
{
|
||||
if(!freeFileSlots)
|
||||
{
|
||||
hFiles = (FileEntry*)realloc(hFiles, sizeof(FileEntry) * header.filesCount + sizeof(FileEntry) * 16);
|
||||
freeFileSlots = 16;
|
||||
}
|
||||
|
||||
//SetFilePointer(pFile, sizeof(PakHeader) + header.dataChunkLength, NULL, FILE_BEGIN);
|
||||
pFile->Seek(sizeof(PakHeader) + header.dataChunkLength);
|
||||
currentMode = PM_WRITE_ENTRY;
|
||||
tmpEntry = hFiles + header.filesCount;
|
||||
header.filesCount++;
|
||||
|
||||
freeFileSlots--;
|
||||
memset(tmpEntry,0,sizeof(FileEntry));
|
||||
path.copy(tmpEntry->name, path.length());
|
||||
tmpEntry->fileOffset = sizeof(PakHeader) + header.dataChunkLength;
|
||||
}
|
||||
|
||||
/*void PakFile::CloseCurrentEntry()
|
||||
{
|
||||
currentMode = PM_IDLE;
|
||||
}
|
||||
void PakFile::WriteCurrentEntry(const void* pData, int length)
|
||||
{
|
||||
DWORD numWrite = 0;
|
||||
//WriteFile(pFile, pData, length, &numWrite, NULL);
|
||||
numWrite = pFile->Write(pData, length);
|
||||
header.dataChunkLength+=length;
|
||||
tmpEntry->fileSize+=length;
|
||||
curFilePosition+=numWrite;
|
||||
}*/
|
||||
int PakFile::LocateEntry(const String& name)
|
||||
{
|
||||
int lastEntry = curEntryId;
|
||||
for(int i = 0; i < header.filesCount; i++)
|
||||
{
|
||||
curEntryId = i;
|
||||
LocateEntry(curEntryId);
|
||||
if(tmpEntry->name == name)
|
||||
return PAK_OK;
|
||||
}
|
||||
curEntryId = lastEntry;
|
||||
LocateEntry(curEntryId);
|
||||
return PAK_ARG_ERROR;
|
||||
}
|
||||
int PakFile::LocateEntry(int id)
|
||||
{
|
||||
if(id >= header.filesCount)
|
||||
return PAK_ARG_ERROR;
|
||||
curEntryId = id;
|
||||
tmpEntry = hFiles + id;
|
||||
return PAK_OK;
|
||||
}
|
||||
void PakFile::Close()
|
||||
{
|
||||
header.extraDataOffset = sizeof(PakHeader) + header.dataChunkLength;
|
||||
DumpHeader();
|
||||
DumpExtraData();
|
||||
}
|
||||
|
||||
void PakFile::DeleteFileEntry(const String& path)
|
||||
{
|
||||
if(LocateEntry(path) == PAK_OK)
|
||||
{
|
||||
if(IsLastEntry(tmpEntry))
|
||||
{
|
||||
header.filesCount--;
|
||||
header.dataChunkLength-= tmpEntry->fileSize;
|
||||
memset(tmpEntry, 0, sizeof(FileEntry));
|
||||
}
|
||||
else
|
||||
{
|
||||
header.filesCount--;
|
||||
memmove(tmpEntry, tmpEntry + 1, (header.filesCount - curEntryId) * sizeof(FileEntry));
|
||||
}
|
||||
}
|
||||
}
|
||||
BOOL PakFile::IsLastEntry(const FileEntry* entry)
|
||||
{
|
||||
return (UINT)(entry->fileOffset + entry->fileSize) == sizeof(PakHeader) + header.dataChunkLength;
|
||||
}
|
||||
/*void PakFile::OpenCurrentEntry()
|
||||
{
|
||||
curFilePosition = 0;
|
||||
currentMode = PM_READ_ENTRY;
|
||||
//SetFilePointer(pFile, tmpEntry->fileOffset, NULL, FILE_BEGIN);
|
||||
pFile->Seek(tmpEntry->fileOffset);
|
||||
}
|
||||
int PakFile::ReadCurrentEntry(void *pBuffer, int length)
|
||||
{
|
||||
int maxCnt = tmpEntry->fileSize - curFilePosition;
|
||||
if(!length || !maxCnt)
|
||||
return 0;
|
||||
if(length > maxCnt)
|
||||
length = maxCnt;
|
||||
DWORD numWrite = 0;
|
||||
//ReadFile(pFile, pBuffer, length, &numWrite, NULL);
|
||||
numWrite = pFile->Read(pBuffer, length);
|
||||
|
||||
curFilePosition +=numWrite;
|
||||
return numWrite;
|
||||
}*/
|
||||
/*void PakFile::SeekCurrentEntry(int position)
|
||||
{
|
||||
SetFilePointer(pFile, tmpEntry->fileOffset + position, NULL, FILE_BEGIN);
|
||||
pFile->Seek(tmpEntry->fileOffset + position);
|
||||
curFilePosition = position;
|
||||
}
|
||||
int PakFile::TellCurrentEntry()
|
||||
{
|
||||
return curFilePosition;
|
||||
}*/
|
||||
int PakFile::filesCount()
|
||||
{
|
||||
return header.filesCount;
|
||||
}
|
||||
entry_info PakFile::GetEntryInfo(int id)
|
||||
{
|
||||
if(id < 0 || id >= filesCount())
|
||||
throw "PAK entry is invalid! Can not get info";
|
||||
FileEntry* entry = hFiles + id;
|
||||
entry_info info;
|
||||
strcpy_s(info.fileName, entry->name);
|
||||
info.fileSize = entry->fileSize;
|
||||
return info;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
#ifndef PAK_FILE_H__
|
||||
#define PAK_FILE_H__
|
||||
|
||||
#include <stdio.h>
|
||||
#include <tchar.h>
|
||||
#include "../../../LString.h"
|
||||
#include "PakTypes.h"
|
||||
#include <windows.h>
|
||||
#include "pakHeader.h"
|
||||
#include "FolderEntry.h"
|
||||
#include "FileEntry.h"
|
||||
#include "EntryInfo.h"
|
||||
#include "../../../IDataStream.h"
|
||||
#include <map>
|
||||
#define PAK_VERSION 0x0100
|
||||
#define PAK_MAX_OPEN_ENTRY 256
|
||||
|
||||
namespace LifeCore
|
||||
{
|
||||
struct OpenEntryInfo
|
||||
{
|
||||
FileEntry* entry;
|
||||
int position;
|
||||
};
|
||||
typedef int PakEntryHandle;
|
||||
|
||||
class PakFile
|
||||
{
|
||||
enum PAK_MODE
|
||||
{
|
||||
PM_WRITE_ENTRY = 0,
|
||||
PM_READ_ENTRY = 1,
|
||||
PM_EDIT_ENTRY = 2,
|
||||
PM_IDLE = 3
|
||||
};
|
||||
|
||||
public:
|
||||
PakFile(void);
|
||||
~PakFile(void);
|
||||
int Open(IDataStream* source);
|
||||
|
||||
void Close();
|
||||
int filesCount();
|
||||
entry_info GetEntryInfo(int id);
|
||||
PakEntryHandle fopen(const String& name);
|
||||
int fread(PakEntryHandle entry, void* buffer, int length);
|
||||
int fwrite(PakEntryHandle entry, const void* buffer, int length);
|
||||
int ftell(PakEntryHandle entry);
|
||||
void fseek(PakEntryHandle entry, int position);
|
||||
void fclose(PakEntryHandle entry);
|
||||
int fget_size(PakEntryHandle entry);
|
||||
private:
|
||||
int curFilePosition;
|
||||
int curEntryId;
|
||||
int freeFileSlots;
|
||||
int freeFolderSlots;
|
||||
int currentMode;
|
||||
FolderEntry* hFolders;
|
||||
FileEntry* hFiles;
|
||||
IDataStream* pFile;
|
||||
PakHeader header;
|
||||
void DumpExtraData();
|
||||
void DumpHeader();
|
||||
FileEntry* tmpEntry;
|
||||
|
||||
void NewFolderEntry(const String& path);
|
||||
void NewFileEntry(const String& path);
|
||||
void DeleteFileEntry(const String& path);
|
||||
|
||||
int LocateEntry(const String& name);
|
||||
int LocateEntry(int id);
|
||||
|
||||
OpenEntryInfo openEntries[PAK_MAX_OPEN_ENTRY];
|
||||
int openEntriesCount;
|
||||
|
||||
BOOL IsLastEntry(const FileEntry* entry);
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,16 @@
|
||||
#ifndef PAK_TYPES_H__
|
||||
#define PAK_TYPES_H__
|
||||
|
||||
#define PAK_ARG_ERROR (-100)
|
||||
#define PAK_INTERNAL_ERROR (-101)
|
||||
#define PAK_BAD_FILE (-102)
|
||||
#define PAK_OK (0)
|
||||
#include "../../../LString.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#define PATH_SPLITTER _text("\\")
|
||||
#else
|
||||
#define PATH_SPLITTER _text("/")
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,12 @@
|
||||
#include <vector>
|
||||
|
||||
typedef struct PakHeader
|
||||
{
|
||||
int version;
|
||||
int whiteSpacesCount;
|
||||
int filesCount;
|
||||
int foldersCount;
|
||||
int extraDataOffset;
|
||||
int lastFolderId;
|
||||
int dataChunkLength;
|
||||
} PakHeader;
|
||||
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
// The following macros define the minimum required platform. The minimum required platform
|
||||
// is the earliest version of Windows, Internet Explorer etc. that has the necessary features to run
|
||||
// your application. The macros work by enabling all features available on platform versions up to and
|
||||
// including the version specified.
|
||||
|
||||
// Modify the following defines if you have to target a platform prior to the ones specified below.
|
||||
// Refer to MSDN for the latest info on corresponding values for different platforms.
|
||||
#ifndef _WIN32_WINNT // Specifies that the minimum required platform is Windows Vista.
|
||||
#define _WIN32_WINNT 0x0600 // Change this to the appropriate value to target other versions of Windows.
|
||||
#endif
|
||||
Reference in New Issue
Block a user