FIFE
2008.0
|
00001 /*************************************************************************** 00002 * Copyright (C) 2005-2008 by the FIFE team * 00003 * http://www.fifengine.de * 00004 * This file is part of FIFE. * 00005 * * 00006 * FIFE is free software; you can redistribute it and/or * 00007 * modify it under the terms of the GNU Lesser General Public * 00008 * License as published by the Free Software Foundation; either * 00009 * version 2.1 of the License, or (at your option) any later version. * 00010 * * 00011 * This library is distributed in the hope that it will be useful, * 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * 00014 * Lesser General Public License for more details. * 00015 * * 00016 * You should have received a copy of the GNU Lesser General Public * 00017 * License along with this library; if not, write to the * 00018 * Free Software Foundation, Inc., * 00019 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * 00020 ***************************************************************************/ 00021 00022 // Standard C++ library includes 00023 #include <algorithm> 00024 00025 // 3rd party library includes 00026 #include <boost/functional.hpp> 00027 #include <boost/regex.hpp> 00028 #include <boost/algorithm/string.hpp> 00029 00030 // FIFE includes 00031 // These includes are split up in two parts, separated by one empty line 00032 // First block: files included from the FIFE root src directory 00033 // Second block: files included from the same folder 00034 #include "vfs/raw/rawdata.h" 00035 #include "util/base/exception.h" 00036 #include "util/log/logger.h" 00037 00038 #include "vfs.h" 00039 #include "vfssource.h" 00040 #include "vfssourceprovider.h" 00041 00042 namespace FIFE { 00043 static Logger _log(LM_VFS); 00044 00045 00046 VFS::VFS() : m_sources() {} 00047 00048 VFS::~VFS() { 00049 cleanup(); 00050 } 00051 00052 void VFS::cleanup() { 00053 type_sources sources = m_sources; 00054 type_sources::const_iterator end = sources.end(); 00055 for (type_sources::iterator i = sources.begin(); i != end; ++i) 00056 delete *i; 00057 00058 type_providers::const_iterator end2 = m_providers.end(); 00059 for (type_providers::iterator j = m_providers.begin(); j != end2; ++j) 00060 delete *j; 00061 00062 m_providers.clear(); 00063 } 00064 00065 void VFS::addProvider(VFSSourceProvider* provider) { 00066 provider->setVFS(this); 00067 m_providers.push_back(provider); 00068 FL_LOG(_log, LMsg("new provider: ") << provider->getName()); 00069 } 00070 00071 VFSSource* VFS::createSource(const std::string& path) const { 00072 if ( m_usedfiles.count(path) ) { 00073 FL_WARN(_log, LMsg(path) << " is already used as VFS source"); 00074 return 0; 00075 } 00076 00077 type_providers::const_iterator end = m_providers.end(); 00078 for (type_providers::const_iterator i = m_providers.begin(); i != end; ++i) { 00079 const VFSSourceProvider* provider = *i; 00080 if (!provider->isReadable(path)) 00081 continue; 00082 00083 try { 00084 VFSSource* source = provider->createSource(path); 00085 m_usedfiles.insert(path); 00086 return source; 00087 } catch (const Exception& ex) { 00088 FL_WARN(_log, LMsg(provider->getName()) << " thought it could load " << path << " but didn't succeed (" << ex.what() << ")"); 00089 continue; 00090 } catch (...) { 00091 FL_WARN(_log, LMsg(provider->getName()) << " thought it could load " << path << " but didn't succeed (unkown exception)"); 00092 continue; 00093 } 00094 } 00095 00096 FL_WARN(_log, LMsg("no provider for ") << path << " found"); 00097 return 0; 00098 } 00099 00100 void VFS::addNewSource(const std::string& path) { 00101 VFSSource* source = createSource(path); 00102 if (source) { 00103 addSource(source); 00104 } else { 00105 FL_WARN(_log, LMsg("Failed to add new VFS source: ") << path); 00106 } 00107 } 00108 00109 void VFS::addSource(VFSSource* source) { 00110 m_sources.push_back(source); 00111 } 00112 00113 void VFS::removeSource(VFSSource* source) { 00114 type_sources::iterator i = std::find(m_sources.begin(), m_sources.end(), source); 00115 if (i != m_sources.end()) 00116 m_sources.erase(i); 00117 } 00118 00119 VFSSource* VFS::getSourceForFile(const std::string& file) const { 00120 type_sources::const_iterator i = std::find_if(m_sources.begin(), m_sources.end(), 00121 boost::bind2nd(boost::mem_fun(&VFSSource::fileExists), file)); 00122 if (i == m_sources.end()) { 00123 FL_WARN(_log, LMsg("no source for ") << file << " found"); 00124 return 0; 00125 } 00126 00127 return *i; 00128 } 00129 00130 bool VFS::exists(const std::string& file) const { 00131 return getSourceForFile(file); 00132 } 00133 00134 bool VFS::isDirectory(const std::string& path) const { 00135 std::vector<std::string> tokens; 00136 // Add a slash in case there isn't one in the string 00137 const std::string newpath = path + "/"; 00138 boost::algorithm::split(tokens, newpath, boost::algorithm::is_any_of("/")); 00139 00140 std::string currentpath = "/"; 00141 std::vector<std::string>::const_iterator token=tokens.begin(); 00142 while (token != tokens.end()) { 00143 if (*token != "") { 00144 if (*token != "." && *token != ".." && listDirectories(currentpath, *token).size() == 0) { 00145 return false; 00146 } else { 00147 currentpath += *token + "/"; 00148 } 00149 } 00150 token++; 00151 } 00152 00153 return true; 00154 } 00155 00156 RawData* VFS::open(const std::string& path) { 00157 FL_DBG(_log, LMsg("Opening: ") << path); 00158 00159 VFSSource* source = getSourceForFile(path); 00160 if (!source) 00161 throw NotFound(path); 00162 00163 return source->open(path); 00164 } 00165 00166 std::set<std::string> VFS::listFiles(const std::string& pathstr) const { 00167 std::set<std::string> list; 00168 type_sources::const_iterator end = m_sources.end(); 00169 for (type_sources::const_iterator i = m_sources.begin(); i != end; ++i) { 00170 std::set<std::string> sourcelist = (*i)->listFiles(pathstr); 00171 list.insert(sourcelist.begin(), sourcelist.end()); 00172 } 00173 00174 return list; 00175 } 00176 00177 std::set<std::string> VFS::listFiles(const std::string& path, const std::string& filterregex) const { 00178 std::set<std::string> list = listFiles(path); 00179 return filterList(list, filterregex); 00180 } 00181 00182 std::set<std::string> VFS::listDirectories(const std::string& pathstr) const { 00183 std::set<std::string> list; 00184 type_sources::const_iterator end = m_sources.end(); 00185 for (type_sources::const_iterator i = m_sources.begin(); i != end; ++i) { 00186 std::set<std::string> sourcelist = (*i)->listDirectories(pathstr); 00187 list.insert(sourcelist.begin(), sourcelist.end()); 00188 } 00189 00190 return list; 00191 } 00192 00193 std::set<std::string> VFS::listDirectories(const std::string& path, const std::string& filterregex) const { 00194 std::set<std::string> list = listDirectories(path); 00195 return filterList(list, filterregex); 00196 } 00197 00198 std::set<std::string> VFS::filterList(const std::set<std::string>& list, const std::string& fregex) const { 00199 std::set<std::string> results; 00200 boost::regex regex(fregex); 00201 std::set<std::string>::const_iterator end = list.end(); 00202 for (std::set<std::string>::const_iterator i = list.begin(); i != end;) { 00203 boost::cmatch match; 00204 if (boost::regex_match((*i).c_str(), match, regex)) { 00205 results.insert(*i); 00206 } 00207 ++i; 00208 } 00209 return results; 00210 } 00211 }