Mercurial > fife-parpg
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 } |