comparison engine/core/vfs/vfs.cpp @ 0:4a0efb7baf70

* Datasets becomes the new trunk and retires after that :-)
author mvbarracuda@33b003aa-7bff-0310-803a-e67f0ece8222
date Sun, 29 Jun 2008 18:44:17 +0000
parents
children 90005975cdbb
comparison
equal deleted inserted replaced
-1:000000000000 0:4a0efb7baf70
1 /***************************************************************************
2 * Copyright (C) 2005-2008 by the FIFE team *
3 * http://www.fifengine.de *
4 * This file is part of FIFE. *
5 * *
6 * FIFE is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation; either version 2 of the License, or *
9 * (at your option) any later version. *
10 * *
11 * This program 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 *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program; if not, write to the *
18 * Free Software Foundation, Inc., *
19 * 51 Franklin St, 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 "vfs/raw/rawdata.h"
35 #include "util/base/exception.h"
36 #include "util/log/logger.h"
37
38 #include "vfs.h"
39 #include "vfssource.h"
40 #include "vfssourceprovider.h"
41
42 namespace FIFE {
43 static Logger _log(LM_VFS);
44
45
46 VFS::VFS() : m_sources() {}
47
48 VFS::~VFS() {
49 cleanup();
50 }
51
52 void VFS::cleanup() {
53 type_sources sources = m_sources;
54 type_sources::const_iterator end = sources.end();
55 for (type_sources::iterator i = sources.begin(); i != end; ++i)
56 delete *i;
57
58 type_providers::const_iterator end2 = m_providers.end();
59 for (type_providers::iterator j = m_providers.begin(); j != end2; ++j)
60 delete *j;
61
62 m_providers.clear();
63 }
64
65 void VFS::addProvider(VFSSourceProvider* provider) {
66 provider->setVFS(this);
67 m_providers.push_back(provider);
68 FL_LOG(_log, LMsg("new provider: ") << provider->getName());
69 }
70
71 VFSSource* VFS::createSource(const std::string& path) const {
72 if ( m_usedfiles.count(path) ) {
73 FL_WARN(_log, LMsg(path) << " is already used as VFS source");
74 return 0;
75 }
76
77 type_providers::const_iterator end = m_providers.end();
78 for (type_providers::const_iterator i = m_providers.begin(); i != end; ++i) {
79 const VFSSourceProvider* provider = *i;
80 if (!provider->isReadable(path))
81 continue;
82
83 try {
84 VFSSource* source = provider->createSource(path);
85 m_usedfiles.insert(path);
86 return source;
87 } catch (const Exception& ex) {
88 FL_WARN(_log, LMsg(provider->getName()) << " thought it could load " << path << " but didn't succeed (" << ex.getMessage() << ")");
89 continue;
90 } catch (...) {
91 FL_WARN(_log, LMsg(provider->getName()) << " thought it could load " << path << " but didn't succeed (unkown exception)");
92 continue;
93 }
94 }
95
96 FL_WARN(_log, LMsg("no provider for ") << path << " found");
97 return 0;
98 }
99
100 void VFS::addNewSource(const std::string& path) {
101 VFSSource* source = createSource(path);
102 if (source) {
103 addSource(source);
104 } else {
105 FL_WARN(_log, LMsg("Failed to add new VFS source: ") << path);
106 }
107 }
108
109 void VFS::addSource(VFSSource* source) {
110 m_sources.push_back(source);
111 }
112
113 void VFS::removeSource(VFSSource* source) {
114 type_sources::iterator i = std::find(m_sources.begin(), m_sources.end(), source);
115 if (i != m_sources.end())
116 m_sources.erase(i);
117 }
118
119 VFSSource* VFS::getSourceForFile(const std::string& file) const {
120 std::string lowerpath = lower(file);
121 type_sources::const_iterator i = std::find_if(m_sources.begin(), m_sources.end(),
122 boost::bind2nd(boost::mem_fun(&VFSSource::fileExists), lowerpath));
123 if (i == m_sources.end()) {
124 FL_WARN(_log, LMsg("no source for ") << lowerpath << " found");
125 return 0;
126 }
127
128 return *i;
129 }
130
131 bool VFS::exists(const std::string& file) const {
132 return getSourceForFile(lower(file));
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 std::string lowerpath = lower(path);
159 FL_DBG(_log, LMsg("Opening: ") << lowerpath);
160
161 VFSSource* source = getSourceForFile(lowerpath);
162 if (!source)
163 throw NotFound(path);
164
165 return source->open(lowerpath);
166 }
167
168 std::string VFS::lower(const std::string& str) const {
169 std::string result;
170 result.resize(str.size());
171 std::transform(str.begin(), str.end(), result.begin(), tolower);
172 return result;
173 }
174
175 std::set<std::string> VFS::listFiles(const std::string& pathstr) const {
176 std::string lowerpath = lower(pathstr);
177 std::set<std::string> list;
178 type_sources::const_iterator end = m_sources.end();
179 for (type_sources::const_iterator i = m_sources.begin(); i != end; ++i) {
180 std::set<std::string> sourcelist = (*i)->listFiles(lowerpath);
181 list.insert(sourcelist.begin(), sourcelist.end());
182 }
183
184 return list;
185 }
186
187 std::set<std::string> VFS::listFiles(const std::string& path, const std::string& filterregex) const {
188 std::string lowerpath = lower(path);
189 std::set<std::string> list = listFiles(lowerpath);
190 return filterList(list, filterregex);
191 }
192
193 std::set<std::string> VFS::listDirectories(const std::string& pathstr) const {
194 std::string lowerpath = lower(pathstr);
195 std::set<std::string> list;
196 type_sources::const_iterator end = m_sources.end();
197 for (type_sources::const_iterator i = m_sources.begin(); i != end; ++i) {
198 std::set<std::string> sourcelist = (*i)->listDirectories(lowerpath);
199 list.insert(sourcelist.begin(), sourcelist.end());
200 }
201
202 return list;
203 }
204
205 std::set<std::string> VFS::listDirectories(const std::string& path, const std::string& filterregex) const {
206 std::set<std::string> list = listDirectories(lower(path));
207 return filterList(list, filterregex);
208 }
209
210 std::set<std::string> VFS::filterList(const std::set<std::string>& list, const std::string& fregex) const {
211 std::set<std::string> results;
212 boost::regex regex(fregex);
213 std::set<std::string>::const_iterator end = list.end();
214 for (std::set<std::string>::const_iterator i = list.begin(); i != end;) {
215 boost::cmatch match;
216 if (boost::regex_match((*i).c_str(), match, regex)) {
217 results.insert(*i);
218 }
219 ++i;
220 }
221 return results;
222 }
223 }