Files
source/ext/VFS/src/Core/vfs_vfile.cpp
T

221 lines
5.4 KiB
C++

/*
* bfVFS : vfs/Core/vfs_vfile.cpp
* - Virtual File, handles access to files from different VFS profiles
*
* 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/vfs_vfile.h>
#include <vfs/Core/vfs_vloc.h>
#include <vfs/Core/vfs.h>
// static member
vfs::ObjBlockAllocator<vfs::CVirtualFile>* vfs::CVirtualFile::_vfile_pool = NULL;
vfs::CVirtualFile* vfs::CVirtualFile::create(vfs::Path const& sFilePath, vfs::CProfileStack& rPStack)
{
unsigned int ID=0;
#ifdef VFILE_BLOCK_CREATE
if(!_vfile_pool)
{
_vfile_pool = new ObjBlockAllocator<vfs::CVirtualFile>();
vfs::ObjectAllocator::registerAllocator(_vfile_pool);
}
CVirtualFile* file = _vfile_pool->New(&ID);
#else
CVirtualFile* file = new CVirtualFile();
#endif
file->_path = sFilePath;
file->_pstack = &rPStack;
file->_myID = ID;
return file;
}
void vfs::CVirtualFile::destroy()
{
#ifndef VFILE_BLOCK_CREATE
delete this;
#endif
}
vfs::CVirtualFile::CVirtualFile()
: _path(L""), _top_pname(L"_INVALID_"), _top_file(NULL), _pstack(NULL), _myID(vfs::UInt32(-1))
{
};
vfs::CVirtualFile::~CVirtualFile()
{
}
vfs::Path const& vfs::CVirtualFile::path()
{
return _path;
}
void vfs::CVirtualFile::add(vfs::IBaseFile *pFile, vfs::String sProfileName, bool bReplace)
{
if(pFile)
{
// if there is no file then just set it
// if bReplace is set to true then override all other settings and just set the file
if(!_top_file || bReplace)
{
_top_file = pFile;
_top_pname = sProfileName;
return;
}
// file already set, but new file is? the same object
if(pFile == _top_file)
{
VFS_THROW_IFF( StrCmp::Equal(sProfileName,_top_pname), L"same file, different profile name");
}
// OK, not the same file, but these two different files are supposed to have the same filename
VFS_THROW_IFF( _top_file->getName() == pFile->getName(), L"different filenames");
// set new file only when its profile is on top of the current file's profile
bool bFoundOld = false, bFoundNew = false;
vfs::CProfileStack::Iterator it = _pstack->begin();
for(; !it.end(); it.next())
{
if(_top_pname == it.value()->cName)
{
bFoundOld = true;
break;
}
else if(sProfileName == it.value()->cName)
{
bFoundNew = true;
break;
}
}
if(bFoundNew && !bFoundOld)
{
_top_file = pFile;
_top_pname = sProfileName;
}
}
}
/**
* @returns : returns true if pFile is not top file or top file could be replaced with another file
* returns false if there is no more files with given name. in this case object should be destroyed
*/
bool vfs::CVirtualFile::remove(vfs::IBaseFile *pFile)
{
if(_top_file == pFile)
{
if(_path == pFile->getPath())
{
// need to replace '_top_file'
vfs::CProfileStack::Iterator prof_it = _pstack->begin();
for(; !prof_it.end(); prof_it.next())
{
CVirtualProfile *pProf = prof_it.value();
if(pProf)
{
vfs::IBaseFile *file = pProf->getFile(_path);
if(file && (file != pFile))
{
_top_file = file;
_top_pname = pProf->cName;
return true;
}
}
}
// no more files
_top_file = NULL;
_top_pname = "";
return false;
}
else
{
VFS_THROW(L"Same file object but different file paths? WTH?");
}
}
return true;
}
vfs::IBaseFile* vfs::CVirtualFile::file(ESearchFile eSearch)
{
if(eSearch == SF_TOP)
{
return _top_file;
}
else if(eSearch == SF_FIRST_WRITABLE)
{
CVirtualProfile *pVProf = _pstack->getWriteProfile();
if(pVProf)
{
return pVProf->getFile(_path);
}
}
else if(eSearch == SF_STOP_ON_WRITABLE_PROFILE)
{
vfs::CProfileStack::Iterator prof_it = _pstack->begin();
for(; !prof_it.end(); prof_it.next())
{
CVirtualProfile *pProf = prof_it.value();
if(pProf)
{
if(pProf->cWritable)
{
return pProf->getFile(_path);
}
else
{
vfs::IBaseFile *pFile = pProf->getFile(_path);
if(pFile)
{
return pFile;
}
}
}
}
}
return NULL;
}
vfs::IBaseFile* vfs::CVirtualFile::file(vfs::String const& sProfileName)
{
if(sProfileName == _top_pname)
{
return vfs::tReadableFile::cast(_top_file);
}
else
{
CVirtualProfile* pProf = _pstack->getProfile(sProfileName);
if(pProf)
{
CVirtualProfile::Iterator loc_it = pProf->begin();
for(; !loc_it.end(); loc_it.next())
{
if(loc_it.value() && loc_it.value()->fileExists(_path))
{
if(loc_it.value())
{
return loc_it.value()->getFile(_path);
}
}
}
}
}
return NULL;
}