Files
Coleman-Code/COM380/Project5/GambleKit/Engine/OSSpecific/GkFileSystem.cpp
T
Amrit Panesar 39ee821f54 start 380 project5
changes to 380 project 4
changes to 350 project 2

Signed-off-by: Amrit Panesar <apanesar@4195tech.com>
2015-05-06 10:18:39 -07:00

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();
}