mirror of
https://github.com/1dot13/source.git
synced 2026-08-26 14:30:26 +02:00
- Added missing projects "VFS" & "export" to SVN
git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@4447 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
@@ -0,0 +1,628 @@
|
||||
/*
|
||||
* bfVFS : vfs/Core/Location/vfs_directory_tree.cpp
|
||||
* - class for directories in a File System, implements Directory interface
|
||||
*
|
||||
* Copyright (C) 2008 - 2010 (BF) john.bf.smith@googlemail.com
|
||||
*
|
||||
* This file is part of the bfVFS library
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <vfs/Core/Location/vfs_directory_tree.h>
|
||||
#include <vfs/Core/File/vfs_dir_file.h>
|
||||
#include <vfs/Core/vfs_os_functions.h>
|
||||
|
||||
#include <queue>
|
||||
#include <list>
|
||||
#include <set>
|
||||
|
||||
#define ERROR_FILE(msg) (_BS(msg) << L" : " << pFile->getPath() << _BS::wget)
|
||||
|
||||
namespace vfs
|
||||
{
|
||||
template<typename WriteType>
|
||||
class TSubDir : public vfs::TDirectory<typename vfs::TDirectoryTree<WriteType>::tWriteType>
|
||||
{
|
||||
typedef vfs::TDirectory<typename vfs::TDirectoryTree<WriteType>::tWriteType> tBaseClass;
|
||||
typedef typename tBaseClass::tFileType tFileType;
|
||||
|
||||
typedef std::map<vfs::Path, tFileType*, vfs::Path::Less> tFileCatalogue;
|
||||
public:
|
||||
typedef vfs::IBaseLocation::Iterator Iterator;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
class IterImpl : public vfs::IBaseLocation::Iterator::IImplementation
|
||||
{
|
||||
friend class TSubDir<WriteType>;
|
||||
typedef vfs::IBaseLocation::Iterator::IImplementation tBaseClass;
|
||||
|
||||
IterImpl(TSubDir<WriteType>* dir): _dir(dir)
|
||||
{
|
||||
VFS_THROW_IFF(_dir, L"");
|
||||
_iter = _dir->m_mapFiles.begin();
|
||||
}
|
||||
public:
|
||||
IterImpl() : tBaseClass(), _dir(NULL)
|
||||
{};
|
||||
virtual ~IterImpl()
|
||||
{};
|
||||
|
||||
virtual tFileType* value()
|
||||
{
|
||||
if(_iter != _dir->m_mapFiles.end())
|
||||
{
|
||||
return _iter->second;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
virtual void next()
|
||||
{
|
||||
if(_iter != _dir->m_mapFiles.end())
|
||||
{
|
||||
_iter++;
|
||||
}
|
||||
}
|
||||
protected:
|
||||
tBaseClass* clone()
|
||||
{
|
||||
IterImpl* iter = new IterImpl();
|
||||
iter->_dir = _dir;
|
||||
iter->_iter = _iter;
|
||||
return iter;
|
||||
}
|
||||
private:
|
||||
TSubDir<WriteType>* _dir;
|
||||
typename tFileCatalogue::iterator _iter;
|
||||
};
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
public:
|
||||
TSubDir(vfs::Path const& sMountPoint, vfs::Path const& sRealPath)
|
||||
: tBaseClass(sMountPoint,sRealPath)
|
||||
{};
|
||||
|
||||
virtual ~TSubDir();
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
template<>
|
||||
vfs::TSubDir<vfs::IWriteType>::tFileType* vfs::TSubDir<vfs::IWriteType>::addFile(vfs::Path const& sFilename, bool bDeleteOldFile);
|
||||
template<>
|
||||
vfs::TSubDir<vfs::IWritable>::tFileType* vfs::TSubDir<vfs::IWritable>::addFile(vfs::Path const& sFilename, bool bDeleteOldFile);
|
||||
|
||||
template<>
|
||||
bool vfs::TSubDir<vfs::IWriteType>::deleteDirectory(vfs::Path const& sDirPath);
|
||||
template<>
|
||||
bool vfs::TSubDir<vfs::IWritable>::deleteDirectory(vfs::Path const& sDirPath);
|
||||
|
||||
template<>
|
||||
bool vfs::TSubDir<vfs::IWriteType>::deleteFileFromDirectory(vfs::Path const& rFileName);
|
||||
template<>
|
||||
bool vfs::TSubDir<vfs::IWritable>::deleteFileFromDirectory(vfs::Path const& rFileName);
|
||||
}
|
||||
|
||||
/********************************************************/
|
||||
|
||||
template<typename WriteType>
|
||||
vfs::TSubDir<WriteType>::~TSubDir()
|
||||
{
|
||||
typename tFileCatalogue::iterator it = m_mapFiles.begin();
|
||||
for(; it != m_mapFiles.end(); ++it)
|
||||
{
|
||||
if(it->second)
|
||||
{
|
||||
it->second->close();
|
||||
delete it->second;
|
||||
}
|
||||
}
|
||||
m_mapFiles.clear();
|
||||
}
|
||||
|
||||
template<typename WriteType>
|
||||
bool vfs::TSubDir<WriteType>::fileExists(vfs::Path const& sFileName)
|
||||
{
|
||||
typename tFileCatalogue::iterator it = m_mapFiles.find(sFileName);
|
||||
bool success = (it != m_mapFiles.end()) && (it->second != NULL);
|
||||
return success;
|
||||
}
|
||||
|
||||
template<typename WriteType>
|
||||
vfs::IBaseFile* vfs::TSubDir<WriteType>::getFile(vfs::Path const& sFileName)
|
||||
{
|
||||
return getFileTyped(sFileName);
|
||||
}
|
||||
|
||||
template<typename WriteType>
|
||||
typename vfs::TSubDir<WriteType>::tFileType* vfs::TSubDir<WriteType>::getFileTyped(vfs::Path const& sFileName)
|
||||
{
|
||||
typename tFileCatalogue::iterator it = m_mapFiles.find(sFileName);
|
||||
if(it != m_mapFiles.end())
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
template<>
|
||||
vfs::TSubDir<vfs::IWriteType>::tFileType* vfs::TSubDir<vfs::IWriteType>::addFile(vfs::Path const& sFilename, bool bDeleteOldFile)
|
||||
{
|
||||
tFileType* pFile = m_mapFiles[sFilename];
|
||||
if(pFile)
|
||||
{
|
||||
if(!bDeleteOldFile)
|
||||
{
|
||||
// not allowed to replace old file
|
||||
return NULL;
|
||||
}
|
||||
delete pFile;
|
||||
}
|
||||
pFile = new vfs::CReadOnlyDirFile(sFilename,this);
|
||||
m_mapFiles[sFilename] = pFile;
|
||||
|
||||
return pFile;
|
||||
}
|
||||
|
||||
template<>
|
||||
vfs::TSubDir<vfs::IWritable>::tFileType* vfs::TSubDir<vfs::IWritable>::addFile(vfs::Path const& sFilename, bool bDeleteOldFile)
|
||||
{
|
||||
tFileType* pFile = m_mapFiles[sFilename];
|
||||
if(pFile)
|
||||
{
|
||||
if(!bDeleteOldFile)
|
||||
{
|
||||
// not allowed to replace old file
|
||||
return NULL;
|
||||
}
|
||||
delete pFile;
|
||||
}
|
||||
pFile = new vfs::CDirFile(sFilename,this);
|
||||
m_mapFiles[sFilename] = pFile;
|
||||
|
||||
return pFile;
|
||||
}
|
||||
|
||||
template<typename WriteType>
|
||||
bool vfs::TSubDir<WriteType>::addFile(tFileType* pFile, bool bDeleteOldFile)
|
||||
{
|
||||
if(!pFile)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
tFileType* pOldFile = m_mapFiles[pFile->getName()];
|
||||
if( pOldFile && (pOldFile != pFile) )
|
||||
{
|
||||
if(bDeleteOldFile)
|
||||
{
|
||||
pOldFile->close();
|
||||
delete pOldFile;
|
||||
}
|
||||
}
|
||||
m_mapFiles[pFile->getName()] = pFile;
|
||||
return true;
|
||||
}
|
||||
|
||||
template<>
|
||||
bool vfs::TSubDir<vfs::IWritable>::deleteDirectory(vfs::Path const& sDirPath)
|
||||
{
|
||||
if( !(this->m_mountPoint == 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->deleteFile())
|
||||
{
|
||||
VFS_THROW( ERROR_FILE(L"Could not delete file") );
|
||||
}
|
||||
delete pFile;
|
||||
}
|
||||
}
|
||||
m_mapFiles.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
template<>
|
||||
bool vfs::TSubDir<vfs::IWriteType>::deleteDirectory(vfs::Path const& sDirPath)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
template<>
|
||||
bool vfs::TSubDir<vfs::IWritable>::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();
|
||||
VFS_THROW_IFF(pFile->deleteFile(), ERROR_FILE(L"Could not delete file"));
|
||||
delete pFile;
|
||||
}
|
||||
m_mapFiles.erase(it);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template<>
|
||||
bool vfs::TSubDir<vfs::IWriteType>::deleteFileFromDirectory(vfs::Path const& rFileName)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename WriteType>
|
||||
bool vfs::TSubDir<WriteType>::createSubDirectory(vfs::Path const& sSubDirPath)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename WriteType>
|
||||
void vfs::TSubDir<WriteType>::getSubDirList(std::list<vfs::Path>& rlSubDirs)
|
||||
{
|
||||
}
|
||||
|
||||
template<typename WriteType>
|
||||
typename vfs::TSubDir<WriteType>::Iterator vfs::TSubDir<WriteType>::begin()
|
||||
{
|
||||
return Iterator(new IterImpl(this));
|
||||
}
|
||||
|
||||
/********************************************************************************************/
|
||||
/********************************************************************************************/
|
||||
/********************************************************************************************/
|
||||
|
||||
template<typename WriteType>
|
||||
class vfs::TDirectoryTree<WriteType>::IterImpl : public vfs::IBaseLocation::Iterator::IImplementation
|
||||
{
|
||||
typedef vfs::IBaseLocation::Iterator::IImplementation tBaseClass;
|
||||
typedef vfs::TDirectoryTree<WriteType> tDirTree;
|
||||
public:
|
||||
IterImpl(tDirTree& tree);
|
||||
virtual ~IterImpl();
|
||||
|
||||
virtual typename tDirTree::tFileType* value();
|
||||
virtual void next();
|
||||
protected:
|
||||
virtual tBaseClass* clone()
|
||||
{
|
||||
IterImpl* iter = new IterImpl(_tree);
|
||||
iter->_subdir_iter = _subdir_iter;
|
||||
iter->_file_iter = _file_iter;
|
||||
return iter;
|
||||
}
|
||||
private:
|
||||
void operator=(typename vfs::TDirectoryTree<WriteType>::IterImpl const& tree);
|
||||
tDirTree& _tree;
|
||||
typename tDirTree::tDirCatalogue::iterator _subdir_iter;
|
||||
typename tDirTree::tLocationType::Iterator _file_iter;
|
||||
};
|
||||
|
||||
template<typename WriteType>
|
||||
vfs::TDirectoryTree<WriteType>::IterImpl::IterImpl(vfs::TDirectoryTree<WriteType>& tree)
|
||||
: tBaseClass(), _tree(tree)
|
||||
{
|
||||
_subdir_iter = _tree.m_catDirs.begin();
|
||||
if(_subdir_iter != _tree.m_catDirs.end())
|
||||
{
|
||||
TSubDir<WriteType> *sdir = dynamic_cast<TSubDir<WriteType>*>(_subdir_iter->second);
|
||||
typename TSubDir<WriteType>::Iterator it = sdir->begin();
|
||||
_file_iter = it;
|
||||
if(_file_iter.end())
|
||||
{
|
||||
next();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename WriteType>
|
||||
vfs::TDirectoryTree<WriteType>::IterImpl::~IterImpl()
|
||||
{
|
||||
}
|
||||
|
||||
template<typename WriteType>
|
||||
typename vfs::TDirectoryTree<WriteType>::tFileType* vfs::TDirectoryTree<WriteType>::IterImpl::value()
|
||||
{
|
||||
if(!_file_iter.end())
|
||||
{
|
||||
return static_cast<typename vfs::TDirectoryTree<WriteType>::tFileType*>(_file_iter.value());
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
template<typename WriteType>
|
||||
void vfs::TDirectoryTree<WriteType>::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;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
template<typename WriteType>
|
||||
vfs::TDirectoryTree<WriteType>::TDirectoryTree(vfs::Path const& sMountPoint, vfs::Path const& sRealPath)
|
||||
: tBaseClass(sMountPoint,sRealPath)
|
||||
{};
|
||||
|
||||
|
||||
template<typename WriteType>
|
||||
vfs::TDirectoryTree<WriteType>::~TDirectoryTree()
|
||||
{
|
||||
typename tDirCatalogue::iterator it = m_catDirs.begin();
|
||||
for(;it != m_catDirs.end(); ++it)
|
||||
{
|
||||
delete it->second;
|
||||
it->second = NULL;
|
||||
}
|
||||
m_catDirs.clear();
|
||||
}
|
||||
|
||||
template<typename WriteType>
|
||||
bool vfs::TDirectoryTree<WriteType>::init()
|
||||
{
|
||||
// contains local path
|
||||
typedef vfs::TSubDir<WriteType> tSubDir;
|
||||
typedef std::pair<vfs::Path,tSubDir*> tDirs;
|
||||
std::queue<tDirs> qSubDirs;
|
||||
qSubDirs.push(tDirs(vfs::Path(vfs::Const::EMPTY()),new tSubDir(this->m_mountPoint, this->m_realPath)));
|
||||
|
||||
m_catDirs[this->m_mountPoint] = qSubDirs.front().second;
|
||||
|
||||
vfs::String sFilename;
|
||||
tSubDir *pCurrentDir;
|
||||
vfs::Path oCurDir;
|
||||
while(!qSubDirs.empty())
|
||||
{
|
||||
pCurrentDir = qSubDirs.front().second;
|
||||
oCurDir = this->m_realPath;
|
||||
if( !qSubDirs.front().first.empty())
|
||||
{
|
||||
oCurDir += qSubDirs.front().first;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
vfs::OS::CIterateDirectory::EFileAttribute eFA;
|
||||
vfs::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 == vfs::OS::CIterateDirectory::FA_DIRECTORY)
|
||||
{
|
||||
vfs::Path sLocal = qSubDirs.front().first + sFilename;
|
||||
|
||||
vfs::Path temp = this->m_mountPoint+sLocal;
|
||||
tSubDir *pNewDir = new tSubDir(sLocal, this->m_realPath+sLocal);
|
||||
qSubDirs.push(tDirs(sLocal,pNewDir));
|
||||
m_catDirs[temp] = pNewDir;
|
||||
}
|
||||
else
|
||||
{
|
||||
pCurrentDir->addFile(vfs::Path(sFilename));
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(std::exception &ex)
|
||||
{
|
||||
// probably directory doesn't exist. abort or continue???
|
||||
// -> abort AND continue
|
||||
VFS_LOG_WARNING(ex.what());
|
||||
return false;
|
||||
}
|
||||
qSubDirs.pop();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename WriteType>
|
||||
typename vfs::TDirectoryTree<WriteType>::tFileType* vfs::TDirectoryTree<WriteType>::addFile(vfs::Path const& sFilename, bool bDeleteOldFile)
|
||||
{
|
||||
vfs::Path sDir,sFile;
|
||||
sFilename.splitLast(sDir,sFile);
|
||||
typename tDirCatalogue::iterator it = m_catDirs.find(sDir);
|
||||
if(it == m_catDirs.end())
|
||||
{
|
||||
vfs::Path sTemp,sCreateDir,sLeft,sRight = sDir;
|
||||
while(!sRight.empty())
|
||||
{
|
||||
sRight.splitFirst(sLeft,sTemp);
|
||||
sRight = sTemp;
|
||||
sCreateDir += sLeft;
|
||||
if(!this->createSubDirectory(sCreateDir))
|
||||
{
|
||||
VFS_THROW(_BS(L"could not create directory : ") << sCreateDir << _BS::wget);
|
||||
}
|
||||
}
|
||||
it = m_catDirs.find(sDir);
|
||||
if(it == m_catDirs.end())
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if(it->second)
|
||||
{
|
||||
return it->second->addFile(sFile,bDeleteOldFile);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
template<typename WriteType>
|
||||
bool vfs::TDirectoryTree<WriteType>::addFile(tFileType* pFile, bool bDeleteOldFile)
|
||||
{
|
||||
// no files from outside
|
||||
// these files are not connected with the correct directory object
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename WriteType>
|
||||
bool vfs::TDirectoryTree<WriteType>::deleteDirectory(vfs::Path const& sDirPath)
|
||||
{
|
||||
typename 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;
|
||||
}
|
||||
|
||||
template<typename WriteType>
|
||||
bool vfs::TDirectoryTree<WriteType>::deleteFileFromDirectory(vfs::Path const& sFileName)
|
||||
{
|
||||
vfs::Path sDir,sFile;
|
||||
sFileName.splitLast(sDir,sFile);
|
||||
typename 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
|
||||
*/
|
||||
template<typename WriteType>
|
||||
bool vfs::TDirectoryTree<WriteType>::fileExists(vfs::Path const& sFileName)
|
||||
{
|
||||
vfs::Path sDir, sFile;
|
||||
sFileName.splitLast(sDir, sFile);
|
||||
typename tDirCatalogue::iterator it = m_catDirs.find(sDir);
|
||||
if(it == m_catDirs.end())
|
||||
{
|
||||
// no such directory
|
||||
return false;
|
||||
}
|
||||
if(it->second)
|
||||
{
|
||||
return it->second->fileExists(sFile);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename WriteType>
|
||||
vfs::IBaseFile* vfs::TDirectoryTree<WriteType>::getFile(vfs::Path const& sFileName)
|
||||
{
|
||||
return getFileTyped(sFileName);
|
||||
}
|
||||
|
||||
template<typename WriteType>
|
||||
typename vfs::TDirectoryTree<WriteType>::tFileType* vfs::TDirectoryTree<WriteType>::getFileTyped(vfs::Path const& sFileName)
|
||||
{
|
||||
vfs::Path sDir, sFile;
|
||||
sFileName.splitLast(sDir, sFile);
|
||||
typename tDirCatalogue::iterator it = m_catDirs.find(sDir);
|
||||
if(it == m_catDirs.end())
|
||||
{
|
||||
// no such directory
|
||||
return NULL;
|
||||
}
|
||||
if(it->second)
|
||||
{
|
||||
return it->second->getFileTyped(sFile);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
template<typename WriteType>
|
||||
bool vfs::TDirectoryTree<WriteType>::createSubDirectory(vfs::Path const& sSubDirPath)
|
||||
{
|
||||
if(vfs::OS::createRealDirectory( this->m_realPath + sSubDirPath ))
|
||||
{
|
||||
if( m_catDirs[sSubDirPath] == NULL)
|
||||
{
|
||||
m_catDirs[sSubDirPath] = new vfs::TSubDir<WriteType>(sSubDirPath, this->m_realPath + sSubDirPath);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename WriteType>
|
||||
void vfs::TDirectoryTree<WriteType>::getSubDirList(std::list<vfs::Path>& rlSubDirs)
|
||||
{
|
||||
typename tDirCatalogue::iterator it = m_catDirs.begin();
|
||||
for(;it != m_catDirs.end(); ++it)
|
||||
{
|
||||
rlSubDirs.push_back(it->first);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename WriteType>
|
||||
typename vfs::TDirectoryTree<WriteType>::Iterator vfs::TDirectoryTree<WriteType>::begin()
|
||||
{
|
||||
return Iterator(new IterImpl(*this));
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
template class vfs::TDirectoryTree<vfs::IWritable>; // explicit template class instantiation
|
||||
template class vfs::TDirectoryTree<vfs::IWriteType>; // explicit template class instantiation
|
||||
|
||||
@@ -0,0 +1,199 @@
|
||||
/*
|
||||
* bfVFS : vfs/Core/Location/vfs_lib_dir.cpp
|
||||
* - class for readonly (sub)directories in archives/libraries
|
||||
*
|
||||
* Copyright (C) 2008 - 2010 (BF) john.bf.smith@googlemail.com
|
||||
*
|
||||
* This file is part of the bfVFS library
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <vfs/Core/Location/vfs_lib_dir.h>
|
||||
#include <vfs/Tools/vfs_log.h>
|
||||
|
||||
class vfs::CLibDirectory::IterImpl : public vfs::IBaseLocation::Iterator::IImplementation
|
||||
{
|
||||
typedef vfs::IBaseLocation::Iterator::IImplementation tBaseClass;
|
||||
public:
|
||||
IterImpl(CLibDirectory& lib);
|
||||
virtual ~IterImpl();
|
||||
virtual vfs::CLibDirectory::tFileType* value();
|
||||
virtual void next();
|
||||
protected:
|
||||
virtual tBaseClass* clone();
|
||||
private:
|
||||
void operator=(vfs::CLibDirectory::IterImpl const& iter);
|
||||
|
||||
vfs::CLibDirectory& _lib;
|
||||
vfs::CLibDirectory::tFileCatalogue::iterator _iter;
|
||||
};
|
||||
|
||||
vfs::CLibDirectory::IterImpl::IterImpl(CLibDirectory& lib)
|
||||
: tBaseClass(), _lib(lib)
|
||||
{
|
||||
_iter = _lib.m_files.begin();
|
||||
}
|
||||
|
||||
vfs::CLibDirectory::IterImpl::~IterImpl()
|
||||
{
|
||||
}
|
||||
|
||||
vfs::CLibDirectory::tFileType* vfs::CLibDirectory::IterImpl::value()
|
||||
{
|
||||
if(_iter != _lib.m_files.end())
|
||||
{
|
||||
return _iter->second;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void vfs::CLibDirectory::IterImpl::next()
|
||||
{
|
||||
if(_iter != _lib.m_files.end())
|
||||
{
|
||||
_iter++;
|
||||
}
|
||||
}
|
||||
|
||||
vfs::CLibDirectory::IterImpl::tBaseClass* vfs::CLibDirectory::IterImpl::clone()
|
||||
{
|
||||
IterImpl* iter = new IterImpl(_lib);
|
||||
iter->_iter = _iter;
|
||||
return iter;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/***************************************************************************/
|
||||
|
||||
vfs::CLibDirectory::CLibDirectory(vfs::Path const& sLocalPath, vfs::Path const& sRealPath)
|
||||
: tBaseClass(sLocalPath,sRealPath)
|
||||
{
|
||||
}
|
||||
|
||||
vfs::CLibDirectory::~CLibDirectory()
|
||||
{
|
||||
tFileCatalogue::iterator it = m_files.begin();
|
||||
for(; it != m_files.end(); ++it)
|
||||
{
|
||||
// don't delete objects here
|
||||
//delete it->second;
|
||||
}
|
||||
m_files.clear();
|
||||
}
|
||||
|
||||
vfs::CLibDirectory::tFileType* vfs::CLibDirectory::addFile(vfs::Path const& filename, bool deleteOldFile)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool vfs::CLibDirectory::addFile(tFileType* file, bool deleteOldFile)
|
||||
{
|
||||
if(!file)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
vfs::Path const& name = file->getName();
|
||||
tFileType* oldFile = m_files[name];
|
||||
if(oldFile && (oldFile != file) )
|
||||
{
|
||||
if(deleteOldFile)
|
||||
{
|
||||
delete oldFile;
|
||||
m_files[name] = file;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
m_files[name] = file;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool vfs::CLibDirectory::deleteDirectory(vfs::Path const& dirPath)
|
||||
{
|
||||
//if( !(m_mountPoint == dirPath) )
|
||||
//{
|
||||
// return false;
|
||||
//}
|
||||
//if(implementsWritable())
|
||||
//{
|
||||
// tFileCatalogue::iterator it = m_files.begin();
|
||||
// for(; it != m_files.end(); ++it)
|
||||
// {
|
||||
// //delete it->second;
|
||||
// }
|
||||
// m_files.clear();
|
||||
// return true;
|
||||
//}
|
||||
VFS_LOG_ERROR(L"called 'deleteDirectory', 'vfs::CLibDirectory' doesn't implement the IWritable interface");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool vfs::CLibDirectory::deleteFileFromDirectory(vfs::Path const& filename)
|
||||
{
|
||||
//if(implementsWritable())
|
||||
//{
|
||||
// tFileCatalogue::iterator it = m_files.find(filename);
|
||||
// if(it != m_files.end())
|
||||
// {
|
||||
// delete it->second;
|
||||
// m_files.erase(it);
|
||||
// return true;
|
||||
// }
|
||||
//}
|
||||
VFS_LOG_ERROR(L"called 'deleteFileFromDirectory', 'vfs::CLibDirectory' doesn't implement the IWritable interface");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool vfs::CLibDirectory::fileExists(vfs::Path const& filename)
|
||||
{
|
||||
return (m_files[filename] != NULL);
|
||||
}
|
||||
|
||||
vfs::IBaseFile* vfs::CLibDirectory::getFile(vfs::Path const& filename)
|
||||
{
|
||||
return getFileTyped(filename);
|
||||
}
|
||||
|
||||
vfs::CLibDirectory::tFileType* vfs::CLibDirectory::getFileTyped(vfs::Path const& filename)
|
||||
{
|
||||
tFileCatalogue::iterator it = m_files.find(filename);
|
||||
if(it != m_files.end())
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool vfs::CLibDirectory::createSubDirectory(vfs::Path const& subDirPath)
|
||||
{
|
||||
// libraries are readonly
|
||||
return false;
|
||||
}
|
||||
|
||||
void vfs::CLibDirectory::getSubDirList(std::list<vfs::Path>& rlSubDirs)
|
||||
{
|
||||
// nothing
|
||||
}
|
||||
|
||||
vfs::CLibDirectory::Iterator vfs::CLibDirectory::begin()
|
||||
{
|
||||
return Iterator(new IterImpl(*this));
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/***************************************************************************/
|
||||
@@ -0,0 +1,320 @@
|
||||
/*
|
||||
* bfVFS : vfs/Core/Location/vfs_uncompressed_lib_base.cpp
|
||||
* - partially implements library interface for uncompressed archive files
|
||||
* - initialization is done in format-specific sub-classes
|
||||
*
|
||||
* Copyright (C) 2008 - 2010 (BF) john.bf.smith@googlemail.com
|
||||
*
|
||||
* This file is part of the bfVFS library
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <vfs/Core/Location/vfs_uncompressed_lib_base.h>
|
||||
|
||||
/********************************************************************************************/
|
||||
vfs::CUncompressedLibraryBase::SFileData& vfs::CUncompressedLibraryBase::_fileDataFromHandle(tFileType* handle)
|
||||
{
|
||||
tFileData::iterator it = m_fileData.find(handle);
|
||||
if(it != m_fileData.end())
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
VFS_THROW(L"Invalid file handle");
|
||||
}
|
||||
/********************************************************************************************/
|
||||
/********************************************************************************************/
|
||||
|
||||
class vfs::CUncompressedLibraryBase::IterImpl : public vfs::IBaseLocation::Iterator::IImplementation
|
||||
{
|
||||
typedef vfs::IBaseLocation::Iterator::IImplementation tBaseClass;
|
||||
public:
|
||||
IterImpl(CUncompressedLibraryBase& lib);
|
||||
virtual ~IterImpl();
|
||||
virtual tFileType* value();
|
||||
virtual void next();
|
||||
protected:
|
||||
virtual tBaseClass* clone()
|
||||
{
|
||||
IterImpl* iter = new IterImpl(*_lib);
|
||||
iter->_iter = _iter;
|
||||
return iter;
|
||||
}
|
||||
private:
|
||||
vfs::CUncompressedLibraryBase* _lib;
|
||||
vfs::CUncompressedLibraryBase::tFileData::iterator _iter;
|
||||
};
|
||||
|
||||
|
||||
vfs::CUncompressedLibraryBase::IterImpl::IterImpl(vfs::CUncompressedLibraryBase &lib)
|
||||
: tBaseClass(), _lib(&lib)
|
||||
{
|
||||
_iter = _lib->m_fileData.begin();
|
||||
}
|
||||
vfs::CUncompressedLibraryBase::IterImpl::~IterImpl()
|
||||
{
|
||||
}
|
||||
|
||||
vfs::CUncompressedLibraryBase::tFileType* vfs::CUncompressedLibraryBase::IterImpl::value()
|
||||
{
|
||||
if(_iter != _lib->m_fileData.end())
|
||||
{
|
||||
return _iter->first;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void vfs::CUncompressedLibraryBase::IterImpl::next()
|
||||
{
|
||||
if(_iter != _lib->m_fileData.end())
|
||||
{
|
||||
_iter++;
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/************************************************************************/
|
||||
|
||||
vfs::CUncompressedLibraryBase::CUncompressedLibraryBase(vfs::tReadableFile *libraryFile, vfs::Path const& mountPoint, bool ownFile)
|
||||
: vfs::ILibrary(libraryFile,mountPoint,ownFile), m_numberOfOpenedFiles(0)
|
||||
{
|
||||
}
|
||||
|
||||
vfs::CUncompressedLibraryBase::~CUncompressedLibraryBase()
|
||||
{
|
||||
this->closeLibrary();
|
||||
// delete sub dirs from catalogue
|
||||
tDirCatalogue::iterator it = m_dirs.begin();
|
||||
for(; it != m_dirs.end(); ++it)
|
||||
{
|
||||
delete it->second;
|
||||
}
|
||||
// LibData is invalid
|
||||
// just clear it, since the file handles were deleted before
|
||||
m_fileData.clear();
|
||||
m_dirs.clear();
|
||||
}
|
||||
|
||||
void vfs::CUncompressedLibraryBase::closeLibrary()
|
||||
{
|
||||
tFileData::iterator it = m_fileData.begin();
|
||||
for(; it != m_fileData .end(); ++it)
|
||||
{
|
||||
// what if closing of (at least) one file fails?? continue or not??
|
||||
// in the end, these are not real files!
|
||||
VFS_IGNOREEXCEPTION(it->first->close(), true);
|
||||
}
|
||||
}
|
||||
|
||||
bool vfs::CUncompressedLibraryBase::fileExists(vfs::Path const& filename)
|
||||
{
|
||||
vfs::Path sDir,sFile;
|
||||
filename.splitLast(sDir,sFile);
|
||||
tDirCatalogue::iterator it = m_dirs.find(sDir);
|
||||
if(it != m_dirs.end())
|
||||
{
|
||||
return it->second->fileExists(sFile);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
vfs::IBaseFile* vfs::CUncompressedLibraryBase::getFile(vfs::Path const& filename)
|
||||
{
|
||||
return getFileTyped(filename);
|
||||
}
|
||||
|
||||
vfs::CUncompressedLibraryBase::tFileType* vfs::CUncompressedLibraryBase::getFileTyped(vfs::Path const& filename)
|
||||
{
|
||||
vfs::Path sDir,sFile;
|
||||
filename.splitLast(sDir,sFile);
|
||||
tDirCatalogue::iterator it = m_dirs.find(sDir);
|
||||
if(it != m_dirs.end())
|
||||
{
|
||||
return it->second->getFileTyped(sFile);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void vfs::CUncompressedLibraryBase::close(tFileType *fileHandle)
|
||||
{
|
||||
try
|
||||
{
|
||||
SFileData& file = _fileDataFromHandle(fileHandle);
|
||||
|
||||
// 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
|
||||
file._currentReadPosition = 0;
|
||||
if(m_numberOfOpenedFiles > 0)
|
||||
{
|
||||
m_numberOfOpenedFiles--;
|
||||
if(m_numberOfOpenedFiles == 0)
|
||||
{
|
||||
m_libraryFile->close();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(std::exception& ex)
|
||||
{
|
||||
VFS_RETHROW(L"", ex);
|
||||
}
|
||||
}
|
||||
bool vfs::CUncompressedLibraryBase::openRead(tFileType *fileHandle)
|
||||
{
|
||||
try
|
||||
{
|
||||
_fileDataFromHandle(fileHandle);
|
||||
}
|
||||
catch(std::exception& ex)
|
||||
{
|
||||
VFS_RETHROW(L"", ex);
|
||||
}
|
||||
|
||||
m_numberOfOpenedFiles++;
|
||||
if(m_numberOfOpenedFiles == 1)
|
||||
{
|
||||
if(!m_libraryFile->isOpenRead() && !m_libraryFile->openRead())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// already open
|
||||
return true;
|
||||
}
|
||||
|
||||
vfs::size_t vfs::CUncompressedLibraryBase::read(tFileType *fileHandle, vfs::Byte* data, vfs::size_t bytesToRead)
|
||||
{
|
||||
try
|
||||
{
|
||||
SFileData& file = _fileDataFromHandle(fileHandle);
|
||||
|
||||
if( (file._currentReadPosition + bytesToRead) > file._fileSize )
|
||||
{
|
||||
bytesToRead = file._fileSize - file._currentReadPosition;
|
||||
}
|
||||
if(bytesToRead == 0)
|
||||
{
|
||||
// eof
|
||||
return 0;
|
||||
}
|
||||
// set lib-file's read-location to match location of lib-file
|
||||
m_libraryFile->setReadPosition(file._fileOffset + file._currentReadPosition, IBaseFile::SD_BEGIN);
|
||||
|
||||
vfs::size_t bytesRead = m_libraryFile->read(data, bytesToRead);
|
||||
VFS_THROW_IFF( bytesToRead == bytesRead, L"Number of bytes doesn't match" );
|
||||
file._currentReadPosition += bytesRead;
|
||||
return bytesRead;
|
||||
}
|
||||
catch(std::exception& ex)
|
||||
{
|
||||
VFS_RETHROW(L"", ex);
|
||||
}
|
||||
}
|
||||
|
||||
vfs::size_t vfs::CUncompressedLibraryBase::getReadPosition(tFileType *fileHandle)
|
||||
{
|
||||
try
|
||||
{
|
||||
return _fileDataFromHandle(fileHandle)._currentReadPosition;
|
||||
}
|
||||
catch(std::exception& ex)
|
||||
{
|
||||
VFS_RETHROW(L"", ex);
|
||||
}
|
||||
}
|
||||
|
||||
void vfs::CUncompressedLibraryBase::setReadPosition(tFileType *fileHandle, vfs::size_t positionInBytes)
|
||||
{
|
||||
try
|
||||
{
|
||||
SFileData& file = _fileDataFromHandle(fileHandle);
|
||||
if( positionInBytes > file._fileSize )
|
||||
{
|
||||
positionInBytes = file._fileSize;
|
||||
}
|
||||
|
||||
// positionInBytes is offset to file-offset
|
||||
file._currentReadPosition = positionInBytes;
|
||||
}
|
||||
catch(std::exception& ex)
|
||||
{
|
||||
VFS_RETHROW(L"", ex);
|
||||
}
|
||||
}
|
||||
|
||||
static inline vfs::offset_t clampReadPosition(vfs::offset_t const& off, vfs::size_t const& size)
|
||||
{
|
||||
return ( off < 0 ) ? ( 0 ) : ( (vfs::size_t)off > size ? size : off );
|
||||
}
|
||||
|
||||
void vfs::CUncompressedLibraryBase::setReadPosition(tFileType *fileHandle, vfs::offset_t offsetInBytes, IBaseFile::ESeekDir seekDir)
|
||||
{
|
||||
try
|
||||
{
|
||||
SFileData& file = _fileDataFromHandle(fileHandle);
|
||||
|
||||
if(seekDir == IBaseFile::SD_BEGIN)
|
||||
{
|
||||
file._currentReadPosition = clampReadPosition(offsetInBytes, file._fileSize);
|
||||
}
|
||||
else if(seekDir == IBaseFile::SD_CURRENT)
|
||||
{
|
||||
vfs::offset_t pos = file._currentReadPosition + offsetInBytes;
|
||||
file._currentReadPosition = clampReadPosition(pos, file._fileSize);
|
||||
}
|
||||
else if(seekDir == IBaseFile::SD_END)
|
||||
{
|
||||
vfs::offset_t pos = file._currentReadPosition + offsetInBytes;
|
||||
file._currentReadPosition = clampReadPosition(pos, file._fileSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
VFS_THROW(L"Unknown seek direction");
|
||||
}
|
||||
}
|
||||
catch(std::exception& ex)
|
||||
{
|
||||
VFS_RETHROW(L"", ex);
|
||||
}
|
||||
}
|
||||
|
||||
vfs::size_t vfs::CUncompressedLibraryBase::getSize(tFileType *fileHandle)
|
||||
{
|
||||
try
|
||||
{
|
||||
return _fileDataFromHandle(fileHandle)._fileSize;
|
||||
}
|
||||
catch(std::exception& ex)
|
||||
{
|
||||
VFS_RETHROW(L"", ex);
|
||||
}
|
||||
}
|
||||
|
||||
void vfs::CUncompressedLibraryBase::getSubDirList(std::list<vfs::Path>& rlSubDirs)
|
||||
{
|
||||
tDirCatalogue::iterator it = m_dirs.begin();
|
||||
for(;it != m_dirs.end(); ++it)
|
||||
{
|
||||
rlSubDirs.push_back(it->first);
|
||||
}
|
||||
}
|
||||
|
||||
vfs::CUncompressedLibraryBase::Iterator vfs::CUncompressedLibraryBase::begin()
|
||||
{
|
||||
return Iterator(new IterImpl(*this));
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user