#include "PakFile.h" #include #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; } }