/******************************************************************************
@File PVRTResourceFile.cpp
@Title PVRTResourceFile.cpp
@Version
@Copyright Copyright (c) Imagination Technologies Limited.
@Platform ANSI compatible
@Description Simple resource file wrapper
******************************************************************************/
#include "PVRTResourceFile.h"
#include <stdio.h>
#include <string.h>
#include "PVRTResourceFile.h"
#include "PVRTString.h"
#include "PVRTMemoryFileSystem.h"
CPVRTString CPVRTResourceFile::s_ReadPath;
static void* LoadFileFunc(const char* pFilename, char** pData, size_t &size)
{
size = 0;
FILE* pFile = fopen(pFilename, "rb");
if (pFile)
{
// Get the file size
fseek(pFile, 0, SEEK_END);
size = ftell(pFile);
fseek(pFile, 0, SEEK_SET);
// read the data
char* pTmp = new char[size];
size_t BytesRead = fread(pTmp, 1, size, pFile);
if (BytesRead != size)
{
delete [] pTmp;
pTmp = NULL;
size = 0;
}
else
*pData = pTmp;
fclose(pFile);
return pTmp;
}
return 0;
}
static bool ReleaseFileFunc(void* handle)
{
if(handle)
{
delete[] (char*) handle;
return true;
}
return false;
}
PFNLoadFileFunc CPVRTResourceFile::s_pLoadFileFunc = &LoadFileFunc;
PFNReleaseFileFunc CPVRTResourceFile::s_pReleaseFileFunc = &ReleaseFileFunc;
/*!***************************************************************************
@Function SetReadPath
@Input pszReadPath The path where you would like to read from
@Description Sets the read path
*****************************************************************************/
void CPVRTResourceFile::SetReadPath(const char* const pszReadPath)
{
s_ReadPath = (pszReadPath) ? pszReadPath : "";
}
/*!***************************************************************************
@Function GetReadPath
@Returns The currently set read path
@Description Returns the currently set read path
*****************************************************************************/
CPVRTString CPVRTResourceFile::GetReadPath()
{
return CPVRTString(s_ReadPath);
}
/*!***************************************************************************
@Function SetLoadReleaseFunctions
@Input pLoadFileFunc Function to use for opening a file
@Input pReleaseFileFunc Function to release any data allocated by the load function
@Description This function is used to override the CPVRTResource file loading functions. If
you pass NULL in as the load function CPVRTResource will use the default functions.
*****************************************************************************/
void CPVRTResourceFile::SetLoadReleaseFunctions(void* pLoadFileFunc, void* pReleaseFileFunc)
{
if(pLoadFileFunc)
{
s_pLoadFileFunc = (PFNLoadFileFunc) pLoadFileFunc;
s_pReleaseFileFunc = (PFNReleaseFileFunc) pReleaseFileFunc;
}
else
{
s_pLoadFileFunc = &LoadFileFunc;
s_pReleaseFileFunc = &ReleaseFileFunc;
}
}
/*!***************************************************************************
@Function CPVRTResourceFile
@Input pszFilename Name of the file you would like to open
@Description Constructor
*****************************************************************************/
CPVRTResourceFile::CPVRTResourceFile(const char* const pszFilename) :
m_bOpen(false),
m_bMemoryFile(false),
m_Size(0),
m_pData(0),
m_Handle(0)
{
CPVRTString Path(s_ReadPath);
Path += pszFilename;
m_Handle = s_pLoadFileFunc(Path.c_str(), (char**) &m_pData, m_Size);
m_bOpen = (m_pData && m_Size) != 0;
if (!m_bOpen)
{
m_bOpen = m_bMemoryFile = CPVRTMemoryFileSystem::GetFile(pszFilename, (const void**)(&m_pData), &m_Size);
}
}
/*!***************************************************************************
@Function CPVRTResourceFile
@Input pData A pointer to the data you would like to use
@Input i32Size The size of the data
@Description Constructor
*****************************************************************************/
CPVRTResourceFile::CPVRTResourceFile(const char* pData, size_t i32Size) :
m_bOpen(true),
m_bMemoryFile(true),
m_Size(i32Size),
m_pData(pData),
m_Handle(0)
{
}
/*!***************************************************************************
@Function ~CPVRTResourceFile
@Description Destructor
*****************************************************************************/
CPVRTResourceFile::~CPVRTResourceFile()
{
Close();
}
/*!***************************************************************************
@Function IsOpen
@Returns true if the file is open
@Description Is the file open
*****************************************************************************/
bool CPVRTResourceFile::IsOpen() const
{
return m_bOpen;
}
/*!***************************************************************************
@Function IsMemoryFile
@Returns true if the file was opened from memory
@Description Was the file opened from memory
*****************************************************************************/
bool CPVRTResourceFile::IsMemoryFile() const
{
return m_bMemoryFile;
}
/*!***************************************************************************
@Function Size
@Returns The size of the opened file
@Description Returns the size of the opened file
*****************************************************************************/
size_t CPVRTResourceFile::Size() const
{
return m_Size;
}
/*!***************************************************************************
@Function DataPtr
@Returns A pointer to the file data
@Description Returns a pointer to the file data
*****************************************************************************/
const void* CPVRTResourceFile::DataPtr() const
{
return m_pData;
}
/*!***************************************************************************
@Function Close
@Description Closes the file
*****************************************************************************/
void CPVRTResourceFile::Close()
{
if (m_bOpen)
{
if (!m_bMemoryFile && s_pReleaseFileFunc)
{
s_pReleaseFileFunc(m_Handle);
}
m_bMemoryFile = false;
m_bOpen = false;
m_pData = 0;
m_Size = 0;
}
}
/****************************************************************************
** class CPVRTMemoryFileSystem
****************************************************************************/
CPVRTMemoryFileSystem::CAtExit CPVRTMemoryFileSystem::s_AtExit;
CPVRTMemoryFileSystem::SFileInfo* CPVRTMemoryFileSystem::s_pFileInfo = 0;
int CPVRTMemoryFileSystem::s_i32Capacity = 0;
int CPVRTMemoryFileSystem::s_i32NumFiles = 0;
/*!***************************************************************************
@Function Destructor
@Description Destructor of CAtExit class. Workaround for platforms that
don't support the atexit() function. This deletes any memory
file system data.
*****************************************************************************/
CPVRTMemoryFileSystem::CAtExit::~CAtExit()
{
for (int i = 0; i < CPVRTMemoryFileSystem::s_i32NumFiles; ++i)
{
if (CPVRTMemoryFileSystem::s_pFileInfo[i].bAllocated)
{
delete [] (char*)CPVRTMemoryFileSystem::s_pFileInfo[i].pszFilename;
delete [] (char*)CPVRTMemoryFileSystem::s_pFileInfo[i].pBuffer;
}
}
delete [] CPVRTMemoryFileSystem::s_pFileInfo;
}
CPVRTMemoryFileSystem::CPVRTMemoryFileSystem(const char* pszFilename, const void* pBuffer, size_t Size, bool bCopy)
{
RegisterMemoryFile(pszFilename, pBuffer, Size, bCopy);
}
/*!***************************************************************************
@Function RegisterMemoryFile
@Input pszFilename Name of file to register
@Input pBuffer Pointer to file data
@Input Size File size
@Input bCopy Name and data should be copied?
@Description Registers a block of memory as a file that can be looked up
by name.
*****************************************************************************/
void CPVRTMemoryFileSystem::RegisterMemoryFile(const char* pszFilename, const void* pBuffer, size_t Size, bool bCopy)
{
if (s_i32NumFiles == s_i32Capacity)
{
SFileInfo* pFileInfo = new SFileInfo[s_i32Capacity + 10];
memcpy(pFileInfo, s_pFileInfo, sizeof(SFileInfo) * s_i32Capacity);
delete [] s_pFileInfo;
s_pFileInfo = pFileInfo;
s_i32Capacity += 10;
}
s_pFileInfo[s_i32NumFiles].pszFilename = pszFilename;
s_pFileInfo[s_i32NumFiles].pBuffer = pBuffer;
if (bCopy)
{
char* pszNewFilename = new char[strlen(pszFilename) + 1];
strcpy(pszNewFilename, pszFilename);
s_pFileInfo[s_i32NumFiles].pszFilename = pszNewFilename;
void* pszNewBuffer = new char[Size];
memcpy(pszNewBuffer, pBuffer, Size);
s_pFileInfo[s_i32NumFiles].pBuffer = pszNewBuffer;
}
s_pFileInfo[s_i32NumFiles].Size = Size;
s_pFileInfo[s_i32NumFiles].bAllocated = bCopy;
++s_i32NumFiles;
}
/*!***************************************************************************
@Function GetFile
@Input pszFilename Name of file to open
@Output ppBuffer Pointer to file data
@Output pSize File size
@Return true if the file was found in memory, false otherwise
@Description Looks up a file in the memory file system by name. Returns a
pointer to the file data as well as its size on success.
*****************************************************************************/
bool CPVRTMemoryFileSystem::GetFile(const char* pszFilename, const void** ppBuffer, size_t* pSize)
{
for (int i = 0; i < s_i32NumFiles; ++i)
{
if (strcmp(s_pFileInfo[i].pszFilename, pszFilename) == 0)
{
if (ppBuffer) *ppBuffer = s_pFileInfo[i].pBuffer;
if (pSize) *pSize = s_pFileInfo[i].Size;
return true;
}
}
return false;
}
/*!***************************************************************************
@Function GetNumFiles
@Return The number of registered files
@Description Getter for the number of registered files
*****************************************************************************/
int CPVRTMemoryFileSystem::GetNumFiles()
{
return s_i32NumFiles;
}
/*!***************************************************************************
@Function GetFilename
@Input i32Index Index of file
@Return A pointer to the filename of the requested file
@Description Looks up a file in the memory file system by name. Returns a
pointer to the file data as well as its size on success.
*****************************************************************************/
const char* CPVRTMemoryFileSystem::GetFilename(int i32Index)
{
if (i32Index < 0 || i32Index > s_i32NumFiles) return 0;
return s_pFileInfo[i32Index].pszFilename;
}
/*****************************************************************************
End of file (PVRTResourceFile.cpp)
*****************************************************************************/