Pioneer
FileSystem.h
Go to the documentation of this file.
1 // Copyright © 2008-2023 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 
26 namespace 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 
45  std::string SanitiseFileName(const std::string &a);
46 
49  std::string JoinPath(const std::string &a, const std::string &b);
50 
55  std::string JoinPathBelow(const std::string &base, const std::string &path);
56 
59  std::string GetRelativePath(const std::string &base, const std::string &path);
60 
66  std::string NormalisePath(const std::string &path);
67 
68  enum class CopyMode {
69  OVERWRITE, // overwrite all files in target with files from source
70  ONLY_MISSING_IN_TARGET // only copy files that aren't present in target
71  };
72 
75  bool CopyDir(FileSource &sourceFS, std::string sourceDir, FileSourceFS &targetFS, std::string targetDir, CopyMode copymode = CopyMode::OVERWRITE);
76 
77  class FileInfo {
78  friend class FileSource;
79 
80  public:
82  m_source(0),
83  m_dirLen(0),
84  m_type(FT_NON_EXISTENT) {}
85 
86  enum FileType {
87  // note: order here affects sort-order of FileInfo
92  };
93 
94  enum FileType GetType() const { return m_type; }
95  bool Exists() const { return (m_type != FT_NON_EXISTENT); }
96  bool IsDir() const { return (m_type == FT_DIR); }
97  bool IsFile() const { return (m_type == FT_FILE); }
98  bool IsSpecial() const { return (m_type == FT_SPECIAL); }
99 
100  // modification time specified in *local* time (not UTC)
101  // (specified in local time because we want it to be easy to display)
102  Time::DateTime GetModificationTime() const { return m_modTime; }
103 
104  const std::string &GetPath() const { return m_path; }
105  std::string GetName() const { return m_path.substr(m_dirLen); }
106  std::string GetDir() const { return m_path.substr(0, m_dirLen); }
107  std::string GetAbsoluteDir() const;
108  std::string GetAbsolutePath() const;
109 
110  const FileSource &GetSource() const { return *m_source; }
111 
113 
114  friend bool operator==(const FileInfo &a, const FileInfo &b)
115  {
116  return (a.m_source == b.m_source && a.m_type == b.m_type && a.m_path == b.m_path);
117  }
118  friend bool operator!=(const FileInfo &a, const FileInfo &b)
119  {
120  return (a.m_source != b.m_source || a.m_type != b.m_type || a.m_path != b.m_path);
121  }
122  friend bool operator<(const FileInfo &a, const FileInfo &b)
123  {
124  int c = a.m_path.compare(b.m_path);
125  if (c != 0) {
126  return (c < 0);
127  }
128  if (a.m_type != b.m_type) {
129  return (a.m_type < b.m_type);
130  }
131  return (a.m_source < b.m_source);
132  }
133  friend bool operator<=(const FileInfo &a, const FileInfo &b)
134  {
135  int c = a.m_path.compare(b.m_path);
136  if (c != 0) {
137  return (c < 0);
138  }
139  if (a.m_type != b.m_type) {
140  return (a.m_type < b.m_type);
141  }
142  return (a.m_source <= b.m_source);
143  }
144  friend bool operator>(const FileInfo &a, const FileInfo &b) { return (b < a); }
145  friend bool operator>=(const FileInfo &a, const FileInfo &b) { return (b <= a); }
146 
147  private:
148  // use FileSource::MakeFileInfo to create your FileInfos
149  FileInfo(FileSource *source, const std::string &path, FileType type, Time::DateTime modTime);
150 
151  FileSource *m_source;
152  std::string m_path;
153  Time::DateTime m_modTime;
154  int m_dirLen;
155  FileType m_type;
156  };
157 
158  class FileData : public RefCounted {
159  public:
160  virtual ~FileData() {}
161 
162  const FileInfo &GetInfo() const { return m_info; }
163  size_t GetSize() const { return m_size; }
164  const char *GetData() const
165  {
166  assert(m_info.IsFile());
167  return m_data;
168  }
171  std::string_view AsStringView() const { return std::string_view(m_data, m_size); }
172 
173  protected:
174  FileData(const FileInfo &info, size_t size, char *data) :
175  m_info(info),
176  m_data(data),
177  m_size(size) {}
178  FileData(const FileInfo &info) :
179  m_info(info),
180  m_data(0),
181  m_size(0) {}
182 
184  char *m_data;
185  size_t m_size;
186  };
187 
188  class FileDataMalloc : public FileData {
189  public:
190  FileDataMalloc(const FileInfo &info, size_t size) :
191  FileData(info, size, static_cast<char *>(std::malloc(size))) {}
192  FileDataMalloc(const FileInfo &info, size_t size, char *data) :
193  FileData(info, size, data) {}
194  virtual ~FileDataMalloc() { std::free(m_data); }
195  };
196 
197  class FileSource {
198  public:
199  explicit FileSource(const std::string &root, bool trusted = false) :
200  m_root(root),
201  m_trusted(trusted) {}
202  virtual ~FileSource() {}
203 
204  const std::string &GetRoot() const { return m_root; }
205 
206  virtual FileInfo Lookup(const std::string &path) = 0;
207  virtual RefCountedPtr<FileData> ReadFile(const std::string &path) = 0;
208  virtual bool ReadDirectory(const std::string &path, std::vector<FileInfo> &output) = 0;
209 
210  bool IsTrusted() const { return m_trusted; }
211 
212  protected:
213  FileInfo MakeFileInfo(const std::string &path, FileInfo::FileType entryType, Time::DateTime modTime);
214  FileInfo MakeFileInfo(const std::string &path, FileInfo::FileType entryType);
215 
216  private:
217  std::string m_root;
218  bool m_trusted;
219  };
220 
221  class FileSourceFS : public FileSource {
222  public:
223  explicit FileSourceFS(const std::string &root, bool trusted = false);
224  ~FileSourceFS();
225 
226  virtual FileInfo Lookup(const std::string &path);
227  virtual RefCountedPtr<FileData> ReadFile(const std::string &path);
228  virtual bool ReadDirectory(const std::string &path, std::vector<FileInfo> &output);
229 
230  bool MakeDirectory(const std::string &path);
231 
232  enum WriteFlags {
233  WRITE_TEXT = 1
234  };
235 
236  // similar to fopen(path, "rb")
237  FILE *OpenReadStream(const std::string &path);
238  // similar to fopen(path, "wb")
239  FILE *OpenWriteStream(const std::string &path, int flags = 0);
240  };
241 
242  class FileSourceUnion : public FileSource {
243  public:
244  FileSourceUnion();
246 
247  // add and remove sources
248  // note: order is important. The array of sources works like a PATH array:
249  // that is, earlier sources take priority over later sources
250  void PrependSource(FileSource *fs);
251  void AppendSource(FileSource *fs);
252  void RemoveSource(FileSource *fs);
253 
254  virtual FileInfo Lookup(const std::string &path);
255  std::vector<FileInfo> LookupAll(const std::string &path);
256  virtual RefCountedPtr<FileData> ReadFile(const std::string &path);
257  virtual bool ReadDirectory(const std::string &path, std::vector<FileInfo> &output);
258 
259  private:
260  std::vector<FileSource *> m_sources;
261  };
262 
264  public:
265  enum Flags {
269  Recurse = 8
270  };
271 
272  explicit FileEnumerator(FileSource &fs, int flags = 0);
273  explicit FileEnumerator(FileSource &fs, const std::string &path, int flags = 0);
274  ~FileEnumerator();
275 
276  void AddSearchRoot(const std::string &path);
277 
278  bool Finished() const { return m_queue.empty(); }
279  void Next();
280  const FileInfo &Current() const { return m_queue.front(); }
281 
282  private:
283  void ExpandDirQueue();
284  void QueueDirectoryContents(const FileInfo &info);
285 
286  FileSource *m_source;
287  std::deque<FileInfo> m_queue;
288  std::deque<FileInfo> m_dirQueue;
289  int m_flags;
290  };
291 
292 } // namespace FileSystem
293 
294 inline std::string FileSystem::FileInfo::GetAbsoluteDir() const
295 {
296  return JoinPath(m_source->GetRoot(), GetDir());
297 }
298 
299 inline std::string FileSystem::FileInfo::GetAbsolutePath() const
300 {
301  return JoinPath(m_source->GetRoot(), GetPath());
302 }
303 
305 {
306  return m_source->ReadFile(m_path);
307 }
308 
309 #endif
Definition: FileSystem.h:188
FileDataMalloc(const FileInfo &info, size_t size)
Definition: FileSystem.h:190
FileDataMalloc(const FileInfo &info, size_t size, char *data)
Definition: FileSystem.h:192
virtual ~FileDataMalloc()
Definition: FileSystem.h:194
Definition: FileSystem.h:158
ByteRange AsByteRange() const
Definition: FileSystem.h:170
FileData(const FileInfo &info, size_t size, char *data)
Definition: FileSystem.h:174
StringRange AsStringRange() const
Definition: FileSystem.h:169
size_t m_size
Definition: FileSystem.h:185
FileData(const FileInfo &info)
Definition: FileSystem.h:178
size_t GetSize() const
Definition: FileSystem.h:163
char * m_data
Definition: FileSystem.h:184
virtual ~FileData()
Definition: FileSystem.h:160
const char * GetData() const
Definition: FileSystem.h:164
const FileInfo & GetInfo() const
Definition: FileSystem.h:162
FileInfo m_info
Definition: FileSystem.h:183
std::string_view AsStringView() const
Definition: FileSystem.h:171
Definition: FileSystem.h:263
Flags
Definition: FileSystem.h:265
@ Recurse
Definition: FileSystem.h:269
@ ExcludeFiles
Definition: FileSystem.h:268
@ IncludeSpecials
Definition: FileSystem.h:267
@ IncludeDirs
Definition: FileSystem.h:266
void Next()
Definition: FileSystem.cpp:385
~FileEnumerator()
Definition: FileSystem.cpp:374
void AddSearchRoot(const std::string &path)
Definition: FileSystem.cpp:376
FileEnumerator(FileSource &fs, int flags=0)
Definition: FileSystem.cpp:363
bool Finished() const
Definition: FileSystem.h:278
const FileInfo & Current() const
Definition: FileSystem.h:280
Definition: FileSystem.h:77
const FileSource & GetSource() const
Definition: FileSystem.h:110
std::string GetName() const
Definition: FileSystem.h:105
const std::string & GetPath() const
Definition: FileSystem.h:104
friend bool operator<=(const FileInfo &a, const FileInfo &b)
Definition: FileSystem.h:133
friend bool operator!=(const FileInfo &a, const FileInfo &b)
Definition: FileSystem.h:118
FileInfo()
Definition: FileSystem.h:81
bool IsFile() const
Definition: FileSystem.h:97
enum FileType GetType() const
Definition: FileSystem.h:94
std::string GetDir() const
Definition: FileSystem.h:106
std::string GetAbsoluteDir() const
Definition: FileSystem.h:294
Time::DateTime GetModificationTime() const
Definition: FileSystem.h:102
std::string GetAbsolutePath() const
Definition: FileSystem.h:299
bool Exists() const
Definition: FileSystem.h:95
FileType
Definition: FileSystem.h:86
@ FT_SPECIAL
Definition: FileSystem.h:91
@ FT_NON_EXISTENT
Definition: FileSystem.h:90
@ FT_FILE
Definition: FileSystem.h:89
@ FT_DIR
Definition: FileSystem.h:88
RefCountedPtr< FileData > Read() const
Definition: FileSystem.h:304
friend bool operator<(const FileInfo &a, const FileInfo &b)
Definition: FileSystem.h:122
friend bool operator>(const FileInfo &a, const FileInfo &b)
Definition: FileSystem.h:144
friend bool operator>=(const FileInfo &a, const FileInfo &b)
Definition: FileSystem.h:145
bool IsSpecial() const
Definition: FileSystem.h:98
bool IsDir() const
Definition: FileSystem.h:96
friend bool operator==(const FileInfo &a, const FileInfo &b)
Definition: FileSystem.h:114
Definition: FileSystem.h:221
virtual bool ReadDirectory(const std::string &path, std::vector< FileInfo > &output)
Definition: FileSystemPosix.cpp:205
FILE * OpenReadStream(const std::string &path)
Definition: FileSystemPosix.cpp:274
virtual FileInfo Lookup(const std::string &path)
Definition: FileSystemPosix.cpp:162
FileSourceFS(const std::string &root, bool trusted=false)
Definition: FileSystemPosix.cpp:126
virtual RefCountedPtr< FileData > ReadFile(const std::string &path)
Definition: FileSystemPosix.cpp:170
WriteFlags
Definition: FileSystem.h:232
@ WRITE_TEXT
Definition: FileSystem.h:233
bool MakeDirectory(const std::string &path)
Definition: FileSystemPosix.cpp:268
~FileSourceFS()
Definition: FileSystemPosix.cpp:129
FILE * OpenWriteStream(const std::string &path, int flags=0)
Definition: FileSystemPosix.cpp:280
Definition: FileSystem.h:242
virtual bool ReadDirectory(const std::string &path, std::vector< FileInfo > &output)
Definition: FileSystem.cpp:327
virtual RefCountedPtr< FileData > ReadFile(const std::string &path)
Definition: FileSystem.cpp:277
void AppendSource(FileSource *fs)
Definition: FileSystem.cpp:239
void PrependSource(FileSource *fs)
Definition: FileSystem.cpp:232
void RemoveSource(FileSource *fs)
Definition: FileSystem.cpp:246
std::vector< FileInfo > LookupAll(const std::string &path)
Definition: FileSystem.cpp:265
virtual FileInfo Lookup(const std::string &path)
Definition: FileSystem.cpp:252
FileSourceUnion()
Definition: FileSystem.cpp:228
~FileSourceUnion()
Definition: FileSystem.cpp:230
Definition: FileSystem.h:197
FileInfo MakeFileInfo(const std::string &path, FileInfo::FileType entryType, Time::DateTime modTime)
Definition: FileSystem.cpp:218
virtual bool ReadDirectory(const std::string &path, std::vector< FileInfo > &output)=0
virtual RefCountedPtr< FileData > ReadFile(const std::string &path)=0
virtual FileInfo Lookup(const std::string &path)=0
FileSource(const std::string &root, bool trusted=false)
Definition: FileSystem.h:199
const std::string & GetRoot() const
Definition: FileSystem.h:204
virtual ~FileSource()
Definition: FileSystem.h:202
bool IsTrusted() const
Definition: FileSystem.h:210
Definition: RefCounted.h:36
Definition: RefCounted.h:11
Definition: DateTime.h:84
Definition: CityOnPlanet.h:27
std::string JoinPathBelow(const std::string &base, const std::string &path)
Definition: FileSystem.cpp:102
void Init()
Definition: FileSystem.cpp:188
std::string GetUserDir()
Definition: FileSystemPosix.cpp:114
void Uninit()
Definition: FileSystem.cpp:194
std::string SanitiseFileName(const std::string &a)
Definition: FileSystem.cpp:21
CopyMode
Definition: FileSystem.h:68
std::string GetDataDir()
Definition: FileSystemPosix.cpp:120
std::string NormalisePath(const std::string &path)
Definition: FileSystem.cpp:94
bool CopyDir(FileSource &sourceFS, std::string sourceDir, FileSourceFS &targetFS, std::string targetDir, FileSystem::CopyMode copymode)
Definition: FileSystem.cpp:148
FileSourceUnion gameDataFiles
Definition: FileSystem.cpp:17
std::string JoinPath(const std::string &a, const std::string &b)
Definition: FileSystem.cpp:46
std::string GetRelativePath(const std::string &base, const std::string &path)
Definition: FileSystem.cpp:126
FileSourceFS userFiles(GetUserDir())
Definition: FileSystem.h:37
Definition: ByteRange.h:12
Definition: StringRange.h:11