/
ifilesystem.h
209 lines (171 loc) · 6.52 KB
/
ifilesystem.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
#pragma once
/**
* \defgroup vfs Virtual filesystem
* \file ifilesystem.h
* Interface types for the VFS module.
*/
#include <cstddef>
#include <string>
#include <list>
#include <set>
#include <functional>
#include <algorithm>
#include "imodule.h"
#include "iarchive.h"
namespace vfs
{
// Extension of std::list to check for existing paths before inserting new ones
class SearchPaths :
public std::list<std::string>
{
public:
bool insertIfNotExists(const std::string& path)
{
if (std::find(begin(), end(), path) != end())
{
return false;
}
push_back(path);
return true;
}
};
/// Visibility of an asset in the mod installation
enum class Visibility
{
/// Standard visibility, shown in all relevant areas
NORMAL,
/// Hidden from selectors, but rendered as normal in the map itself
HIDDEN
};
inline std::ostream& operator<< (std::ostream& s, const Visibility& v)
{
if (v == Visibility::HIDDEN)
return s << "Visibility::HIDDEN";
else if (v == Visibility::NORMAL)
return s << "Visibility::NORMAL";
else
return s << "Visibility(invalid)";
}
/// Metadata about a file in the virtual filesystem
struct FileInfo
{
/// Top-level directory (if any), e.g. "def" or "models"
std::string topDir;
/// Name of the file, including intermediate directories under the topDir
std::string name;
/// Visibility of the file
Visibility visibility = Visibility::NORMAL;
/// Return the full mod-relative path, including the containing directory
std::string fullPath() const
{
if (topDir.empty())
return name;
else
return topDir + (topDir.back() == '/' ? "" : "/") + name;
}
/// Equality comparison with another FileInfo
bool operator== (const FileInfo& rhs) const
{
return topDir == rhs.topDir && name == rhs.name
&& visibility == rhs.visibility;
}
};
/**
* Main interface for the virtual filesystem.
*
* The virtual filesystem provides a unified view of the contents of Doom 3's
* base and mod subdirectories, including the contents of PK4 files. Assets can
* be retrieved using a single unique path, without needing to know whereabouts
* in the physical filesystem the asset is located.
*
* \ingroup vfs
*/
class VirtualFileSystem :
public RegisterableModule
{
public:
virtual ~VirtualFileSystem() {}
// Functor taking the filename and visibility as argument. The filename is
// relative to the base path passed to the GlobalFileSystem().foreach*()
// method.
typedef std::function<void(const FileInfo&)> VisitorFunc;
/**
* Interface for VFS observers.
*
* A VFS observer is automatically notified of events relating to the
* VFS, including startup and shutdown.
*/
class Observer
{
public:
virtual ~Observer() {}
/**
* Notification of VFS initialisation.
*
* This method is invoked for all VFS observers when the VFS is
* initialised. An empty default implementation is provided.
*/
virtual void onFileSystemInitialise() {}
/**
* Notification of VFS shutdown.
*
* This method is invoked for all VFS observers when the VFS is shut
* down. An empty default implementation is provided.
*/
virtual void onFileSystemShutdown() {}
};
typedef std::set<std::string> ExtensionSet;
// Initialises the filesystem using the given search order.
virtual void initialise(const SearchPaths& vfsSearchPaths, const ExtensionSet& allowedArchiveExtensions) = 0;
/// \brief Shuts down the filesystem.
virtual void shutdown() = 0;
// Returns the extension set this VFS instance has been initialised with
virtual const ExtensionSet& getArchiveExtensions() const = 0;
// greebo: Adds/removes observers to/from the VFS
virtual void addObserver(Observer& observer) = 0;
virtual void removeObserver(Observer& observer) = 0;
// Returns the number of files in the VFS matching the given filename
virtual int getFileCount(const std::string& filename) = 0;
/// \brief Returns the file identified by \p filename opened in binary mode, or 0 if not found.
// greebo: Note: expects the filename to be normalised (forward slashes, trailing slash).
virtual ArchiveFilePtr openFile(const std::string& filename) = 0;
/// \brief Returns the file identified by \p filename opened in binary mode, or 0 if not found.
// This is a variant of openFile taking an absolute path as argument.
virtual ArchiveFilePtr openFileInAbsolutePath(const std::string& filename) = 0;
/// \brief Returns the file identified by \p filename opened in text mode, or 0 if not found.
virtual ArchiveTextFilePtr openTextFile(const std::string& filename) = 0;
/// \brief Returns the file identified by \p filename opened in text mode, or NULL if not found.
/// This is a variant of openTextFile taking an absolute path as argument.
virtual ArchiveTextFilePtr openTextFileInAbsolutePath(const std::string& filename) = 0;
// Opens an independent archive located in the given physical path.
// (This archive can be located somewhere outside the current VFS hierarchy.)
// Loading this archive won't have any effect on the VFS setup, it is opened stand-alone.
virtual IArchive::Ptr openArchiveInAbsolutePath(const std::string& pathToArchive) = 0;
/// \brief Calls the visitor function for each file under \p basedir matching \p extension.
/// Use "*" as \p extension to match all file extensions.
virtual void forEachFile(const std::string& basedir,
const std::string& extension,
const VisitorFunc& visitorFunc,
std::size_t depth = 1) = 0;
// Similar to forEachFile, this routine traverses an absolute path
// searching for files matching a certain extension and invoking
// the givne visitor functor on each occurrence.
virtual void forEachFileInAbsolutePath(const std::string& path,
const std::string& extension,
const VisitorFunc& visitorFunc,
std::size_t depth = 1) = 0;
/// \brief Returns the absolute filename for a relative \p name, or "" if not found.
virtual std::string findFile(const std::string& name) = 0;
/// \brief Returns the filesystem root for an absolute \p name, or "" if not found.
/// This can be used to convert an absolute name to a relative name.
virtual std::string findRoot(const std::string& name) = 0;
// Returns the list of registered VFS paths, ordered by search priority
virtual const SearchPaths& getVfsSearchPaths() = 0;
};
}
const char* const MODULE_VIRTUALFILESYSTEM("VirtualFileSystem");
inline vfs::VirtualFileSystem& GlobalFileSystem()
{
static module::InstanceReference<vfs::VirtualFileSystem> _reference(MODULE_VIRTUALFILESYSTEM);
return _reference;
}