This commit is contained in:
2025-05-13 02:46:21 +03:00
parent 143e16692e
commit 86914b7fcc
610 changed files with 92343 additions and 2 deletions
+31
View File
@@ -0,0 +1,31 @@
#include "IPakFile.h"
#include "IPakFileContentProvider.h"
namespace LifeCore
{
IPakFile::IPakFile()
{
isOpen = false;
}
IDataStreamPtr IPakFile::OpenWrite(int mode)
{
printf("ow->mode: %i\n", mode);
g_stream = new IPakStream(&((IPakFileContentProvider*)this->Provider)->g_sourceFile, EntryName, FA_WRITE);
return IDataStreamPtr(g_stream);
}
IDataStreamPtr IPakFile::OpenReadWrite(int mode)
{
printf("or->mode: %i\n", mode);
return IDataStreamPtr(0);
//throw new NotImplementedException();
}
IDataStreamPtr IPakFile::OpenRead()
{
IPakFileContentProvider* prov = (IPakFileContentProvider*)this->Provider;
g_stream = new IPakStream(&prov->g_sourceFile, EntryName, FA_READ);
return IDataStreamPtr(g_stream);
//g_stream = new IZipStream((this->Provider as IZipFileContentProvider).GetSource(), EntryName, FA_READ);
//return g_stream;
}
}
+26
View File
@@ -0,0 +1,26 @@
#ifndef IPAKFILE_H__
#define IPAKFILE_H__
//#include "IDataStream.h"
#include "../../LString.h"
#include "../IFile.h"
#include "IPakStream.h"
namespace LifeCore
{
class IPakFile : public IFile
{
public:
IPakFile();
~IPakFile(){}
String EntryName;
IDataStreamPtr OpenWrite(int mode);
IDataStreamPtr OpenReadWrite(int mode);
IDataStreamPtr OpenRead();
private:
int offsetIndex;
IPakStream* g_stream;
};
}
#endif
@@ -0,0 +1,76 @@
#include "IPakFileContentProvider.h"
namespace LifeCore
{
static const String pakPathSplitter(_text("/"));
IPakFileContentProvider::IPakFileContentProvider(IDataStream* pakFile, const String& name)
{
IPakFolder* folder = new IPakFolder();
// g_rootFolder = pakFile;
folder->Provider = this;
folder->Name = name;
folder->EntryName = _text("");
fileSystem = new IFileSystem(folder);
g_sourceFile.Open(pakFile);
fileSystem->GetRootFolder();
BuildTree();
}
void IPakFileContentProvider::BuildTree()
{
//g_sourceFile.LocateEntry(0);
int numFiles = g_sourceFile.filesCount();
for (int i = 0; i < numFiles; i++)
{
//g_sourceFile.LocateEntry(i);
entry_info info = g_sourceFile.GetEntryInfo(i);
String p = GetPakPathWithoutFilename(info.fileName);
IPakFolder* folder;
if(this->fileSystem->GetFolder(p, (IFolder**)&folder) != SC_OK)
{
printf("Failed to get folder! IPakFileContentProvider::BuildTree\n");
return;
}
IPakFile* file = new IPakFile();
file->FileName = GetFileName(info.fileName, pakPathSplitter);
file->Provider = this;
file->Size = info.fileSize;
file->EntryName = info.fileName;
folder->AddFile(file);
//g_sourceFile.CloseCurrentEntry();
}
//print folder tree
String tab(_text("\t"));
int cnt = fileSystem->GetRootFolder()->folderCount;
for(int i = 0; i < cnt; i++)
{
IFolder* fld = fileSystem->GetRootFolder()->GetFolder(i);
PRINT(_text("%s\n"), fld->Name.c_str());
PRINT(_text("Files count: %i\n"), fld->fileCount);
}
}
String IPakFileContentProvider::GetPakPathWithoutFilename(const String& path)
{
int offset = path.find_last_of(_text("/"));
if(offset>=0)
{
return path.substr(0, offset);
}
else
{
return _text("/");
}
}
}
@@ -0,0 +1,28 @@
#ifndef IPAKFILECONTENTPROVIDER_H__
#define IPAKFILECONTENTPROVIDER_H__
#include "../IContentProvider.h"
#include "../../LString.h"
#include "../IFileSystem.h"
#include "pak_io/PakFile.h"
#include "IPakFolder.h"
namespace LifeCore
{
class IPakFileContentProvider : public IContentProvider
{
public:
~IPakFileContentProvider(){};
void Close(){}
IFileSystem* getFileSystem(){return fileSystem;}
IPakFileContentProvider(IDataStream* pakFile, const String& name);
String g_rootFolder;
PakFile g_sourceFile;
IFileSystem* fileSystem;
private:
void BuildTree();
String GetPakPathWithoutFilename(const String& path);
};
}
#endif
+31
View File
@@ -0,0 +1,31 @@
#include "IPakFolder.h"
namespace LifeCore
{
IPakFolder::~IPakFolder(void)
{
for( FolderMap::iterator it = g_folderCollection.begin(); it != g_folderCollection.end(); it++ )
delete it->second;
}
IFolder* IPakFolder::NewFolder(const String& name)
{
IPakFolder* newFolder = new IPakFolder();
newFolder->Name = name;
newFolder->setParent(this);
newFolder->EntryName = this->EntryName + name + _text("/");
newFolder->Provider = this->Provider;
this->AddFolder(newFolder);
return newFolder;
}
IFile* IPakFolder::NewFile(const String& name, int size)
{
UNREFERENCED_PARAMETER(size);
IFile* newFile = new IPakFile();
newFile->FileName = name;
newFile->Provider = this->Provider;
IPakFile* xf = (IPakFile*)newFile;
xf->EntryName = this->EntryName + name;
this->AddFile(newFile);
return newFile;
}
}
+24
View File
@@ -0,0 +1,24 @@
#ifndef IPAKFOLDER_H__
#define IPAKFOLDER_H__
#include "../../IDataStream.h"
#include "../../LString.h"
#include "../IFolder.h"
#include "IPakFile.h"
#include "../IContentProvider.h"
#include <map>
namespace LifeCore
{
class IPakFolder : public IFolder
{
public:
~IPakFolder(void);
IContentProvider* Provider;
String EntryName;
IFolder* NewFolder(const String& name);
IFile* NewFile(const String& name, int size);
};
}
#endif
+77
View File
@@ -0,0 +1,77 @@
#ifndef IPAKSTREAM_H__
#define IPAKSTREAM_H__
#include "../../IDataStream.h"
#include "../../LString.h"
#include <assert.h>
#include "pak_io/PakFile.h"
namespace LifeCore
{
class IPakStream : public IDataStream
{
private:
PakFile* source;
entry_info info;
int openMode;
size_t stmLength;
PakEntryHandle entry;
public:
~IPakStream(){}
void Close()
{
source->fclose(entry);
openMode = 0;
}
IPakStream(PakFile* file, String& entryName, int fileAccessMode)
{
source = file;
openMode = fileAccessMode;
// source->CloseCurrentEntry();
if (fileAccessMode == FA_READ)
{
entry = source->fopen(entryName);
// source->LocateEntry(entry);
//info = source->GetEntryInfo();
stmLength = source->fget_size(entry);
//source->OpenCurrentEntry();
}
else
{
throw "Creation of new PAK entry is not implemented! IPakStream.h";
//source->NewFileEntry(entry);
}
}
size_t Read(void* pBuffer, size_t countBytes)
{
return source->fread(entry, pBuffer, countBytes);
}
size_t Write(const void* pBuffer, size_t countBytes)
{
source->fwrite(entry, pBuffer, countBytes);
return countBytes;
}
void Seek(size_t position)
{
source->fseek(entry, position);
}
size_t Tell()
{
return source->ftell(entry);
}
size_t Length()
{
return source->fget_size(entry);
}
bool CanRead()
{
return true;
}
bool CanWrite()
{
return true;
}
};
}
#endif
+13
View File
@@ -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
+11
View File
@@ -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;
+6
View File
@@ -0,0 +1,6 @@
#define MAX_ENTRY_NAME_LENGTH 0x100
typedef struct FolderEntry
{
wchar_t name[MAX_ENTRY_NAME_LENGTH];
}FolderEntry;
+312
View File
@@ -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;
}
}
+80
View File
@@ -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
+16
View File
@@ -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
+12
View File
@@ -0,0 +1,12 @@
#include <vector>
typedef struct PakHeader
{
int version;
int whiteSpacesCount;
int filesCount;
int foldersCount;
int extraDataOffset;
int lastFolderId;
int dataChunkLength;
} PakHeader;
+12
View File
@@ -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