mirror of
https://github.com/1dot13/source.git
synced 2026-08-12 14:10:23 +02:00
*** 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:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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_
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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_
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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_
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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_
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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_
|
||||
|
||||
@@ -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++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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_
|
||||
|
||||
Reference in New Issue
Block a user