/* * 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 #include #include // static member vfs::ObjBlockAllocator* 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::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; }