changes to 380 project 4 changes to 350 project 2 Signed-off-by: Amrit Panesar <apanesar@4195tech.com>
285 lines
7.1 KiB
C++
285 lines
7.1 KiB
C++
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
// GambleKit Copyright (C) 2014 Ivan Donev
|
|
//
|
|
// This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
|
|
//
|
|
// This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
//
|
|
// contact: gamblekit@gmail.com
|
|
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
#include "GkFileSystem.h"
|
|
|
|
#include <Windows.h>
|
|
#include <vector>
|
|
#include <string>
|
|
#include "..\Utils\GkStrings.h"
|
|
|
|
std::wstring GkFileSystem::source;
|
|
//wchar_t *GkFileSystem::source;
|
|
FileSystemMode GkFileSystem::mode;
|
|
GkFileSystem::Init GkFileSystem::init;
|
|
|
|
GkFileSystem::Init::Init(void)
|
|
{
|
|
//GkFileSystem::source = GkStrings::Copy(L"\0");
|
|
}
|
|
|
|
GkFileSystem::Init::~Init(void)
|
|
{
|
|
//delete[] GkFileSystem::source;
|
|
}
|
|
|
|
GkFileSystem::GkFileSystem(void)
|
|
{
|
|
}
|
|
|
|
|
|
GkFileSystem::~GkFileSystem(void)
|
|
{
|
|
}
|
|
|
|
|
|
void GkFileSystem::SetSource(const wchar_t *source, FileSystemMode mode)
|
|
{
|
|
//delete[] GkFileSystem::source;
|
|
|
|
//if (source == 0)
|
|
// GkFileSystem::source = GkStrings::Copy(L"\0");
|
|
//else
|
|
// GkFileSystem::source = GkStrings::Copy(source);
|
|
|
|
if (source == 0)
|
|
GkFileSystem::source = std::wstring(L"\0");
|
|
else
|
|
GkFileSystem::source = std::wstring(source);
|
|
|
|
|
|
|
|
GkFileSystem::mode = mode;
|
|
}
|
|
|
|
bool GkFileSystem::LoadFile(const wchar_t *fileName, void **fileData, unsigned int *fileSize)
|
|
{
|
|
if (GkFileSystem::mode == FileSystemMode_Physical)
|
|
return GkFileSystem::LoadPhysicalFile(fileName, fileData, fileSize);
|
|
|
|
if (GkFileSystem::mode == FileSystemMode_Virtual)
|
|
return GkFileSystem::LoadVirtualFile(fileName, fileData, fileSize);
|
|
|
|
return false;
|
|
}
|
|
|
|
void GkFileSystem::CreateVirtualFileSystem(const wchar_t* directory, const wchar_t* fileName)
|
|
{
|
|
std::ofstream fileStream(fileName, std::ios::out | std::ios::binary);
|
|
|
|
GkFileSystem::WriteVirtualFileSystem(directory, &fileStream);
|
|
|
|
fileStream.close();
|
|
}
|
|
|
|
bool GkFileSystem::LoadVirtualFile(const wchar_t *fileName, void **fileData, unsigned int *fileSize)
|
|
{
|
|
std::vector<wchar_t*> pathElements;
|
|
|
|
int elementStart = 0;
|
|
int i = 0;
|
|
bool done;
|
|
do
|
|
{
|
|
done = *((char*)&fileName[i]) == 0;
|
|
|
|
if ((fileName[i] == L'\\') || done)
|
|
{
|
|
int l = i - elementStart;
|
|
wchar_t *element = new wchar_t[l + 1];
|
|
CopyMemory(element, &fileName[elementStart], l * sizeof(wchar_t));
|
|
element[l] = 0;
|
|
pathElements.push_back(element);
|
|
elementStart = i + 1;
|
|
}
|
|
|
|
i++;
|
|
} while (!done);
|
|
|
|
|
|
std::ifstream file(GkFileSystem::source, std::ios::in | std::ios::binary | std::ios::ate);
|
|
int pathElementIndex = 0;
|
|
|
|
int dirLimit = (int)file.tellg();
|
|
file.seekg(0);
|
|
|
|
done = false;
|
|
while (file && !done)
|
|
{
|
|
wchar_t *vfn = GkFileSystem::ReadString(&file);
|
|
int size;
|
|
file.read((char*)&size, sizeof(int));
|
|
|
|
if (wcscmp(vfn, pathElements[pathElementIndex]) == 0)
|
|
{
|
|
pathElementIndex++;
|
|
dirLimit = (int)file.tellg() + size;
|
|
|
|
if (pathElementIndex == pathElements.size())
|
|
{
|
|
*fileSize = size;
|
|
*fileData = new char[size];
|
|
file.read((char*)*fileData, size);
|
|
|
|
done = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
file.seekg((int)file.tellg() + size);
|
|
}
|
|
|
|
delete vfn;
|
|
|
|
if (file.tellg() >= dirLimit)
|
|
break;
|
|
}
|
|
|
|
file.close();
|
|
|
|
|
|
for (int i = 0; i < (int)pathElements.size(); i++)
|
|
{
|
|
delete pathElements[i];
|
|
}
|
|
|
|
return done;
|
|
}
|
|
|
|
bool GkFileSystem::LoadPhysicalFile(const wchar_t *fileName, void **fileData, unsigned int *fileSize)
|
|
{
|
|
// TODO: fix this static string
|
|
std::wstring fn(GkFileSystem::source);
|
|
fn.append(fileName);
|
|
|
|
std::ifstream file(fn.c_str(), std::ios::in | std::ios::binary | std::ios::ate);
|
|
|
|
if (!file)
|
|
return false;
|
|
|
|
*fileSize = (unsigned int)file.tellg();
|
|
*fileData = new char[*fileSize];
|
|
|
|
file.seekg(0);
|
|
file.read((char*)*fileData, *fileSize);
|
|
|
|
file.close();
|
|
|
|
return true;
|
|
}
|
|
|
|
wchar_t* GkFileSystem::ReadString(std::ifstream* fileStream)
|
|
{
|
|
int l;
|
|
fileStream->read((char*)&l, sizeof(int));
|
|
|
|
wchar_t *result = new wchar_t[l + 1];
|
|
fileStream->read((char*)result, l * sizeof(wchar_t));
|
|
result[l] = 0;
|
|
|
|
return result;
|
|
}
|
|
|
|
void GkFileSystem::WriteVirtualFileSystem(const wchar_t* directory, std::ofstream* fileStream)
|
|
{
|
|
std::wstring fullSearchDir(directory);
|
|
fullSearchDir.append(L"\\*");
|
|
|
|
WIN32_FIND_DATAW findData;
|
|
|
|
HANDLE findHandle = INVALID_HANDLE_VALUE;
|
|
findHandle = FindFirstFileW(fullSearchDir.c_str(), &findData);
|
|
|
|
if (findHandle == INVALID_HANDLE_VALUE)
|
|
{
|
|
return;
|
|
}
|
|
|
|
int chunkSize, chunkSizePos;
|
|
do
|
|
{
|
|
if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
|
{
|
|
if ((wcscmp(findData.cFileName, L".") != 0) && (wcscmp(findData.cFileName, L"..") != 0))
|
|
{
|
|
std::wstring fullSearchSubDir(directory);
|
|
fullSearchSubDir.append(L"\\");
|
|
fullSearchSubDir.append(findData.cFileName);
|
|
|
|
GkFileSystem::WriteString(findData.cFileName, fileStream);
|
|
|
|
chunkSizePos = (int)fileStream->tellp();
|
|
fileStream->write((char*)&chunkSize, sizeof(int));
|
|
|
|
GkFileSystem::WriteVirtualFileSystem(fullSearchSubDir.c_str(), fileStream);
|
|
|
|
int endPos = (int)fileStream->tellp();
|
|
chunkSize = endPos - chunkSizePos - 4;
|
|
fileStream->seekp(chunkSizePos);
|
|
fileStream->write((char*)&chunkSize, sizeof(int));
|
|
fileStream->seekp(endPos);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
std::wstring fullFileName(directory);
|
|
fullFileName.append(L"\\");
|
|
fullFileName.append(findData.cFileName);
|
|
|
|
GkFileSystem::WriteString(findData.cFileName, fileStream);
|
|
|
|
chunkSizePos = (int)fileStream->tellp();
|
|
fileStream->write((char*)&chunkSize, sizeof(int));
|
|
|
|
GkFileSystem::WriteFile(fullFileName.c_str(), fileStream);
|
|
|
|
int endPos = (int)fileStream->tellp();
|
|
chunkSize = endPos - chunkSizePos - 4;
|
|
fileStream->seekp(chunkSizePos);
|
|
fileStream->write((char*)&chunkSize, sizeof(int));
|
|
fileStream->seekp(endPos);
|
|
}
|
|
|
|
}
|
|
while (FindNextFileW(findHandle, &findData) != 0);
|
|
|
|
FindClose(findHandle);
|
|
}
|
|
|
|
void GkFileSystem::WriteString(const wchar_t* s, std::ofstream* fileStream)
|
|
{
|
|
int l = 0;
|
|
while (s[l] != 0)
|
|
l++;
|
|
|
|
fileStream->write((char*)&l, sizeof(int));
|
|
fileStream->write((char*)s, l * sizeof(wchar_t));
|
|
}
|
|
|
|
void GkFileSystem::WriteFile(const wchar_t* fileName, std::ofstream* fileStream)
|
|
{
|
|
std::ifstream file(fileName, std::ios::in | std::ios::binary);
|
|
|
|
const int bufferSize = 2048;
|
|
char buffer[bufferSize];
|
|
|
|
for (;;)
|
|
{
|
|
file.read(buffer, bufferSize);
|
|
fileStream->write(buffer, file.gcount());
|
|
|
|
if (!file)
|
|
break;
|
|
}
|
|
|
|
file.close();
|
|
} |