Pioneer
Loading...
Searching...
No Matches
FileSystem.h
Go to the documentation of this file.
1// Copyright © 2008-2024 Pioneer Developers. See AUTHORS.txt for details
2// Licensed under the terms of the GPL v3. See licenses/GPL-3.txt
3
4#ifndef _FILESYSTEM_H
5#define _FILESYSTEM_H
6
7#include "ByteRange.h"
8#include "DateTime.h"
9#include "RefCounted.h"
10#include "StringRange.h"
11#include <deque>
12#include <memory>
13#include <string>
14#include <vector>
15
16/*
17 * Functionality:
18 * - Overlay multiple file sources (directories and archives)
19 * in a single virtual file system.
20 * - Enumerate entries from that combined virtual file system.
21 * - Read a file from the virtual file system.
22 * - Determine the path of the application's installed files.
23 * - Determine a sensible path for application configuration files.
24 */
25
26namespace FileSystem {
27
28 class FileSource;
29 class FileData;
30 class FileSourceFS;
31 class FileSourceUnion;
32
33 void Init();
34 void Uninit();
35
36 extern FileSourceUnion gameDataFiles;
38
39 std::string GetUserDir();
40 std::string GetDataDir();
41 bool IsValidFilename(const std::string &fileName);
42
46 std::string SanitiseFileName(const std::string &a);
47
50 std::string JoinPath(const std::string &a, const std::string &b);
51
56 std::string JoinPathBelow(const std::string &base, const std::string &path);
57
60 std::string GetRelativePath(const std::string &base, const std::string &path);
61
67 std::string NormalisePath(const std::string &path);
68
69 enum class CopyMode {
70 OVERWRITE, // overwrite all files in target with files from source
71 ONLY_MISSING_IN_TARGET // only copy files that aren't present in target
72 };
73
76 bool CopyDir(FileSource &sourceFS, std::string sourceDir, FileSourceFS &targetFS, std::string targetDir, CopyMode copymode = CopyMode::OVERWRITE);
77
78 class FileInfo {
79 friend class FileSource;
80
81 public:
83 m_source(0),
84 m_dirLen(0),
85 m_type(FT_NON_EXISTENT) {}
86
87 enum FileType {
88 // note: order here affects sort-order of FileInfo
93 };
94
95 enum FileType GetType() const { return m_type; }
96 bool Exists() const { return (m_type != FT_NON_EXISTENT); }
97 bool IsDir() const { return (m_type == FT_DIR); }
98 bool IsFile() const { return (m_type == FT_FILE); }
99 bool IsSpecial() const { return (m_type == FT_SPECIAL); }
100
101 // modification time specified in *local* time (not UTC)
102 // (specified in local time because we want it to be easy to display)
103 Time::DateTime GetModificationTime() const { return m_modTime; }
104
105 const std::string &GetPath() const { return m_path; }
106 std::string GetName() const { return m_path.substr(m_dirLen); }
107 std::string GetDir() const { return m_path.substr(0, m_dirLen); }
108 std::string GetAbsoluteDir() const;
109 std::string GetAbsolutePath() const;
110
111 const FileSource &GetSource() const { return *m_source; }
112
114
115 friend bool operator==(const FileInfo &a, const FileInfo &b)
116 {
117 return (a.m_source == b.m_source && a.m_type == b.m_type && a.m_path == b.m_path);
118 }
119 friend bool operator!=(const FileInfo &a, const FileInfo &b)
120 {
121 return (a.m_source != b.m_source || a.m_type != b.m_type || a.m_path != b.m_path);
122 }
123 friend bool operator<(const FileInfo &a, const FileInfo &b)
124 {
125 int c = a.m_path.compare(b.m_path);
126 if (c != 0) {
127 return (c < 0);
128 }
129 if (a.m_type != b.m_type) {
130 return (a.m_type < b.m_type);
131 }
132 return (a.m_source < b.m_source);
133 }
134 friend bool operator<=(const FileInfo &a, const FileInfo &b)
135 {
136 int c = a.m_path.compare(b.m_path);
137 if (c != 0) {
138 return (c < 0);
139 }
140 if (a.m_type != b.m_type) {
141 return (a.m_type < b.m_type);
142 }
143 return (a.m_source <= b.m_source);
144 }
145 friend bool operator>(const FileInfo &a, const FileInfo &b) { return (b < a); }
146 friend bool operator>=(const FileInfo &a, const FileInfo &b) { return (b <= a); }
147
148 private:
149 // use FileSource::MakeFileInfo to create your FileInfos
150 FileInfo(FileSource *source, const std::string &path, FileType type, Time::DateTime modTime);
151
152 FileSource *m_source;
153 std::string m_path;
154 Time::DateTime m_modTime;
155 int m_dirLen;
156 FileType m_type;
157 };
158
159 class FileData : public RefCounted {
160 public:
161 virtual ~FileData() {}
162
163 const FileInfo &GetInfo() const { return m_info; }
164 size_t GetSize() const { return m_size; }
165 const char *GetData() const
166 {
167 assert(m_info.IsFile());
168 return m_data;
169 }
172 std::string_view AsStringView() const { return std::string_view(m_data, m_size); }
173
174 protected:
175 FileData(const FileInfo &info, size_t size, char *data) :
176 m_info(info),
177 m_data(data),
178 m_size(size) {}
180 m_info(info),
181 m_data(0),
182 m_size(0) {}
183
185 char *m_data;
186 size_t m_size;
187 };
188
189 class FileDataMalloc : public FileData {
190 public:
191 FileDataMalloc(const FileInfo &info, size_t size) :
192 FileData(info, size, static_cast<char *>(std::malloc(size))) {}
193 FileDataMalloc(const FileInfo &info, size_t size, char *data) :
194 FileData(info, size, data) {}
195 virtual ~FileDataMalloc() { std::free(m_data); }
196 };
197
199 public:
200 enum Flags {
204 Recurse = 8
205 };
206
207 // Iterator interface for use with C++11 range-for only
208 struct iter {
210 bool m_atend = false;
211
212 using iterator_category = std::input_iterator_tag;
213 using reference = const FileInfo &;
214 using value_type = const FileInfo;
215
216 reference operator*() const { return m_enum.Current(); }
217 bool operator!=(const iter &rhs) { return m_enum.Finished() != rhs.m_atend; }
218
220 {
221 m_enum.Next();
222 return *this;
223 }
224 };
225
226 explicit FileEnumerator(FileSource &fs, int flags = 0);
227 explicit FileEnumerator(FileSource &fs, const std::string &path, int flags = 0);
229
230 void AddSearchRoot(const std::string &path);
231
232 bool Finished() const { return m_queue.empty(); }
233 void Next();
234 const FileInfo &Current() const { return m_queue.front(); }
235
236 iter begin() { return iter{ *this, false }; }
237 iter end() { return iter{ *this, true }; }
238
239 private:
240 void ExpandDirQueue();
241 void QueueDirectoryContents(const FileInfo &info);
242
243 FileSource *m_source;
244 std::deque<FileInfo> m_queue;
245 std::deque<FileInfo> m_dirQueue;
246 int m_flags;
247 };
248
250 public:
251 explicit FileSource(const std::string &root, bool trusted = false) :
252 m_root(root),
253 m_trusted(trusted) {}
254 virtual ~FileSource() {}
255
256 const std::string &GetRoot() const { return m_root; }
257
258 virtual FileInfo Lookup(const std::string &path) = 0;
259 virtual RefCountedPtr<FileData> ReadFile(const std::string &path) = 0;
260 virtual bool ReadDirectory(const std::string &path, std::vector<FileInfo> &output) = 0;
261
262 virtual FileEnumerator Enumerate(int enumeratorFlags)
263 {
264 return FileEnumerator(*this, enumeratorFlags);
265 }
266
267 virtual FileEnumerator Enumerate(const std::string &path, int enumeratorFlags)
268 {
269 return FileEnumerator(*this, path, enumeratorFlags);
270 }
271
272 virtual FileEnumerator Recurse(const std::string &path, int enumeratorFlags = 0)
273 {
274 return FileEnumerator(*this, path, FileEnumerator::Recurse | enumeratorFlags);
275 }
276
277 bool IsTrusted() const { return m_trusted; }
278
279 protected:
280 FileInfo MakeFileInfo(const std::string &path, FileInfo::FileType entryType, Time::DateTime modTime);
281 FileInfo MakeFileInfo(const std::string &path, FileInfo::FileType entryType);
282
283 private:
284 std::string m_root;
285 bool m_trusted;
286 };
287
288 class FileSourceFS : public FileSource {
289 public:
290 explicit FileSourceFS(const std::string &root, bool trusted = false);
292
293 virtual FileInfo Lookup(const std::string &path);
294 virtual RefCountedPtr<FileData> ReadFile(const std::string &path);
295 virtual bool ReadDirectory(const std::string &path, std::vector<FileInfo> &output);
296
297 bool MakeDirectory(const std::string &path);
298
300 WRITE_TEXT = 1
301 };
302
303 // similar to fopen(path, "rb")
304 FILE *OpenReadStream(const std::string &path);
305 // similar to fopen(path, "wb")
306 FILE *OpenWriteStream(const std::string &path, int flags = 0);
307 bool RemoveFile(const std::string &relativePath);
308 bool IsChildOfRoot(const std::string &path);
309 };
310
312 public:
315
316 // add and remove sources
317 // note: order is important. The array of sources works like a PATH array:
318 // that is, earlier sources take priority over later sources
322
323 virtual FileInfo Lookup(const std::string &path);
324 std::vector<FileInfo> LookupAll(const std::string &path);
325 virtual RefCountedPtr<FileData> ReadFile(const std::string &path);
326 virtual bool ReadDirectory(const std::string &path, std::vector<FileInfo> &output);
327
328 private:
329 std::vector<FileSource *> m_sources;
330 };
331
332} // namespace FileSystem
333
334inline std::string FileSystem::FileInfo::GetAbsoluteDir() const
335{
336 return JoinPath(m_source->GetRoot(), GetDir());
337}
338
340{
341 return JoinPath(m_source->GetRoot(), GetPath());
342}
343
345{
346 return m_source->ReadFile(m_path);
347}
348
349#endif
Definition: FileSystem.h:189
FileDataMalloc(const FileInfo &info, size_t size)
Definition: FileSystem.h:191
FileDataMalloc(const FileInfo &info, size_t size, char *data)
Definition: FileSystem.h:193
virtual ~FileDataMalloc()
Definition: FileSystem.h:195
Definition: FileSystem.h:159
ByteRange AsByteRange() const
Definition: FileSystem.h:171
FileData(const FileInfo &info, size_t size, char *data)
Definition: FileSystem.h:175
StringRange AsStringRange() const
Definition: FileSystem.h:170
size_t m_size
Definition: FileSystem.h:186
FileData(const FileInfo &info)
Definition: FileSystem.h:179
size_t GetSize() const
Definition: FileSystem.h:164
char * m_data
Definition: FileSystem.h:185
virtual ~FileData()
Definition: FileSystem.h:161
const char * GetData() const
Definition: FileSystem.h:165
const FileInfo & GetInfo() const
Definition: FileSystem.h:163
FileInfo m_info
Definition: FileSystem.h:184
std::string_view AsStringView() const
Definition: FileSystem.h:172
Definition: FileSystem.h:198
Flags
Definition: FileSystem.h:200
@ Recurse
Definition: FileSystem.h:204
@ ExcludeFiles
Definition: FileSystem.h:203
@ IncludeSpecials
Definition: FileSystem.h:202
@ IncludeDirs
Definition: FileSystem.h:201
iter begin()
Definition: FileSystem.h:236
const FileInfo & Current() const
Definition: FileSystem.h:234
void Next()
Definition: FileSystem.cpp:386
~FileEnumerator()
Definition: FileSystem.cpp:375
void AddSearchRoot(const std::string &path)
Definition: FileSystem.cpp:377
bool Finished() const
Definition: FileSystem.h:232
iter end()
Definition: FileSystem.h:237
Definition: FileSystem.h:78
std::string GetName() const
Definition: FileSystem.h:106
friend bool operator<=(const FileInfo &a, const FileInfo &b)
Definition: FileSystem.h:134
friend bool operator!=(const FileInfo &a, const FileInfo &b)
Definition: FileSystem.h:119
FileInfo()
Definition: FileSystem.h:82
bool IsFile() const
Definition: FileSystem.h:98
enum FileType GetType() const
Definition: FileSystem.h:95
std::string GetDir() const
Definition: FileSystem.h:107
std::string GetAbsoluteDir() const
Definition: FileSystem.h:334
Time::DateTime GetModificationTime() const
Definition: FileSystem.h:103
std::string GetAbsolutePath() const
Definition: FileSystem.h:339
bool Exists() const
Definition: FileSystem.h:96
FileType
Definition: FileSystem.h:87
@ FT_SPECIAL
Definition: FileSystem.h:92
@ FT_NON_EXISTENT
Definition: FileSystem.h:91
@ FT_FILE
Definition: FileSystem.h:90
@ FT_DIR
Definition: FileSystem.h:89
RefCountedPtr< FileData > Read() const
Definition: FileSystem.h:344
friend bool operator<(const FileInfo &a, const FileInfo &b)
Definition: FileSystem.h:123
friend bool operator>(const FileInfo &a, const FileInfo &b)
Definition: FileSystem.h:145
friend bool operator>=(const FileInfo &a, const FileInfo &b)
Definition: FileSystem.h:146
bool IsSpecial() const
Definition: FileSystem.h:99
const std::string & GetPath() const
Definition: FileSystem.h:105
bool IsDir() const
Definition: FileSystem.h:97
friend bool operator==(const FileInfo &a, const FileInfo &b)
Definition: FileSystem.h:115
const FileSource & GetSource() const
Definition: FileSystem.h:111
Definition: FileSystem.h:288
virtual bool ReadDirectory(const std::string &path, std::vector< FileInfo > &output)
Definition: FileSystemPosix.cpp:217
FILE * OpenReadStream(const std::string &path)
Definition: FileSystemPosix.cpp:286
virtual FileInfo Lookup(const std::string &path)
Definition: FileSystemPosix.cpp:174
bool IsChildOfRoot(const std::string &path)
Definition: FileSystemPosix.cpp:298
virtual RefCountedPtr< FileData > ReadFile(const std::string &path)
Definition: FileSystemPosix.cpp:182
WriteFlags
Definition: FileSystem.h:299
@ WRITE_TEXT
Definition: FileSystem.h:300
bool MakeDirectory(const std::string &path)
Definition: FileSystemPosix.cpp:280
~FileSourceFS()
Definition: FileSystemPosix.cpp:141
FILE * OpenWriteStream(const std::string &path, int flags=0)
Definition: FileSystemPosix.cpp:292
bool RemoveFile(const std::string &relativePath)
Definition: FileSystemPosix.cpp:325
Definition: FileSystem.h:311
virtual bool ReadDirectory(const std::string &path, std::vector< FileInfo > &output)
Definition: FileSystem.cpp:328
virtual RefCountedPtr< FileData > ReadFile(const std::string &path)
Definition: FileSystem.cpp:278
void AppendSource(FileSource *fs)
Definition: FileSystem.cpp:240
void PrependSource(FileSource *fs)
Definition: FileSystem.cpp:233
void RemoveSource(FileSource *fs)
Definition: FileSystem.cpp:247
std::vector< FileInfo > LookupAll(const std::string &path)
Definition: FileSystem.cpp:266
virtual FileInfo Lookup(const std::string &path)
Definition: FileSystem.cpp:253
FileSourceUnion()
Definition: FileSystem.cpp:229
~FileSourceUnion()
Definition: FileSystem.cpp:231
Definition: FileSystem.h:249
virtual bool ReadDirectory(const std::string &path, std::vector< FileInfo > &output)=0
FileInfo MakeFileInfo(const std::string &path, FileInfo::FileType entryType, Time::DateTime modTime)
Definition: FileSystem.cpp:219
virtual FileInfo Lookup(const std::string &path)=0
FileSource(const std::string &root, bool trusted=false)
Definition: FileSystem.h:251
virtual FileEnumerator Enumerate(int enumeratorFlags)
Definition: FileSystem.h:262
const std::string & GetRoot() const
Definition: FileSystem.h:256
virtual FileEnumerator Recurse(const std::string &path, int enumeratorFlags=0)
Definition: FileSystem.h:272
virtual RefCountedPtr< FileData > ReadFile(const std::string &path)=0
virtual FileEnumerator Enumerate(const std::string &path, int enumeratorFlags)
Definition: FileSystem.h:267
virtual ~FileSource()
Definition: FileSystem.h:254
bool IsTrusted() const
Definition: FileSystem.h:277
Definition: RefCounted.h:36
Definition: RefCounted.h:11
Definition: DateTime.h:84
Definition: CityOnPlanet.h:28
std::string JoinPathBelow(const std::string &base, const std::string &path)
Definition: FileSystem.cpp:103
void Init()
Definition: FileSystem.cpp:189
std::string GetUserDir()
Definition: FileSystemPosix.cpp:117
void Uninit()
Definition: FileSystem.cpp:195
std::string SanitiseFileName(const std::string &a)
Definition: FileSystem.cpp:22
CopyMode
Definition: FileSystem.h:69
std::string GetDataDir()
Definition: FileSystemPosix.cpp:123
std::string NormalisePath(const std::string &path)
Definition: FileSystem.cpp:95
bool CopyDir(FileSource &sourceFS, std::string sourceDir, FileSourceFS &targetFS, std::string targetDir, FileSystem::CopyMode copymode)
Definition: FileSystem.cpp:149
bool IsValidFilename(const std::string &fileName)
Definition: FileSystemPosix.cpp:129
FileSourceUnion gameDataFiles
Definition: FileSystem.cpp:18
std::string JoinPath(const std::string &a, const std::string &b)
Definition: FileSystem.cpp:47
std::string GetRelativePath(const std::string &base, const std::string &path)
Definition: FileSystem.cpp:127
FileSourceFS userFiles(GetUserDir())
Definition: FileSystem.h:37
int info()
Definition: savegamedump.cpp:9
Definition: ByteRange.h:12
Definition: LuaFileSystem.cpp:34
Definition: FileSystem.h:208
FileEnumerator & m_enum
Definition: FileSystem.h:209
std::input_iterator_tag iterator_category
Definition: FileSystem.h:212
bool m_atend
Definition: FileSystem.h:210
reference operator*() const
Definition: FileSystem.h:216
iter & operator++()
Definition: FileSystem.h:219
bool operator!=(const iter &rhs)
Definition: FileSystem.h:217
Definition: StringRange.h:11