*** Merged Code from Multiplayer Branch Revision 2960 ***

- Virtual File System (VFS) by birdflu. This is needed for Multiplayer and is also used for Single Player. Very neat system :-)
- Multiplayer Version 1.1 + some additional features and bugfixes
* INFO: If you compile a new EXE and want to test, be sure to also use the latest SVN GameDir files in your JA2 install directory *




git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@2961 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
Wanne
2009-06-04 21:01:45 +00:00
parent 17f44f63e8
commit 47db604b50
301 changed files with 76701 additions and 1843 deletions
+215
View File
@@ -0,0 +1,215 @@
#include "vfs_7z_library.h"
#include "vfs_lib_dir.h"
#include "../File/vfs_lib_file.h"
#include "../vfs_file_raii.h"
namespace sz
{
extern "C"
{
#include "7zCrc.h"
#include "Archive/7z/7zAlloc.h"
#include "Archive/7z/7zExtract.h"
#include "Archive/7z/7zIn.h"
}
}
/********************************************************************************************/
/*** my 7z extensions ***/
/********************************************************************************************/
namespace szExt
{
typedef struct CSzVfsFile
{
vfs::tReadableFile* file;
} CSzVfsFile;
typedef struct CVfsFileInStream
{
sz::ISeekInStream s;
CSzVfsFile file;
} CVfsFileInStream;
static sz::SRes VfsFileInStream_Read(void *pp, void *buf, size_t *size)
{
CVfsFileInStream *p = (CVfsFileInStream *)pp;
vfs::UInt32 to_read = *size;
vfs::UInt32 has_read = 0;
sz::SRes res;
if(p->file.file->Read((vfs::Byte*)buf,to_read, has_read))
{
res = SZ_OK;
}
else
{
res = SZ_ERROR_READ;
}
*size = has_read;
return res;
}
static sz::SRes VfsFileInStream_Seek(void *pp, sz::Int64 *pos, sz::ESzSeek origin)
{
CVfsFileInStream *p = (CVfsFileInStream *)pp;
vfs::IBaseFile::ESeekDir eSD;
switch (origin)
{
case sz::SZ_SEEK_SET:
eSD = vfs::IBaseFile::SD_BEGIN;
break;
case sz::SZ_SEEK_CUR:
eSD = vfs::IBaseFile::SD_CURRENT;
break;
case sz::SZ_SEEK_END:
eSD = vfs::IBaseFile::SD_END;
break;
default:
return ERROR_INVALID_PARAMETER;
}
vfs::Int32 _pos = (vfs::Int32)(*pos); // only 32 bit
sz::SRes res;
if(p->file.file->SetReadLocation(_pos,eSD))
{
*pos = p->file.file->GetReadLocation();
res = SZ_OK;
}
else
{
res = SZ_ERROR_READ;
}
return res;
}
void VfsFileInStream_CreateVTable(CVfsFileInStream *p)
{
p->s.Read = VfsFileInStream_Read;
p->s.Seek = VfsFileInStream_Seek;
}
}; // end namespace szExt
/********************************************************************************************/
/********************************************************************************************/
/********************************************************************************************/
#define k_Copy 0
sz::UInt64 GetSum(const sz::UInt64 *values, sz::UInt32 index)
{
sz::UInt64 sum = 0;
sz::UInt32 i;
for (i = 0; i < index; i++)
{
sum += values[i];
}
return sum;
}
bool vfs::CUncompressed7zLibrary::Init()
{
if(!m_pLibraryFile)
{
return false;
}
szExt::CVfsFileInStream archiveStream;
sz::CLookToRead lookStream;
sz::CSzArEx db;
sz::SRes res;
sz::ISzAlloc allocImp;
sz::ISzAlloc allocTempImp;
if(!m_pLibraryFile->OpenRead())
{
return false;
}
archiveStream.file.file = m_pLibraryFile;
szExt::VfsFileInStream_CreateVTable(&archiveStream);
sz::LookToRead_CreateVTable(&lookStream, False);
lookStream.realStream = &archiveStream.s;
sz::LookToRead_Init(&lookStream);
allocImp.Alloc = sz::SzAlloc;
allocImp.Free = sz::SzFree;
allocTempImp.Alloc = sz::SzAllocTemp;
allocTempImp.Free = sz::SzFreeTemp;
sz::CrcGenerateTable();
sz::SzArEx_Init(&db);
if( SZ_OK != (res = sz::SzArEx_Open(&db, &lookStream.s, &allocImp, &allocTempImp)) )
{
std::stringstream wss;
wss << "Could not open 7z archive [" << m_pLibraryFile->GetFullPath()().utf8() << "]";
THROWEXCEPTION(wss.str().c_str());
}
vfs::IDirectory<ILibrary::tWriteType>* pLD = NULL;
vfs::Path oDir, oFile;
vfs::Path oDirPath;
for(vfs::UInt32 i = 0; i < db.db.NumFiles; i++)
{
sz::CSzFileItem *f = db.db.Files + i;
if (f->IsDir)
{
continue;
}
vfs::Path sPath(f->Name);
sPath.SplitLast(oDir,oFile);
oDirPath = m_sMountPoint;
if(!oDir.empty())
{
oDirPath += oDir;
}
// determine offset and size
sz::UInt32 folderIndex = db.FileIndexToFolderIndexMap[i];
sz::CSzFolder *folder = db.db.Folders + folderIndex;
sz::UInt64 unpackSizeSpec = sz::SzFolder_GetUnpackSize(folder);
size_t unpackSize = (size_t)unpackSizeSpec;
sz::UInt64 startOffset = sz::SzArEx_GetFolderStreamPos(&db, folderIndex, 0);
const sz::UInt64 *packSizes = db.db.PackSizes + db.FolderStartPackStreamIndex[folderIndex];
//CSzCoderInfo *coder = &folder->Coders[0];
//if (coder->MethodID == k_Copy)
//{
// UInt32 si = 0;
// UInt64 offset;
// UInt64 inSize;
// offset = GetSum(packSizes, si);
// inSize = packSizes[si];
//}
// get or create according directory object
tDirCatalogue::iterator it = m_catDirs.find(oDirPath);
if(it != m_catDirs.end())
{
pLD = it->second;
}
else
{
pLD = new CLibDirectory(oDir,oDirPath);
m_catDirs.insert(std::make_pair(oDirPath,pLD));
}
// create file
vfs::CLibFile *pFile = vfs::CLibFile::Create(oFile,pLD,this,_allocator);
// add file to directory
if(!pLD->AddFile(pFile))
{
// something is wrong
m_pLibraryFile->Close();
return false;
}
// link file data struct to file object
m_mapLibData.insert(std::pair<tFileType*,sFileData>(pFile,sFileData(unpackSize, (UInt32)startOffset)));
}
return true;
}
+30
View File
@@ -0,0 +1,30 @@
#ifndef _VFS_7Z_LIBRARY_H_
#define _VFS_7Z_LIBRARY_H_
#include "vfs_uncompressed_lib_base.h"
#include "File/vfs_lib_file.h"
namespace vfs
{
class CUncompressed7zLibrary : public vfs::CUncompressedLibraryBase
{
public:
CUncompressed7zLibrary(tReadableFile *pLibraryFile,
vfs::Path const& sMountPoint,
bool bOwnFile = false,
ObjBlockAllocator<vfs::CLibFile>* allocator=NULL)
: vfs::CUncompressedLibraryBase(pLibraryFile,sMountPoint,bOwnFile), _allocator(allocator)
{};
virtual ~CUncompressed7zLibrary()
{};
/**
* ILibrary interface
*/
virtual bool Init();
private:
ObjBlockAllocator<vfs::CLibFile>* _allocator;
};
} // end namespace
#endif // _VFS_7Z_LIBRARY_H_
+402
View File
@@ -0,0 +1,402 @@
//#define VFS_BASIC_TYPES
#include "../vfs_types.h"
#include "vfs_create_7z_library.h"
#include "../vfs_file_raii.h"
#include "../vfs_debug.h"
namespace sz
{
extern "C"
{
#include "7zCrc.h"
#include "Archive/7z/7zIn.h"
}
};
#include <vector>
#include <sstream>
/******************************************************************************************/
/******************************************************************************************/
/******************************************************************************************/
namespace szExt
{
inline vfs::UInt32 WRITEBYTE(std::ostream& out, sz::Byte const& value)
{
out.write((char*)&value,sizeof(sz::Byte));
return 1;
}
template<typename T>
inline vfs::UInt32 WRITEALL(std::ostream& out, T const& value)
{
out.write((char*)&value,sizeof(T));
return sizeof(T);
}
template<typename T>
inline vfs::UInt32 WRITEBUFFER(std::ostream& out, T* value, size_t num_elements)
{
out.write((char*)value,sizeof(T) * num_elements);
return num_elements*sizeof(T);
}
/**
* "compress" numbers by removing heading zero-bytes
* - add additional byte that represents a bit-vector of bytes within a 64-bit/8-byte number
* - if the number is smaller than 128, use the extra byte to store the value
*/
template<typename T>
inline vfs::UInt32 WRITE(std::ostream& out, T const& value)
{
vfs::UInt32 count = 0;
sz::Byte data[8];
sz::Byte firstByte = 0;
sz::Byte* b = (sz::Byte*)&value;
size_t SIZE = sizeof(T);
b+= SIZE-1;
vfs::Int32 i;
for(i=SIZE-1; i>=0; --i)
{
if( (*b & 0xFF) != 0)
{
break;
}
b--;
}
if(i < 0)
{
count += WRITEBYTE(out,0);
return count;
}
if(i == 0)
{
if(*b >= 0x80)
{
count += WRITEBYTE(out,0x80);
}
count += WRITEBYTE(out,*b);
return count;
}
vfs::Int32 num = 0;
for(;i >= 0; --i)
{
firstByte |= 1 << (8 - i - 1);
data[i] = *b--;
num++;
}
count += WRITEBYTE(out,firstByte);
count += WRITEBUFFER(out,data,num);
return count;
}
}
/******************************************************************************************/
/******************************************************************************************/
/******************************************************************************************/
vfs::CCreateUncompressed7zLibrary::CCreateUncompressed7zLibrary()
: m_pLibFile(NULL)
{
sz::CrcGenerateTable();
}
vfs::CCreateUncompressed7zLibrary::~CCreateUncompressed7zLibrary()
{
m_pLibFile = NULL;
m_lFileInfo.clear();
m_mapDirInfo.clear();
}
bool vfs::CCreateUncompressed7zLibrary::AddFile(vfs::tReadableFile* pFile)
{
if(!pFile)
{
// at least nothing bad happened
return true;
}
try
{
vfs::COpenReadFile infile(pFile);
}
catch(CBasicException &ex)
{
std::wstringstream wss;
wss << L"Could not open File \"" << pFile->GetFullPath()() << L"\"";
RETHROWEXCEPTION(wss.str().c_str(),&ex);
}
SFileInfo fi;
vfs::Path filename = pFile->GetFullPath();
fi.name = filename().c_wcs();
fi.size = pFile->GetFileSize();
if(m_lFileInfo.empty())
{
fi.offset = 0;
}
else
{
SFileInfo const& fic = m_lFileInfo.back();
fi.offset = fic.offset + fic.size;
}
std::vector<vfs::Byte> data(fi.size);
UInt32 ui_read;
pFile->Read(&data[0], fi.size, ui_read);
fi.CRC = sz::CrcCalc(&data[0],fi.size);
m_ssFileStream.write(&data[0],fi.size);
m_lFileInfo.push_back(fi);
vfs::Path path,dummy;
filename.SplitLast(path,dummy);
if(!path.empty())
{
tDirInfo::iterator it_find = m_mapDirInfo.find(path().c_wcs());
if(it_find == m_mapDirInfo.end())
{
SFileInfo dir;
dir.name = path().c_wcs();
dir.offset = 0;
dir.size = 0;
dir.time_creation = 0;
dir.time_last_access = 0;
dir.time_write = 0;
m_mapDirInfo.insert(std::make_pair(dir.name,dir));
}
}
return true;
}
bool vfs::CCreateUncompressed7zLibrary::WriteLibrary(vfs::Path const& sLibName)
{
vfs::COpenWriteFile outfile(sLibName,true);
return WriteLibrary(&outfile.file());
}
bool vfs::CCreateUncompressed7zLibrary::WriteLibrary(vfs::tWriteableFile* pFile)
{
if(!pFile)
{
return false;
}
if(m_lFileInfo.empty())
{
return false;
}
m_pLibFile = pFile;
if(!m_pLibFile->IsOpenWrite() && !m_pLibFile->OpenWrite(true,true))
{
return false;
}
//
WriteNextHeader(m_ssInfoStream);
//
std::stringstream ssSigHeader;
WriteSignatureHeader(ssSigHeader);
//
UInt32 written;
//
m_pLibFile->Write(ssSigHeader.str().c_str(),ssSigHeader.str().length(), written);
//
m_pLibFile->Write(m_ssFileStream.str().c_str(),m_ssFileStream.str().length(), written);
//
m_pLibFile->Write(m_ssInfoStream.str().c_str(),m_ssInfoStream.str().length(), written);
return true;
}
/**************************************************************************************/
bool vfs::CCreateUncompressed7zLibrary::WriteSignatureHeader(std::ostream& out)
{
vfs::UInt32 count=0;
// #define k7zSignatureSize -> not in namespace sz
count += szExt::WRITEBUFFER(out, sz::k7zSignature, k7zSignatureSize);
sz::Byte Major = 0, Minor = 2;
count += szExt::WRITEALL(out, (sz::Byte)Major );
count += szExt::WRITEALL(out, (sz::Byte)Minor );
sz::UInt32 StartHeaderCRC, NextHeaderCRC;
SFileInfo const& fi = m_lFileInfo.back();
sz::UInt64 NextHeaderOffset = fi.offset + fi.size;
sz::UInt64 NextHeaderSize = m_ssInfoStream.str().length()*sizeof(char);
NextHeaderCRC = sz::CrcCalc(m_ssInfoStream.str().c_str(),(size_t)NextHeaderSize);
std::stringstream sstemp;
count += szExt::WRITEALL(sstemp, (sz::UInt64)NextHeaderOffset );
count += szExt::WRITEALL(sstemp, (sz::UInt64)NextHeaderSize );
count += szExt::WRITEALL(sstemp, (sz::UInt32)NextHeaderCRC );
StartHeaderCRC = sz::CrcCalc(sstemp.str().c_str(), sstemp.str().length()*sizeof(char));
count += szExt::WRITEALL(out, (sz::UInt32)StartHeaderCRC );
out << sstemp.str();
return true;
}
bool vfs::CCreateUncompressed7zLibrary::WriteNextHeader(std::ostream& out)
{
szExt::WRITE(out, (sz::Byte)sz::k7zIdHeader);
// this->WriteArchiveProperties(out);
// this->WriteAdditionalStreamsInfo(out)
//
this->WriteMainStreamsInfo(out);
//
this->WriteFilesInfo(out);
szExt::WRITE(out, (sz::Byte)sz::k7zIdEnd );
return true;
}
bool vfs::CCreateUncompressed7zLibrary::WriteMainStreamsInfo(std::ostream& out)
{
szExt::WRITE(out, (sz::Byte)sz::k7zIdMainStreamsInfo );
this->WritePackInfo(out);
this->WriteUnPackInfo(out);
this->WriteSubStreamsInfo(out);
szExt::WRITE(out, (sz::Byte)sz::k7zIdEnd );
return true;
}
bool vfs::CCreateUncompressed7zLibrary::WritePackInfo(std::ostream& out)
{
szExt::WRITE(out, (sz::Byte)sz::k7zIdPackInfo );
szExt::WRITE(out, (sz::UInt64)0 ); // data offset
szExt::WRITE(out, (sz::UInt32)m_lFileInfo.size() );
szExt::WRITE(out, (sz::Byte)sz::k7zIdSize );
std::list<SFileInfo>::iterator it = m_lFileInfo.begin();
for(;it != m_lFileInfo.end(); ++it)
{
szExt::WRITE(out, (sz::UInt64)it->size );
}
szExt::WRITE(out, (sz::Byte)sz::k7zIdEnd );
return true;
}
bool vfs::CCreateUncompressed7zLibrary::WriteUnPackInfo(std::ostream& out)
{
szExt::WRITE(out, (sz::Byte)sz::k7zIdUnpackInfo );
szExt::WRITE(out, (sz::Byte)sz::k7zIdFolder );
szExt::WRITE(out, (sz::UInt64)m_lFileInfo.size() );
szExt::WRITE(out, (sz::Byte)0 ); // External
std::list<SFileInfo>::iterator fit = m_lFileInfo.begin();
for(;fit != m_lFileInfo.end(); ++fit)
{
this->WriteFolder(out);
}
szExt::WRITE(out, (sz::Byte)sz::k7zIdCodersUnpackSize );
fit = m_lFileInfo.begin();
for(;fit != m_lFileInfo.end(); ++fit)
{
szExt::WRITE(out, (sz::UInt64)fit->size );
}
szExt::WRITE(out, (sz::Byte)sz::k7zIdEnd );
return true;
}
bool vfs::CCreateUncompressed7zLibrary::WriteSubStreamsInfo(std::ostream& out)
{
szExt::WRITE(out, (sz::Byte)sz::k7zIdSubStreamsInfo );
szExt::WRITE(out, (sz::Byte)sz::k7zIdCRC );
szExt::WRITE(out, (sz::Byte)1 ); // early out - all CRCs defined
std::list<SFileInfo>::iterator fit = m_lFileInfo.begin();
for(;fit != m_lFileInfo.end(); ++fit )
{
szExt::WRITEALL(out, (sz::UInt32)fit->CRC);
}
szExt::WRITE(out, (sz::Byte)sz::k7zIdEnd );
return true;
}
bool vfs::CCreateUncompressed7zLibrary::WriteFolder(std::ostream& out)
{
szExt::WRITE(out, (sz::UInt32)1 ); // NumCoders
szExt::WRITE(out, (sz::Byte)1 ); // MainByte
szExt::WRITE(out, (sz::Byte)0 ); // Methods
return true;
}
bool vfs::CCreateUncompressed7zLibrary::WriteFilesInfo(std::ostream& out)
{
szExt::WRITE(out, (sz::Byte)sz::k7zIdFilesInfo );
vfs::UInt64 num_files = (m_lFileInfo.size()+m_mapDirInfo.size());
szExt::WRITE(out, (sz::UInt64)num_files );
// empty stream -> pack info in bit-vector
szExt::WRITE(out, (sz::Byte)sz::k7zIdEmptyStream );
sz::UInt64 num_empty64 = num_files/8 + (num_files%8 == 0 ? 0 : 1);
size_t num_empty = (size_t)num_empty64;
THROWIFFALSE(num_empty == num_empty64, L"WTF");
sz::Byte *empty_vector = new sz::Byte[num_empty];
memset(empty_vector,0,num_empty);
for(vfs::UInt32 e=m_lFileInfo.size(); e < num_files; ++e)
{
size_t index = e / 8;
empty_vector[index] |= 1 << (7 - e%8);
}
szExt::WRITE(out, (sz::UInt64)num_empty ); // size
szExt::WRITEBUFFER(out, empty_vector, num_empty);
delete[] empty_vector;
// names
szExt::WRITE(out, (sz::Byte)sz::k7zIdName );
sz::UInt32 count = 0;
std::stringstream name_stream;
count += szExt::WRITE(name_stream, (sz::Byte)0 ); // switch
std::list<SFileInfo>::iterator fit = m_lFileInfo.begin();
for(;fit != m_lFileInfo.end(); ++fit)
{
count += this->WriteFileName(name_stream, fit->name);
}
std::map<utf8string::str_t,SFileInfo>::iterator dit = m_mapDirInfo.begin();
for(;dit != m_mapDirInfo.end(); ++dit)
{
count += this->WriteFileName(name_stream, dit->second.name);
}
szExt::WRITE(out, (sz::UInt64)count ); // size
szExt::WRITEBUFFER(out, name_stream.str().c_str(), name_stream.str().length() );
//szExt::WRITE(out, (sz::Byte)sz::k7zIdEmptyFile );
//szExt::WRITE(out, (sz::Byte)sz::k7zIdCTime ); // create
//szExt::WRITE(out, (sz::Byte)sz::k7zIdATime ); // last access
//szExt::WRITE(out, (sz::Byte)sz::k7zIdMTime ); // write
//szExt::WRITE(out, (sz::Byte)sz::k7zIdWinAttributes );
szExt::WRITE(out, (sz::Byte)sz::k7zIdEnd );
return true;
}
vfs::UInt32 vfs::CCreateUncompressed7zLibrary::WriteFileName(std::ostream& out, utf8string const& filename)
{
vfs::UInt32 count = 0;
THROWIFFALSE(filename.length(), L"zero length name");
count += szExt::WRITEBUFFER(out, &filename.c_wcs().at(0), filename.length());
count += szExt::WRITE(out, (sz::Byte)0);
count += szExt::WRITE(out, (sz::Byte)0);
return count;
}
+64
View File
@@ -0,0 +1,64 @@
#ifndef _VFS_CREATE_7Z_LIBRARY_H_
#define _VFS_CREATE_7Z_LIBRARY_H_
//#include "Interface/vfs_library_interface.h"
//#include "Interface/vfs_directory_interface.h"
#include "../Interface/vfs_file_interface.h"
#include <sstream>
#include <map>
#include <list>
namespace vfs
{
class CCreateUncompressed7zLibrary
{
public:
CCreateUncompressed7zLibrary();
virtual ~CCreateUncompressed7zLibrary();
bool AddFile(vfs::tReadableFile* pFile);
bool WriteLibrary(vfs::Path const& sLibName);
bool WriteLibrary(vfs::tWriteableFile* pFile);
protected:
bool WriteSignatureHeader(std::ostream& out);
bool WriteNextHeader(std::ostream& out);
bool WriteMainStreamsInfo(std::ostream &out);
bool WritePackInfo(std::ostream& out);
bool WriteUnPackInfo(std::ostream& out);
bool WriteSubStreamsInfo(std::ostream& out);
bool WriteFolder(std::ostream& out);
bool WriteFilesInfo(std::ostream& out);
private:
unsigned int WriteFileName(std::ostream& out, utf8string const& filename);
protected:
vfs::tWriteableFile* m_pLibFile;
struct SFileInfo
{
SFileInfo()
: name(L""), CRC(0), offset(0), size(0), time_creation(0), time_last_access(0), time_write(0)
{};
//////
utf8string::str_t name;
UInt32 CRC;
UInt64 offset;
UInt64 size;
UInt64 time_creation,time_last_access,time_write;
};
typedef std::map<utf8string::str_t,SFileInfo> tDirInfo;
std::list<SFileInfo> m_lFileInfo;
tDirInfo m_mapDirInfo;
// keeping pointers to files to write their contents lates is not enough,
// as the file may only exist for a short time
std::stringstream m_ssFileStream;
std::stringstream m_ssInfoStream;
};
} // end namespace
#endif // _VFS_CREATE_7Z_LIBRARY_H_
+512
View File
@@ -0,0 +1,512 @@
#include "vfs_directory_tree.h"
#include "../File/vfs_dir_file.h"
#include "../Interface/vfs_location_aware_file_interface.h"
#include "../iteratedir.h"
#include <queue>
#include <list>
#include <set>
const utf8string::str_t CONST_EXT_TXT = L".TXT";
const utf8string::str_t CONST_EXT_LOG = L".LOG";
const utf8string::str_t CONST_EXT_INI = L".INI";
namespace vfs
{
class CSubDir : public vfs::IDirectory<vfs::CDirectoryTree::tWriteType>
{
typedef std::map<vfs::Path, tFileType*, vfs::Path::Less> tFileCatalogue;
class IterImpl : public tClassType::Iterator::IImplemetation
{
public:
IterImpl(CSubDir& dir);
virtual ~IterImpl();
virtual tFileType* value();
virtual void next();
private:
CSubDir& _dir;
tFileCatalogue::iterator _iter;
};
public:
CSubDir(vfs::Path const& sMountPoint, vfs::Path const& sRealPath)
: vfs::IDirectory<vfs::CDirectoryTree::tWriteType>(sMountPoint,sRealPath)
{};
virtual ~CSubDir();
virtual bool FileExists(vfs::Path const& rFileName);
virtual vfs::IBaseFile* GetFile(vfs::Path const& rFileName);
virtual tFileType* GetFileTyped(vfs::Path const& rFileName);
virtual tFileType* AddFile(vfs::Path const& sFilename, bool bDeleteOldFile=false);
virtual bool AddFile(tFileType* pFile, bool bDeleteOldFile=false);
virtual bool CreateSubDirectory(vfs::Path const& sSubDirPath);
virtual bool DeleteDirectory(vfs::Path const& sDirPath);
virtual bool DeleteFileFromDirectory(vfs::Path const& sFileName);
virtual void GetSubDirList(std::list<vfs::Path>& rlSubDirs);
virtual Iterator begin();
private:
tFileCatalogue m_mapFiles;
};
}
/********************************************************/
vfs::CSubDir::IterImpl::IterImpl(CSubDir& dir)
: _dir(dir)
{
_iter = _dir.m_mapFiles.begin();
}
vfs::CSubDir::IterImpl::~IterImpl()
{
}
vfs::CSubDir::tFileType* vfs::CSubDir::IterImpl::value()
{
if(_iter != _dir.m_mapFiles.end())
{
return _iter->second;
}
return NULL;
}
void vfs::CSubDir::IterImpl::next()
{
if(_iter != _dir.m_mapFiles.end())
{
_iter++;
}
}
/********************************************************/
vfs::CSubDir::~CSubDir()
{
tFileCatalogue::iterator it = m_mapFiles.begin();
for(; it != m_mapFiles.end(); ++it)
{
if(it->second)
{
it->second->Close();
delete it->second;
}
}
m_mapFiles.clear();
}
bool vfs::CSubDir::FileExists(vfs::Path const& sFileName)
{
tFileCatalogue::iterator it = m_mapFiles.find(sFileName);
bool success = (it != m_mapFiles.end()) && (it->second != NULL);
return success;
}
vfs::IBaseFile* vfs::CSubDir::GetFile(vfs::Path const& sFileName)
{
return GetFileTyped(sFileName);
}
vfs::CSubDir::tFileType* vfs::CSubDir::GetFileTyped(vfs::Path const& sFileName)
{
tFileCatalogue::iterator it = m_mapFiles.find(sFileName);
if(it != m_mapFiles.end())
{
CSubDir::tFileType* file = it->second;
return file;
}
return NULL;
}
vfs::CSubDir::tFileType* vfs::CSubDir::AddFile(vfs::Path const& sFilename, bool bDeleteOldFile)
{
#if 1
tFileType* pFile = m_mapFiles[sFilename];
#else
CSubDir::tFileCatalogue::iterator it;
tFileType* pFile = ((it=m_mapFiles.find(sFilename)) != m_mapFiles.end()) ? it->second : NULL;
#endif
if(pFile)
{
if(!bDeleteOldFile)
{
// not allowed to replace old file
return NULL;
}
delete pFile;
}
utf8string sExtension;
sFilename.Extension(sExtension);
if(sExtension == CONST_EXT_TXT || sExtension == CONST_EXT_LOG || sExtension == CONST_EXT_INI)
{
pFile = new vfs::CVFSTextFile(sFilename,this);
}
else
{
pFile = new vfs::CVFSFile(sFilename,this);
}
#if 1
m_mapFiles[sFilename] = pFile;
#else
m_mapFiles.insert(std::make_pair(sFilename,pFile));
#endif
return pFile;
}
bool vfs::CSubDir::AddFile(tFileType* pFile, bool bDeleteOldFile)
{
if(!pFile)
{
return false;
}
tFileType * pOldFile = m_mapFiles[pFile->GetFileName()];
if( pOldFile && (pOldFile != pFile) )
{
if(bDeleteOldFile)
{
pOldFile->Close();
delete pOldFile;
}
}
m_mapFiles[pFile->GetFileName()] = pFile;
return true;
}
bool vfs::CSubDir::DeleteDirectory(vfs::Path const& sDirPath)
{
if( !(m_sMountPoint == sDirPath) )
{
return false;
}
tFileCatalogue::iterator it = m_mapFiles.begin();
for(; it != m_mapFiles.end(); ++it)
{
tFileType* pFile = it->second;
if(pFile)
{
pFile->Close();
if(!pFile->Delete())
{
std::wstringstream wss;
wss << L"Could not delete file \"" << pFile->GetFullPath()() << L"\"";
THROWEXCEPTION(wss.str().c_str());
}
delete pFile;
}
}
m_mapFiles.clear();
return true;
}
bool vfs::CSubDir::DeleteFileFromDirectory(vfs::Path const& rFileName)
{
tFileCatalogue::iterator it = m_mapFiles.find(rFileName);
if( it != m_mapFiles.end() )
{
tFileType* pFile = it->second;
if(pFile)
{
pFile->Close();
THROWIFFALSE(pFile->Delete(), L"Could not delete file");
delete pFile;
}
m_mapFiles.erase(it);
return true;
}
return false;
}
bool vfs::CSubDir::CreateSubDirectory(vfs::Path const& sSubDirPath)
{
return false;
}
void vfs::CSubDir::GetSubDirList(std::list<vfs::Path>& rlSubDirs)
{
}
vfs::CSubDir::Iterator vfs::CSubDir::begin()
{
Iterator it;
{
it = Iterator(new IterImpl(*this));
}
return it;
}
/********************************************************************************************/
/********************************************************************************************/
/********************************************************************************************/
vfs::CDirectoryTree::~CDirectoryTree()
{
tDirCatalogue::iterator it = m_catDirs.begin();
for(;it != m_catDirs.end(); ++it)
{
delete it->second;
it->second = NULL;
}
m_catDirs.clear();
}
bool vfs::CDirectoryTree::Init()
{
// contains local path
typedef std::pair<vfs::Path,CSubDir*> tDirs;
std::queue<tDirs> qSubDirs;
qSubDirs.push(tDirs(vfs::Path(vfs::Const::EMPTY()),new CSubDir(m_sMountPoint,m_sRealPath)));
m_catDirs[m_sMountPoint] = qSubDirs.front().second;
utf8string sFilename;
CSubDir *pCurrentDir;
vfs::Path oCurDir;
while(!qSubDirs.empty())
{
pCurrentDir = qSubDirs.front().second;
oCurDir = m_sRealPath;
if( !qSubDirs.front().first.empty())
{
oCurDir += qSubDirs.front().first;
}
try
{
os::CIterateDirectory::EFileAttribute eFA;
os::CIterateDirectory iterFS(oCurDir, vfs::Const::STAR());
while ( iterFS.NextFile(sFilename, eFA) )
{
if (StrCmp::Equal(vfs::Const::DOT(),sFilename) || StrCmp::Equal(vfs::Const::DOTDOT(),sFilename) || StrCmp::Equal(vfs::Const::DOTSVN(),sFilename) )
{
continue;
}
if (eFA == os::CIterateDirectory::FA_DIRECTORY)
{
vfs::Path sLocal = qSubDirs.front().first + sFilename;
vfs::Path temp = m_sMountPoint+sLocal;
CSubDir *pNewDir = new CSubDir(sLocal, m_sRealPath+sLocal);
qSubDirs.push(tDirs(sLocal,pNewDir));
m_catDirs[temp] = pNewDir;
}
else
{
pCurrentDir->AddFile(vfs::Path(sFilename));
}
}
}
catch(CBasicException &ex)
{
// probably directory doesn't exist. abort or continue???
// -> abort AND continue
return false;
}
qSubDirs.pop();
}
return true;
}
vfs::CDirectoryTree::tFileType* vfs::CDirectoryTree::AddFile(vfs::Path const& sFilename, bool bDeleteOldFile)
{
vfs::Path sDir,sFile;
sFilename.SplitLast(sDir,sFile);
tDirCatalogue::iterator it = m_catDirs.find(sDir);
if(it == m_catDirs.end())
{
vfs::Path sTemp,sCreateDir,sLeft,sRight = sDir;
while(sRight.SplitFirst(sLeft,sTemp))
{
sRight = sTemp;
sCreateDir += sLeft;
CreateSubDirectory(sCreateDir);
}
it = m_catDirs.find(sDir);
if(it == m_catDirs.end())
{
return NULL;
}
}
if(it->second)
{
vfs::CDirectoryTree::tFileType* file = it->second->AddFile(sFile,bDeleteOldFile);
return file;
}
return NULL;
}
bool vfs::CDirectoryTree::AddFile(tFileType* pFile, bool bDeleteOldFile)
{
// no files from outside
// these files are not connected with the correct directory object
return false;
}
bool vfs::CDirectoryTree::DeleteDirectory(vfs::Path const& sDirPath)
{
tDirCatalogue::iterator it = m_catDirs.find(sDirPath);
if(it == m_catDirs.end())
{
// no such directory
return false;
}
if(it->second)
{
return it->second->DeleteDirectory(sDirPath);
}
return false;
}
bool vfs::CDirectoryTree::DeleteFileFromDirectory(vfs::Path const& sFileName)
{
vfs::Path sDir,sFile;
sFileName.SplitLast(sDir,sFile);
tDirCatalogue::iterator it = m_catDirs.find(sDir);
if(it == m_catDirs.end())
{
// no such directory
return false;
}
if(it->second)
{
return it->second->DeleteFileFromDirectory(sFile);
}
return false;
}
/**
* IVFSLocation interface
*/
bool vfs::CDirectoryTree::FileExists(vfs::Path const& sFileName)
{
vfs::Path sDir, sFile;
sFileName.SplitLast(sDir, sFile);
tDirCatalogue::iterator it = m_catDirs.find(sDir);
if(it == m_catDirs.end())
{
// no such directory
return false;
}
if(it->second)
{
bool success = it->second->FileExists(sFile);
return success;
}
return false;
}
vfs::IBaseFile* vfs::CDirectoryTree::GetFile(vfs::Path const& sFileName)
{
return GetFileTyped(sFileName);
}
vfs::CDirectoryTree::tFileType* vfs::CDirectoryTree::GetFileTyped(vfs::Path const& sFileName)
{
vfs::Path sDir, sFile;
sFileName.SplitLast(sDir, sFile);
//tDirCatalogue::iterator it = m_catDirs.find(sDir);
tDirCatalogue::iterator it = m_catDirs.find(sDir);
if(it == m_catDirs.end())
{
// no such directory
return NULL;
}
if(it->second)
{
vfs::CDirectoryTree::tFileType* file = it->second->GetFileTyped(sFile);
return file;
}
return NULL;
}
bool vfs::CDirectoryTree::CreateSubDirectory(vfs::Path const& sSubDirPath)
{
if(os::CreateRealDirecory( m_sRealPath + sSubDirPath ))
{
if( m_catDirs[sSubDirPath] == NULL)
{
CSubDir *pNewDir = new CSubDir(sSubDirPath, m_sRealPath + sSubDirPath);
m_catDirs[sSubDirPath] = pNewDir;
}
return true;
}
return false;
}
void vfs::CDirectoryTree::GetSubDirList(std::list<vfs::Path>& rlSubDirs)
{
tDirCatalogue::iterator it = m_catDirs.begin();
for(;it != m_catDirs.end(); ++it)
{
rlSubDirs.push_back(it->first);
}
}
vfs::CDirectoryTree::Iterator vfs::CDirectoryTree::begin()
{
return Iterator(new IterImpl(*this));
}
/*****************************************************************************/
/*****************************************************************************/
vfs::CDirectoryTree::IterImpl::IterImpl(CDirectoryTree& tree)
: _tree(tree)
{
_subdir_iter = _tree.m_catDirs.begin();
if(_subdir_iter != _tree.m_catDirs.end())
{
CSubDir *sdir = dynamic_cast<CSubDir*>(_subdir_iter->second);
CSubDir::Iterator it = sdir->begin();
_file_iter = it;
if(_file_iter.end())
{
next();
}
}
}
vfs::CDirectoryTree::IterImpl::~IterImpl()
{
}
vfs::CDirectoryTree::tFileType* vfs::CDirectoryTree::IterImpl::value()
{
if(!_file_iter.end())
{
return static_cast<tFileType*>(_file_iter.value());
}
return NULL;
}
void vfs::CDirectoryTree::IterImpl::next()
{
if(!_file_iter.end())
{
_file_iter.next();
}
// need to loop for the case when one or many sub directories are empty
while(_file_iter.end())
{
if(_subdir_iter == _tree.m_catDirs.end())
{
break;
}
else
{
_subdir_iter++;
if(_subdir_iter != _tree.m_catDirs.end())
{
_file_iter = _subdir_iter->second->begin();
}
}
}
return;
}
+70
View File
@@ -0,0 +1,70 @@
#ifndef _VFS_DIRECTORY_H_
#define _VFS_DIRECTORY_H_
#include "../vfs_types.h"
//#include "Interface/vfs_location_interface.h"
#include "../Interface/vfs_file_interface.h"
#include "../Interface/vfs_directory_interface.h"
#include <map>
#include <vector>
namespace vfs
{
/**
* IDirectory<read,write>
*/
class CDirectoryTree : public vfs::IDirectory<vfs::IWriteable>
{
typedef std::map<vfs::Path, vfs::IDirectory<CDirectoryTree::tWriteType>*, vfs::Path::Less> tDirCatalogue;
class IterImpl : public tClassType::Iterator::IImplemetation
{
public:
IterImpl(CDirectoryTree& tree);
virtual ~IterImpl();
virtual tFileType* value();
virtual void next();
private:
CDirectoryTree& _tree;
tDirCatalogue::iterator _subdir_iter;
tClassType::Iterator _file_iter;
};
public:
CDirectoryTree(vfs::Path const& sMountPoint, vfs::Path const& sRealPath)
: vfs::IDirectory<vfs::IWriteable>(sMountPoint,sRealPath)
{};
virtual ~CDirectoryTree();
bool Init();
/**
* IDirectory interface
*/
virtual tFileType* AddFile(vfs::Path const& sFilename, bool bDeleteOldFile=false);
virtual bool AddFile(tFileType* pFile, bool bDeleteOldFile=false);
virtual bool CreateSubDirectory(vfs::Path const& sSubDirPath);
virtual bool DeleteDirectory(vfs::Path const& sDirPath);
virtual bool DeleteFileFromDirectory(vfs::Path const& sFileName);
/**
* IVFSLocation interface
*/
virtual bool FileExists(vfs::Path const& sFileName);
virtual vfs::IBaseFile* GetFile(vfs::Path const& sFileName);
virtual tFileType* GetFileTyped(vfs::Path const& sFileName);
virtual void GetSubDirList(std::list<vfs::Path>& rlSubDirs);
virtual Iterator begin();
protected:
tDirCatalogue m_catDirs;
};
} // end namespace
#endif // _VFS_DIRECTORY_H_
+151
View File
@@ -0,0 +1,151 @@
#include "vfs_lib_dir.h"
vfs::CLibDirectory::~CLibDirectory()
{
tFileCatalogue::iterator it = m_mapFiles.begin();
for(; it != m_mapFiles.end(); ++it)
{
// don't delete objects here
//delete it->second;
}
m_mapFiles.clear();
}
vfs::CLibDirectory::tFileType* vfs::CLibDirectory::AddFile(vfs::Path const& sFilename, bool bDeleteOldFile)
{
return NULL;
}
bool vfs::CLibDirectory::AddFile(tFileType* pFile, bool bDeleteOldFile)
{
if(!pFile)
{
return false;
}
vfs::Path const& sName = pFile->GetFileName();
tFileType* pFileOld = m_mapFiles[sName];
if(pFileOld && (pFileOld != pFile) )
{
if(bDeleteOldFile)
{
delete pFileOld;
m_mapFiles[sName] = pFile;
}
else
{
return false;
}
}
m_mapFiles[sName] = pFile;
return true;
}
bool vfs::CLibDirectory::DeleteDirectory(vfs::Path const& sDirPath)
{
if( !(m_sMountPoint == sDirPath) )
{
return false;
}
if(IsWriteable())
{
tFileCatalogue::iterator it = m_mapFiles.begin();
for(; it != m_mapFiles.end(); ++it)
{
delete it->second;
}
m_mapFiles.clear();
return true;
}
return false;
}
bool vfs::CLibDirectory::DeleteFileFromDirectory(vfs::Path const& sFileName)
{
if(IsWriteable())
{
tFileCatalogue::iterator it = m_mapFiles.find(sFileName);
if(it != m_mapFiles.end())
{
delete it->second;
m_mapFiles.erase(it);
return true;
}
}
return false;
}
bool vfs::CLibDirectory::FileExists(vfs::Path const& sFileName)
{
bool success = (m_mapFiles[sFileName] != NULL);
return success;
}
vfs::IBaseFile* vfs::CLibDirectory::GetFile(vfs::Path const& sFileName)
{
return GetFileTyped(sFileName);
}
vfs::CLibDirectory::tFileType* vfs::CLibDirectory::GetFileTyped(vfs::Path const& sFileName)
{
CLibDirectory::tFileType* file = m_mapFiles[sFileName];
return file;
}
bool vfs::CLibDirectory::CreateSubDirectory(vfs::Path const& sSubDirPath)
{
// libraries are readonly
return false;
}
void vfs::CLibDirectory::GetSubDirList(std::list<vfs::Path>& rlSubDirs)
{
}
vfs::CLibDirectory::Iterator vfs::CLibDirectory::begin()
{
return Iterator(new IterImpl(*this));
}
/***************************************************************************/
/***************************************************************************/
vfs::CLibDirectory::IterImpl::IterImpl(CLibDirectory& lib)
: _lib(lib)
{
_iter = _lib.m_mapFiles.begin();
}
vfs::CLibDirectory::IterImpl::~IterImpl()
{
}
vfs::CLibDirectory::tFileType* vfs::CLibDirectory::IterImpl::value()
{
if(_iter != _lib.m_mapFiles.end())
{
return _iter->second;
}
return NULL;
}
void vfs::CLibDirectory::IterImpl::next()
{
if(_iter != _lib.m_mapFiles.end())
{
_iter++;
}
}
/***************************************************************************/
/***************************************************************************/
static void tesst()
{
vfs::CLibDirectory *dir = new vfs::CLibDirectory(vfs::Path("test"), vfs::Path("test2"));
vfs::CLibDirectory::Iterator it = dir->begin();
while(!it.end())
{
vfs::CLibDirectory::tFileType* file = static_cast<vfs::CLibDirectory::tFileType*>(it.value());
it.next();
}
}
+54
View File
@@ -0,0 +1,54 @@
#ifndef _VFS_LIB_DIR_H_
#define _VFS_LIB_DIR_H_
#include "../Interface/vfs_directory_interface.h"
namespace vfs
{
class CLibDirectory : public vfs::IDirectory<vfs::IWriteType>
{
typedef std::map<vfs::Path, tFileType*, vfs::Path::Less> tFileCatalogue;
class IterImpl : public tClassType::Iterator::IImplemetation
{
public:
IterImpl(CLibDirectory& lib);
virtual ~IterImpl();
virtual tFileType* value();
virtual void next();
private:
CLibDirectory& _lib;
tFileCatalogue::iterator _iter;
};
public:
CLibDirectory(vfs::Path const& sLocalPath, vfs::Path const& sRealPath)
: vfs::IDirectory<vfs::IWriteType>(sLocalPath,sRealPath)
{};
virtual ~CLibDirectory();
/**
* IDirectory interface
*/
virtual tFileType* AddFile(vfs::Path const& sFilename, bool bDeleteOldFile=false);
virtual bool AddFile(tFileType* pFile, bool bDeleteOldFile=false);
virtual bool DeleteFileFromDirectory(vfs::Path const& sFileName);
virtual bool CreateSubDirectory(vfs::Path const& sSubDirPath);
virtual bool DeleteDirectory(vfs::Path const& sDirPath);
/**
* IVFSLocation interface
*/
virtual bool FileExists(vfs::Path const& sFileName);
virtual vfs::IBaseFile* GetFile(vfs::Path const& sFileName);
virtual tFileType* GetFileTyped(vfs::Path const& sFileName);
virtual void GetSubDirList(std::list<vfs::Path>& rlSubDirs);
virtual Iterator begin();
protected:
tFileCatalogue m_mapFiles;
};
} // -end- namespace
#endif // _VFS_LIB_DIR_H_
+156
View File
@@ -0,0 +1,156 @@
#include "vfs_slf_library.h"
#include "../Interface/vfs_directory_interface.h"
#include "vfs_lib_dir.h"
#include "../File/vfs_lib_file.h"
namespace slf
{
// copy from WinDef.h
typedef unsigned long DWORD;
typedef struct _FILETIME {
DWORD dwLowDateTime;
DWORD dwHighDateTime;
} FILETIME, *PFILETIME, *LPFILETIME;
typedef void* HANDLE;
const vfs::UInt32 FILENAME_SIZE = 256;
const vfs::UInt32 PATH_SIZE = 80;
const vfs::UInt32 FILE_OK = 0;
const vfs::UInt32 FILE_DELETED = 0xff;
const vfs::UInt32 FILE_OLD = 1;
const vfs::UInt32 FILE_DOESNT_EXIST = 0xfe;
struct LIBHEADER
{
vfs::Byte sLibName[ FILENAME_SIZE ];
vfs::Byte sPathToLibrary[ FILENAME_SIZE ];
vfs::Int32 iEntries;
vfs::Int32 iUsed;
vfs::UInt16 iSort;
vfs::UInt16 iVersion;
vfs::UByte fContainsSubDirectories;
vfs::Int32 iReserved;
};
struct DIRENTRY
{
vfs::Byte sFileName[ FILENAME_SIZE ];
vfs::UInt32 uiOffset;
vfs::UInt32 uiLength;
vfs::UInt8 ubState;
vfs::UInt8 ubReserved;
FILETIME sFileTime;
vfs::UInt16 usReserved2;
};
}; // end namespace slf
/********************************************************************************************/
/********************************************************************************************/
/********************************************************************************************/
vfs::CSLFLibrary::~CSLFLibrary()
{
}
bool vfs::CSLFLibrary::Init()
{
if(m_pLibraryFile)
{
if(!m_pLibraryFile->OpenRead())
{
return false;
}
slf::LIBHEADER LibFileHeader;
UInt32 uiNumBytesRead;
if(!m_pLibraryFile->Read((Byte*)&LibFileHeader,sizeof( slf::LIBHEADER ), uiNumBytesRead))
{
m_pLibraryFile->Close();
return false;
}
if( uiNumBytesRead != sizeof( slf::LIBHEADER ) )
{
//Error Reading the file database header.
m_pLibraryFile->Close();
return false;
}
vfs::Path oLibPath;
//if the library has a path
if( strlen( LibFileHeader.sPathToLibrary ) != 0 )
{
oLibPath = vfs::Path( LibFileHeader.sPathToLibrary );
}
else
{
//else the library name does not contain a path ( most likely either an error or it is the default path )
oLibPath = vfs::Path( vfs::Const::EMPTY() );
}
if(m_sMountPoint.empty())
{
m_sMountPoint = oLibPath;
}
else
{
m_sMountPoint += oLibPath;
}
//place the file pointer at the begining of the file headers ( they are at the end of the file )
m_pLibraryFile->SetReadLocation(-( LibFileHeader.iEntries * (Int32)sizeof(slf::DIRENTRY) ), vfs::IBaseFile::SD_END);
//loop through the library and determine the number of files that are FILE_OK
//ie. so we dont load the old or deleted files
slf::DIRENTRY DirEntry;
vfs::Path oDir, oFile;
vfs::Path oDirPath;
for(UInt32 uiLoop=0; uiLoop < (UInt32)LibFileHeader.iEntries; uiLoop++ )
{
//read in the file header
if(!m_pLibraryFile->Read((Byte*)&DirEntry, sizeof( slf::DIRENTRY ), uiNumBytesRead))
{
m_pLibraryFile->Close();
return false;
}
if( DirEntry.ubState == slf::FILE_OK )
{
vfs::Path sPath(utf8string::as_utf16(DirEntry.sFileName));
sPath.SplitLast(oDir,oFile);
oDirPath = m_sMountPoint;
if(!oDir.empty())
{
oDirPath += oDir;
}
// get or create according directory object
vfs::IDirectory<ILibrary::tWriteType>* pLD = NULL;
tDirCatalogue::iterator it = m_catDirs.find(oDirPath);
if(it != m_catDirs.end())
{
pLD = it->second;
}
else
{
pLD = new vfs::CLibDirectory(oDirPath,oDirPath);
m_catDirs.insert(std::make_pair(oDirPath,pLD));
}
// create file
vfs::CLibFile *pFile = vfs::CLibFile::Create(oFile,pLD,this);
// add file to directory
if(!pLD->AddFile(pFile))
{
m_pLibraryFile->Close();
return false;
}
// link file data struct to file object
m_mapLibData.insert(std::make_pair(pFile,sFileData(DirEntry.uiLength, DirEntry.uiOffset)));
} // end if
} // end for
m_pLibraryFile->Close();
return true;
} // end if
// no library file
return false;
}
+27
View File
@@ -0,0 +1,27 @@
#ifndef _VFS_SLF_LIBRARY_H_
#define _VFS_SLF_LIBRARY_H_
//#include "Interface/vfs_library_interface.h"
//#include "Interface/vfs_directory_interface.h"
#include "vfs_uncompressed_lib_base.h"
namespace vfs
{
class CSLFLibrary : public vfs::CUncompressedLibraryBase
{
public:
CSLFLibrary(tReadableFile *pLibraryFile, vfs::Path const& sMountPoint, bool bOwnFile = false)
: vfs::CUncompressedLibraryBase(pLibraryFile,sMountPoint,bOwnFile)
{};
virtual ~CSLFLibrary();
/**
* ILibrary interface
*/
virtual bool Init();
};
} // end namespace
#endif // _VFS_SLF_LIBRARY_H_
+267
View File
@@ -0,0 +1,267 @@
#include "vfs_uncompressed_lib_base.h"
/********************************************************************************************/
/********************************************************************************************/
/********************************************************************************************/
vfs::CUncompressedLibraryBase::~CUncompressedLibraryBase()
{
this->CloseLibrary();
// delete sub dirs from catalogue
tDirCatalogue::iterator it = m_catDirs.begin();
for(; it != m_catDirs.end(); ++it)
{
delete it->second;
}
// LibData is invalid
// just clear it, since the file handles were deleted before
m_mapLibData.clear();
m_catDirs.clear();
}
bool vfs::CUncompressedLibraryBase::CloseLibrary()
{
bool success = true;
tLibData::iterator it = m_mapLibData.begin();
for(; it != m_mapLibData .end(); ++it)
{
success &= it->first->Close();
// what if closing of (at least) one file fails?? continue or not??
// in the end, these are not real files!
}
return success;
}
bool vfs::CUncompressedLibraryBase::FileExists(vfs::Path const& sFileName)
{
vfs::Path sDir,sFile;
sFileName.SplitLast(sDir,sFile);
tDirCatalogue::iterator it = m_catDirs.find(sDir);
if(it != m_catDirs.end())
{
return it->second->FileExists(sFile);
}
return false;
}
vfs::IBaseFile* vfs::CUncompressedLibraryBase::GetFile(vfs::Path const& sFileName)
{
return GetFileTyped(sFileName);
}
vfs::CUncompressedLibraryBase::tFileType* vfs::CUncompressedLibraryBase::GetFileTyped(vfs::Path const& sFileName)
{
vfs::Path sDir,sFile;
sFileName.SplitLast(sDir,sFile);
tDirCatalogue::iterator it = m_catDirs.find(sDir);
if(it != m_catDirs.end())
{
return it->second->GetFileTyped(sFile);
}
return NULL;
}
bool vfs::CUncompressedLibraryBase::Close(tFileType *pFileHandle)
{
tLibData::iterator it = m_mapLibData.find(pFileHandle);
if(it == m_mapLibData.end())
{
// wrong file handle
return false;
}
// reset read position
// can't do this when opening file,
// because you could try to open a file when it is already open and would so reset the read position
it->second.uiCurrentReadPosition = 0;
if(m_uiNumberOfOpenedFiles > 0)
{
m_uiNumberOfOpenedFiles--;
if(m_uiNumberOfOpenedFiles == 0)
{
m_pLibraryFile->Close();
}
}
return true;
}
bool vfs::CUncompressedLibraryBase::OpenRead(tFileType *pFileHandle)
{
tLibData::iterator it = m_mapLibData.find(pFileHandle);
if(it == m_mapLibData.end())
{
// wrong file handle
return false;
}
m_uiNumberOfOpenedFiles++;
if(m_uiNumberOfOpenedFiles == 1)
{
if(!m_pLibraryFile->IsOpenRead() && !m_pLibraryFile->OpenRead())
{
return false;
}
}
// already open
return true;
}
bool vfs::CUncompressedLibraryBase::Read(tFileType *pFileHandle, Byte* pData, UInt32 uiBytesToRead, UInt32& uiBytesRead)
{
tLibData::iterator it = m_mapLibData.find(pFileHandle);
if(it == m_mapLibData.end())
{
// wrong file handle
return false;
}
// if(m_pLibraryFile->IsOpen()) ... we could check it (*AGAIN*),
// but the file implementation does it already,
// and the user probably called 'OpenRead' too,
// so why do it over and over again
if( (it->second.uiCurrentReadPosition + uiBytesToRead) > it->second.uiFileSize )
{
// original implementation
uiBytesRead = 0;
return false;
// or you could adjust the number of bytes to read
uiBytesToRead = it->second.uiFileSize - it->second.uiCurrentReadPosition; // +-1 ???
}
// set lib-file's read-location to match location of virtual-file
m_pLibraryFile->SetReadLocation(it->second.uiFileOffset + it->second.uiCurrentReadPosition,IBaseFile::SD_BEGIN);
bool success = m_pLibraryFile->Read(pData,uiBytesToRead,uiBytesRead)
&& (uiBytesToRead == uiBytesRead);
if(success)
{
it->second.uiCurrentReadPosition += uiBytesRead;
}
// false if read operation failed
return success;
}
vfs::UInt32 vfs::CUncompressedLibraryBase::GetReadLocation(tFileType *pFileHandle)
{
tLibData::iterator it = m_mapLibData.find(pFileHandle);
if(it == m_mapLibData.end())
{
// wrong file handle
return -1;
}
return it->second.uiCurrentReadPosition;
}
bool vfs::CUncompressedLibraryBase::SetReadLocation(tFileType *pFileHandle, vfs::UInt32 uiPositionInBytes)
{
tLibData::iterator it = m_mapLibData.find(pFileHandle);
if(it == m_mapLibData.end())
{
// wrong file handle
return false;
}
if( (uiPositionInBytes < 0) || (uiPositionInBytes >= (vfs::Int32)(it->second.uiFileSize)) )
{
return false;
}
// uiCurrentReadPosition is offset to file-offset
it->second.uiCurrentReadPosition = uiPositionInBytes;
return true;
}
bool vfs::CUncompressedLibraryBase::SetReadLocation(tFileType *pFileHandle, Int32 uiOffsetInBytes, IBaseFile::ESeekDir eSeekDir)
{
tLibData::iterator it = m_mapLibData.find(pFileHandle);
if(it == m_mapLibData.end())
{
// wrong file handle
return false;
}
if( abs(uiOffsetInBytes) > (Int32)(it->second.uiFileSize) )
{
// cannot be corrent in any case
return false;
}
if(eSeekDir == IBaseFile::SD_BEGIN)
{
if(uiOffsetInBytes < 0)
{
return false;
}
it->second.uiCurrentReadPosition = uiOffsetInBytes;
return true;
}
else if(eSeekDir == IBaseFile::SD_CURRENT)
{
vfs::Int32 temp = it->second.uiCurrentReadPosition + uiOffsetInBytes;
if( (temp < 0) || (temp > (Int32)(it->second.uiFileSize)) )
{
return false;
}
it->second.uiCurrentReadPosition = temp;
return true;
}
else if(eSeekDir == IBaseFile::SD_END)
{
if(uiOffsetInBytes > 0)
{
return false;
}
it->second.uiCurrentReadPosition = it->second.uiFileSize - uiOffsetInBytes;
return true;
}
return false;
}
bool vfs::CUncompressedLibraryBase::GetFileSize(tFileType *pFileHandle, UInt32& uiFileSize)
{
tLibData::iterator it = m_mapLibData.find(pFileHandle);
if(it == m_mapLibData.end())
{
// wrong file handle
uiFileSize = 0;
return false;
}
uiFileSize = it->second.uiFileSize;
return true;
}
void vfs::CUncompressedLibraryBase::GetSubDirList(std::list<vfs::Path>& rlSubDirs)
{
tDirCatalogue::iterator it = m_catDirs.begin();
for(;it != m_catDirs.end(); ++it)
{
rlSubDirs.push_back(it->first);
}
}
vfs::CUncompressedLibraryBase::Iterator vfs::CUncompressedLibraryBase::begin()
{
return Iterator(new IterImpl(*this));
}
/************************************************************************/
/************************************************************************/
vfs::CUncompressedLibraryBase::IterImpl::IterImpl(vfs::CUncompressedLibraryBase &lib)
: _lib(&lib)
{
_iter = _lib->m_mapLibData.begin();
}
vfs::CUncompressedLibraryBase::IterImpl::~IterImpl()
{
}
vfs::CUncompressedLibraryBase::tFileType* vfs::CUncompressedLibraryBase::IterImpl::value()
{
if(_iter != _lib->m_mapLibData.end())
{
return _iter->first;
}
return NULL;
}
void vfs::CUncompressedLibraryBase::IterImpl::next()
{
if(_iter != _lib->m_mapLibData.end())
{
_iter++;
}
}
+74
View File
@@ -0,0 +1,74 @@
#ifndef _VFS_UNCOMPRESSED_LIB_BASE_H_
#define _VFS_UNCOMPRESSED_LIB_BASE_H_
#include "../Interface/vfs_library_interface.h"
#include "../Interface/vfs_directory_interface.h"
#include <sstream>
namespace vfs
{
class CUncompressedLibraryBase : public vfs::ILibrary
{
protected:
typedef std::map<vfs::Path, vfs::IDirectory<ILibrary::tWriteType>*, vfs::Path::Less> tDirCatalogue;
struct sFileData
{
sFileData(UInt32 const& fileSize, UInt32 const& fileOffset)
: uiFileSize(fileSize), uiFileOffset(fileOffset), uiCurrentReadPosition(0)
{};
UInt32 uiFileSize,uiFileOffset,uiCurrentReadPosition;
};
typedef std::map<tFileType*, sFileData> tLibData;
class IterImpl : public tClassType::Iterator::IImplemetation
{
public:
IterImpl(CUncompressedLibraryBase& lib);
virtual ~IterImpl();
virtual tFileType* value();
virtual void next();
private:
CUncompressedLibraryBase* _lib;
tLibData::iterator _iter;
};
public:
CUncompressedLibraryBase(tReadableFile *pLibraryFile, vfs::Path const& sMountPoint, bool bOwnFile = false)
: vfs::ILibrary(pLibraryFile,sMountPoint,bOwnFile), m_uiNumberOfOpenedFiles(0)
{};
virtual ~CUncompressedLibraryBase();
/**
* IVFSLocation interface
*/
virtual bool FileExists(vfs::Path const& sFileName);
virtual vfs::IBaseFile* GetFile(vfs::Path const& sFileName);
virtual tFileType* GetFileTyped(vfs::Path const& sFileName);
virtual void GetSubDirList(std::list<vfs::Path>& rlSubDirs);
/**
* ILibrary interface
*/
virtual bool Init() = 0;
virtual bool CloseLibrary();
virtual bool Close(tFileType *pFileHandle);
virtual bool OpenRead(tFileType *pFileHandle);
virtual bool Read(tFileType *pFileHandle, Byte* pData, UInt32 uiBytesToRead, UInt32& uiBytesRead);
virtual UInt32 GetReadLocation(tFileType *pFileHandle);
virtual bool SetReadLocation(tFileType *pFileHandle, UInt32 uiPositionInBytes);
virtual bool SetReadLocation(tFileType *pFileHandle, Int32 uiOffsetInBytes, IBaseFile::ESeekDir eSeekDir);
virtual bool GetFileSize(tFileType *pFileHandle, UInt32& uiFileSize);
virtual Iterator begin();
protected:
tDirCatalogue m_catDirs;
tLibData m_mapLibData;
UInt32 m_uiNumberOfOpenedFiles;
};
} // end namespace
#endif // _VFS_UNCOMPRESSED_LIB_BASE_H_