FIFE
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
vfs.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * Copyright (C) 2005-2013 by the FIFE team *
3  * http://www.fifengine.net *
4  * This file is part of FIFE. *
5  * *
6  * FIFE is free software; you can redistribute it and/or *
7  * modify it under the terms of the GNU Lesser General Public *
8  * License as published by the Free Software Foundation; either *
9  * version 2.1 of the License, or (at your option) any later version. *
10  * *
11  * This library is distributed in the hope that it will be useful, *
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
14  * Lesser General Public License for more details. *
15  * *
16  * You should have received a copy of the GNU Lesser General Public *
17  * License along with this library; if not, write to the *
18  * Free Software Foundation, Inc., *
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
20  ***************************************************************************/
21 
22 // Standard C++ library includes
23 #include <algorithm>
24 
25 // 3rd party library includes
26 #include <boost/functional.hpp>
27 #include <boost/regex.hpp>
28 #include <boost/algorithm/string.hpp>
29 
30 // FIFE includes
31 // These includes are split up in two parts, separated by one empty line
32 // First block: files included from the FIFE root src directory
33 // Second block: files included from the same folder
34 #include "util/base/exception.h"
35 #include "util/log/logger.h"
36 
37 #include "vfs.h"
38 #include "vfssource.h"
39 #include "vfssourceprovider.h"
40 
41 namespace FIFE {
45  static Logger _log(LM_VFS);
46 
47  VFS::VFS() : m_sources() {}
48 
50  cleanup();
51  }
52 
53  void VFS::cleanup() {
54  type_sources sources = m_sources;
55  type_sources::const_iterator end = sources.end();
56  for (type_sources::iterator i = sources.begin(); i != end; ++i)
57  delete *i;
58 
59  type_providers::const_iterator end2 = m_providers.end();
60  for (type_providers::iterator j = m_providers.begin(); j != end2; ++j)
61  delete *j;
62 
63  m_providers.clear();
64  }
65 
67  provider->setVFS(this);
68  m_providers.push_back(provider);
69  FL_LOG(_log, LMsg("new provider: ") << provider->getName());
70  }
71 
72  VFSSource* VFS::createSource(const std::string& path) const {
73  if ( m_usedfiles.count(path) ) {
74  FL_WARN(_log, LMsg(path) << " is already used as VFS source");
75  return 0;
76  }
77 
78  type_providers::const_iterator end = m_providers.end();
79  for (type_providers::const_iterator i = m_providers.begin(); i != end; ++i) {
80  const VFSSourceProvider* provider = *i;
81  if (!provider->isReadable(path))
82  continue;
83 
84  try {
85  VFSSource* source = provider->createSource(path);
86  m_usedfiles.insert(path);
87  return source;
88  } catch (const Exception& ex) {
89  FL_WARN(_log, LMsg(provider->getName()) << " thought it could load " << path << " but didn't succeed (" << ex.what() << ")");
90  continue;
91  } catch (...) {
92  FL_WARN(_log, LMsg(provider->getName()) << " thought it could load " << path << " but didn't succeed (unkown exception)");
93  continue;
94  }
95  }
96 
97  FL_WARN(_log, LMsg("no provider for ") << path << " found");
98  return 0;
99  }
100 
101  void VFS::addNewSource(const std::string& path) {
102  VFSSource* source = createSource(path);
103  if (source) {
104  addSource(source);
105  } else {
106  FL_WARN(_log, LMsg("Failed to add new VFS source: ") << path);
107  }
108  }
109 
110  void VFS::addSource(VFSSource* source) {
111  m_sources.push_back(source);
112  }
113 
114  void VFS::removeSource(VFSSource* source) {
115  type_sources::iterator i = std::find(m_sources.begin(), m_sources.end(), source);
116  if (i != m_sources.end())
117  m_sources.erase(i);
118  }
119 
120  VFSSource* VFS::getSourceForFile(const std::string& file) const {
121  type_sources::const_iterator i = std::find_if(m_sources.begin(), m_sources.end(),
122  boost::bind2nd(boost::mem_fun(&VFSSource::fileExists), file));
123  if (i == m_sources.end()) {
124  FL_WARN(_log, LMsg("no source for ") << file << " found");
125  return 0;
126  }
127 
128  return *i;
129  }
130 
131  bool VFS::exists(const std::string& file) const {
132  return getSourceForFile(file) != 0;
133  }
134 
135  bool VFS::isDirectory(const std::string& path) const {
136  std::vector<std::string> tokens;
137  // Add a slash in case there isn't one in the string
138  const std::string newpath = path + "/";
139  boost::algorithm::split(tokens, newpath, boost::algorithm::is_any_of("/"));
140 
141  std::string currentpath = "/";
142  std::vector<std::string>::const_iterator token=tokens.begin();
143  while (token != tokens.end()) {
144  if (*token != "") {
145  if (*token != "." && *token != ".." && listDirectories(currentpath, *token).size() == 0) {
146  return false;
147  } else {
148  currentpath += *token + "/";
149  }
150  }
151  token++;
152  }
153 
154  return true;
155  }
156 
157  RawData* VFS::open(const std::string& path) {
158  FL_DBG(_log, LMsg("Opening: ") << path);
159 
160  VFSSource* source = getSourceForFile(path);
161  if (!source)
162  throw NotFound(path);
163 
164  return source->open(path);
165  }
166 
167  std::set<std::string> VFS::listFiles(const std::string& pathstr) const {
168  std::set<std::string> list;
169  type_sources::const_iterator end = m_sources.end();
170  for (type_sources::const_iterator i = m_sources.begin(); i != end; ++i) {
171  std::set<std::string> sourcelist = (*i)->listFiles(pathstr);
172  list.insert(sourcelist.begin(), sourcelist.end());
173  }
174 
175  return list;
176  }
177 
178  std::set<std::string> VFS::listFiles(const std::string& path, const std::string& filterregex) const {
179  std::set<std::string> list = listFiles(path);
180  return filterList(list, filterregex);
181  }
182 
183  std::set<std::string> VFS::listDirectories(const std::string& pathstr) const {
184  std::set<std::string> list;
185  type_sources::const_iterator end = m_sources.end();
186  for (type_sources::const_iterator i = m_sources.begin(); i != end; ++i) {
187  std::set<std::string> sourcelist = (*i)->listDirectories(pathstr);
188  list.insert(sourcelist.begin(), sourcelist.end());
189  }
190 
191  return list;
192  }
193 
194  std::set<std::string> VFS::listDirectories(const std::string& path, const std::string& filterregex) const {
195  std::set<std::string> list = listDirectories(path);
196  return filterList(list, filterregex);
197  }
198 
199  std::set<std::string> VFS::filterList(const std::set<std::string>& list, const std::string& fregex) const {
200  std::set<std::string> results;
201  boost::regex regex(fregex);
202  std::set<std::string>::const_iterator end = list.end();
203  for (std::set<std::string>::const_iterator i = list.begin(); i != end;) {
204  boost::cmatch match;
205  if (boost::regex_match((*i).c_str(), match, regex)) {
206  results.insert(*i);
207  }
208  ++i;
209  }
210  return results;
211  }
212 }
#define FL_WARN(logger, msg)
Definition: logger.h:72
bool exists(const std::string &file) const
Check if the given file exists.
Definition: vfs.cpp:131
std::set< std::string > listFiles(const std::string &path) const
Get a filelist of the given directory.
Definition: vfs.cpp:167
void addProvider(VFSSourceProvider *provider)
add new VFSSourceProvider
Definition: vfs.cpp:66
virtual const char * what() const
Returns the error message.
Definition: exception.cpp:41
virtual bool fileExists(const std::string &file) const =0
check if the given file exists
Helper class to create log strings out from separate parts Usage: LMsg(&quot;some text&quot;) &lt;&lt; variable &lt;&lt; &quot;...
Definition: logger.h:82
VFSSource abstract baseclass.
Definition: vfssource.h:46
VFSSource * getSourceForFile(const std::string &file) const
Definition: vfs.cpp:120
const std::string & getName() const
Returns the name of this VFSSourceProvider.
RawData * open(const std::string &path)
Open a file.
Definition: vfs.cpp:157
virtual VFSSource * createSource(const std::string &file) const =0
Create a new instance of a VFSSource initialized with the given file.
static Logger _log(LM_AUDIO)
void cleanup()
Definition: vfs.cpp:53
Exception base class.
Definition: exception.h:43
virtual bool isReadable(const std::string &file) const =0
Check if a given file is readable for this VFSSource.
type_usedfiles m_usedfiles
Definition: vfs.h:162
VFSSource * createSource(const std::string &path) const
tries to create a new VFSSource for the given file
Definition: vfs.cpp:72
void removeSource(VFSSource *source)
remove a VFSSource
Definition: vfs.cpp:114
VFSSourceProvider abstract baseclass.
std::set< std::string > filterList(const std::set< std::string > &list, const std::string &fregex) const
Definition: vfs.cpp:199
void addSource(VFSSource *source)
Add a new VFSSource.
Definition: vfs.cpp:110
virtual ~VFS()
Destructor.
Definition: vfs.cpp:49
bool isDirectory(const std::string &path) const
Check if the given path is a directory.
Definition: vfs.cpp:135
VFS()
Constructor Called by the Engine on startup.
Definition: vfs.cpp:47
#define FL_LOG(logger, msg)
Definition: logger.h:71
Definition: modules.h:59
void addNewSource(const std::string &path)
create a new Source and add it to VFS
Definition: vfs.cpp:101
void setVFS(VFS *vfs)
Get the VFS this provider is using.
#define FL_DBG(logger, msg)
Definition: logger.h:70
type_providers m_providers
Definition: vfs.h:156
virtual RawData * open(const std::string &file) const =0
open a file inside this source
type_sources m_sources
Definition: vfs.h:159
Used to access diffrent kinds of data.
Definition: rawdata.h:48
std::vector< VFSSource * > type_sources
Definition: vfs.h:158
std::set< std::string > listDirectories(const std::string &path) const
Get a directorylist of the given directory.
Definition: vfs.cpp:183