Pioneer
FileSystem.h
Go to the documentation of this file.
1 // Copyright © 2008-2021 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 
172  protected:
173  FileData(const FileInfo &info, size_t size, char *data) :
174  m_info(info),
175  m_data(data),
176  m_size(size) {}
177  FileData(const FileInfo &info) :
178  m_info(info),
179  m_data(0),
180  m_size(0) {}
181 
183  char *m_data;
184  size_t m_size;
185  };
186 
187  class FileDataMalloc : public FileData {
188  public:
189  FileDataMalloc(const FileInfo &info, size_t size) :
190  FileData(info, size, static_cast<char *>(std::malloc(size))) {}
191  FileDataMalloc(const FileInfo &info, size_t size, char *data) :
192  FileData(info, size, data) {}
193  virtual ~FileDataMalloc() { std::free(m_data); }
194  };
195 
196  class FileSource {
197  public:
198  explicit FileSource(const std::string &root, bool trusted = false) :
199  m_root(root),
200  m_trusted(trusted) {}
201  virtual ~FileSource() {}
202 
203  const std::string &GetRoot() const { return m_root; }
204 
205  virtual FileInfo Lookup(const std::string &path) = 0;
206  virtual RefCountedPtr<FileData> ReadFile(const std::string &path) = 0;
207  virtual bool ReadDirectory(const std::string &path, std::vector<FileInfo> &output) = 0;
208 
209  bool IsTrusted() const { return m_trusted; }
210 
211  protected:
212  FileInfo MakeFileInfo(const std::string &path, FileInfo::FileType entryType, Time::DateTime modTime);
213  FileInfo MakeFileInfo(const std::string &path, FileInfo::FileType entryType);
214 
215  private:
216  std::string m_root;
217  bool m_trusted;
218  };
219 
220  class FileSourceFS : public FileSource {
221  public:
222  explicit FileSourceFS(const std::string &root, bool trusted = false);
223  ~FileSourceFS();
224 
225  virtual FileInfo Lookup(const std::string &path);
226  virtual RefCountedPtr<FileData> ReadFile(const std::string &path);
227  virtual bool ReadDirectory(const std::string &path, std::vector<FileInfo> &output);
228 
229  bool MakeDirectory(const std::string &path);
230 
231  enum WriteFlags {
232  WRITE_TEXT = 1
233  };
234 
235  // similar to fopen(path, "rb")
236  FILE *OpenReadStream(const std::string &path);
237  // similar to fopen(path, "wb")
238  FILE *OpenWriteStream(const std::string &path, int flags = 0);
239  };
240 
241  class FileSourceUnion : public FileSource {
242  public:
243  FileSourceUnion();
245 
246  // add and remove sources
247  // note: order is important. The array of sources works like a PATH array:
248  // that is, earlier sources take priority over later sources
249  void PrependSource(FileSource *fs);
250  void AppendSource(FileSource *fs);
251  void RemoveSource(FileSource *fs);
252 
253  virtual FileInfo Lookup(const std::string &path);
254  std::vector<FileInfo> LookupAll(const std::string &path);
255  virtual RefCountedPtr<FileData> ReadFile(const std::string &path);
256  virtual bool ReadDirectory(const std::string &path, std::vector<FileInfo> &output);
257 
258  private:
259  std::vector<FileSource *> m_sources;
260  };
261 
263  public:
264  enum Flags {
268  Recurse = 8
269  };
270 
271  explicit FileEnumerator(FileSource &fs, int flags = 0);
272  explicit FileEnumerator(FileSource &fs, const std::string &path, int flags = 0);
273  ~FileEnumerator();
274 
275  void AddSearchRoot(const std::string &path);
276 
277  bool Finished() const { return m_queue.empty(); }
278  void Next();
279  const FileInfo &Current() const { return m_queue.front(); }
280 
281  private:
282  void ExpandDirQueue();
283  void QueueDirectoryContents(const FileInfo &info);
284 
285  FileSource *m_source;
286  std::deque<FileInfo> m_queue;
287  std::deque<FileInfo> m_dirQueue;
288  int m_flags;
289  };
290 
291 } // namespace FileSystem
292 
293 inline std::string FileSystem::FileInfo::GetAbsoluteDir() const
294 {
295  return JoinPath(m_source->GetRoot(), GetDir());
296 }
297 
298 inline std::string FileSystem::FileInfo::GetAbsolutePath() const
299 {
300  return JoinPath(m_source->GetRoot(), GetPath());
301 }
302 
304 {
305  return m_source->ReadFile(m_path);
306 }
307 
308 #endif
Definition: FileSystem.h:187
FileDataMalloc(const FileInfo &info, size_t size)
Definition: FileSystem.h:189
FileDataMalloc(const FileInfo &info, size_t size, char *data)
Definition: FileSystem.h:191
virtual ~FileDataMalloc()
Definition: FileSystem.h:193
Definition: FileSystem.h:158
ByteRange AsByteRange() const
Definition: FileSystem.h:170
FileData(const FileInfo &info, size_t size, char *data)
Definition: FileSystem.h:173
StringRange AsStringRange() const
Definition: FileSystem.h:169
size_t m_size
Definition: FileSystem.h:184
FileData(const FileInfo &info)
Definition: FileSystem.h:177
size_t GetSize() const
Definition: FileSystem.h:163
char * m_data
Definition: FileSystem.h:183
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:182
Definition: FileSystem.h:262
Flags
Definition: FileSystem.h:264
@ Recurse
Definition: FileSystem.h:268
@ ExcludeFiles
Definition: FileSystem.h:267
@ IncludeSpecials
Definition: FileSystem.h:266
@ IncludeDirs
Definition: FileSystem.h:265
void Next()
Definition: FileSystem.cpp:381
~FileEnumerator()
Definition: FileSystem.cpp:370
void AddSearchRoot(const std::string &path)
Definition: FileSystem.cpp:372
FileEnumerator(FileSource &fs, int flags=0)
Definition: FileSystem.cpp:359
bool Finished() const
Definition: FileSystem.h:277
const FileInfo & Current() const
Definition: FileSystem.h:279
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:293
Time::DateTime GetModificationTime() const
Definition: FileSystem.h:102
std::string GetAbsolutePath() const
Definition: FileSystem.h:298
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:303
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:220
virtual bool ReadDirectory(const std::string &path, std::vector< FileInfo > &output)
Definition: FileSystemPosix.cpp:192
FILE * OpenReadStream(const std::string &path)
Definition: FileSystemPosix.cpp:261
virtual FileInfo Lookup(const std::string &path)
Definition: FileSystemPosix.cpp:149
FileSourceFS(const std::string &root, bool trusted=false)
Definition: FileSystemPosix.cpp:113
virtual RefCountedPtr< FileData > ReadFile(const std::string &path)
Definition: FileSystemPosix.cpp:157
WriteFlags
Definition: FileSystem.h:231
@ WRITE_TEXT
Definition: FileSystem.h:232
bool MakeDirectory(const std::string &path)
Definition: FileSystemPosix.cpp:255
~FileSourceFS()
Definition: FileSystemPosix.cpp:116
FILE * OpenWriteStream(const std::string &path, int flags=0)
Definition: FileSystemPosix.cpp:267
Definition: FileSystem.h:241
virtual bool ReadDirectory(const std::string &path, std::vector< FileInfo > &output)
Definition: FileSystem.cpp:323
virtual RefCountedPtr< FileData > ReadFile(const std::string &path)
Definition: FileSystem.cpp:273
void AppendSource(FileSource *fs)
Definition: FileSystem.cpp:235
void PrependSource(FileSource *fs)
Definition: FileSystem.cpp:228
void RemoveSource(FileSource *fs)
Definition: FileSystem.cpp:242
std::vector< FileInfo > LookupAll(const std::string &path)
Definition: FileSystem.cpp:261
virtual FileInfo Lookup(const std::string &path)
Definition: FileSystem.cpp:248
FileSourceUnion()
Definition: FileSystem.cpp:224
~FileSourceUnion()
Definition: FileSystem.cpp:226
Definition: FileSystem.h:196
FileInfo MakeFileInfo(const std::string &path, FileInfo::FileType entryType, Time::DateTime modTime)
Definition: FileSystem.cpp:214
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:198
const std::string & GetRoot() const
Definition: FileSystem.h:203
virtual ~FileSource()
Definition: FileSystem.h:201
bool IsTrusted() const
Definition: FileSystem.h:209
Definition: RefCounted.h:36
Definition: RefCounted.h:11
Definition: DateTime.h:84
Definition: IniConfig.h:10
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:101
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:107
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