Mana
Loading...
Searching...
No Matches
filesystem.h
Go to the documentation of this file.
1/*
2 * The Mana Client
3 * Copyright (C) 2024 The Mana Developers
4 *
5 * This file is part of The Mana Client.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#pragma once
22
23// Suppress deprecation warnings for PHYSFS_getUserDir
24#define PHYSFS_DEPRECATED
25
26#include "utils/physfsrwops.h"
27
28#include <optional>
29#include <string>
30
35namespace FS {
36
37inline bool init(const char *argv0)
38{
39 return PHYSFS_init(argv0) != 0;
40}
41
42inline void deinit()
43{
44 PHYSFS_deinit();
45}
46
47inline const char *getDirSeparator()
48{
49 return PHYSFS_getDirSeparator();
50}
51
52inline const char *getBaseDir()
53{
54 return PHYSFS_getBaseDir();
55}
56
57inline const char *getUserDir()
58{
59 return PHYSFS_getUserDir();
60}
61
62inline const char *getPrefDir(const char *org, const char *app)
63{
64 return PHYSFS_getPrefDir(org, app);
65}
66
73inline bool setWriteDir(const std::string &path)
74{
75 return PHYSFS_setWriteDir(path.c_str()) != 0;
76}
77
85inline bool addToSearchPath(const std::string &path, bool append)
86{
87 return PHYSFS_mount(path.c_str(), "/", append ? 1 : 0) != 0;
88}
89
93inline bool exists(const std::string &path)
94{
95 return PHYSFS_exists(path.c_str()) != 0;
96}
97
98inline std::optional<const char *> getRealDir(const std::string &path)
99{
100 auto dir = PHYSFS_getRealDir(path.c_str());
101 return dir ? std::optional<const char *>(dir) : std::nullopt;
102}
103
107inline bool isDirectory(const std::string &path)
108{
109 PHYSFS_Stat stat;
110 if (PHYSFS_stat(path.c_str(), &stat) != 0)
111 {
112 return stat.filetype == PHYSFS_FILETYPE_DIRECTORY;
113 }
114 return false;
115}
116
120inline bool mkdir(const std::string &path)
121{
122 return PHYSFS_mkdir(path.c_str()) != 0;
123}
124
129class Files
130{
131public:
132 struct End {};
133 friend bool operator!=(const char *const *files, End)
134 { return *files != nullptr; }
135
136 explicit Files(char **files) : mFiles(files) {}
137 ~Files() { PHYSFS_freeList(mFiles); }
138
139 Files(const Files &) = delete;
140 Files &operator=(const Files &) = delete;
141
142 // Relies on C++17 support for begin/end to not have the same return type
143 const char* const *begin() const { return mFiles; }
144 End end() const { return End(); }
145
146private:
147 char **mFiles;
148};
149
153inline Files enumerateFiles(const std::string &dir)
154{
155 return Files(PHYSFS_enumerateFiles(dir.c_str()));
156}
157
161class File
162{
163public:
164 explicit File(PHYSFS_file *file)
165 : file(file)
166 {}
167
169 {
170 if (isOpen())
171 close();
172 }
173
174 bool isOpen() const
175 {
176 return file != nullptr;
177 }
178
179 operator bool() const
180 {
181 return isOpen();
182 }
183
184 bool close()
185 {
186 if (PHYSFS_close(file) != 0)
187 {
188 file = nullptr;
189 return true;
190 }
191 return false;
192 }
193
194 std::optional<size_t> read(void *data, size_t size)
195 {
196 auto len = PHYSFS_readBytes(file, data, size);
197 return len >= 0 ? std::optional<size_t>(len) : std::nullopt;
198 }
199
200 std::optional<size_t> write(const void *data, size_t size)
201 {
202 auto len = PHYSFS_writeBytes(file, data, size);
203 return len >= 0 ? std::optional<size_t>(len) : std::nullopt;
204 }
205
206 bool flush()
207 {
208 return PHYSFS_flush(file) != 0;
209 }
210
211 bool seek(size_t pos)
212 {
213 return PHYSFS_seek(file, pos) != 0;
214 }
215
216 std::optional<size_t> fileLength() const
217 {
218 auto len = PHYSFS_fileLength(file);
219 return len >= 0 ? std::optional<size_t>(len) : std::nullopt;
220 }
221
222 std::optional<size_t> tell() const
223 {
224 auto pos = PHYSFS_tell(file);
225 return pos >= 0 ? std::optional<size_t>(pos) : std::nullopt;
226 }
227
228 bool eof() const
229 {
230 return PHYSFS_eof(file) != 0;
231 }
232
233private:
234 PHYSFS_file *file;
235};
236
237inline File openWrite(const std::string &path)
238{
239 return File(PHYSFS_openWrite(path.c_str()));
240}
241
242inline File openAppend(const std::string &path)
243{
244 return File(PHYSFS_openAppend(path.c_str()));
245}
246
247inline File openRead(const std::string &path)
248{
249 return File(PHYSFS_openRead(path.c_str()));
250}
251
252inline const char *getLastError()
253{
254 return PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode());
255}
256
257//
258// Helper functions for loading files through SDL_RWops
259//
260
261inline SDL_RWops *openRWops(const std::string &path)
262{
263 return PHYSFSRWOPS_openRead(path.c_str());
264}
265
274inline SDL_RWops *openBufferedRWops(const std::string &path,
275 PHYSFS_uint64 bufferSize = 2048)
276{
277 if (auto file = PHYSFS_openRead(path.c_str()))
278 {
279 PHYSFS_setBuffer(file, bufferSize);
280 if (auto rw = PHYSFSRWOPS_makeRWops(file))
281 return rw;
282 else
283 PHYSFS_close(file);
284 }
285 return nullptr;
286}
287
288inline void *loadFile(const std::string &path, size_t &datasize)
289{
290 auto file = openRWops(path);
291 if (!file)
292 return nullptr;
293
294 return SDL_LoadFile_RW(file, &datasize, 1);
295}
296
297} // namespace FS
File wrapper class to provide a more convenient API and automatic closing.
Definition filesystem.h:162
File(PHYSFS_file *file)
Definition filesystem.h:164
bool eof() const
Definition filesystem.h:228
std::optional< size_t > read(void *data, size_t size)
Definition filesystem.h:194
bool flush()
Definition filesystem.h:206
PHYSFS_file * file
Definition filesystem.h:234
std::optional< size_t > write(const void *data, size_t size)
Definition filesystem.h:200
std::optional< size_t > fileLength() const
Definition filesystem.h:216
bool isOpen() const
Definition filesystem.h:174
bool seek(size_t pos)
Definition filesystem.h:211
std::optional< size_t > tell() const
Definition filesystem.h:222
bool close()
Definition filesystem.h:184
Helper class to iterate over the files in a directory.
Definition filesystem.h:130
Files & operator=(const Files &)=delete
Files(const Files &)=delete
Files(char **files)
Definition filesystem.h:136
End end() const
Definition filesystem.h:144
char ** mFiles
Definition filesystem.h:147
friend bool operator!=(const char *const *files, End)
Definition filesystem.h:133
const char *const * begin() const
Definition filesystem.h:143
These functions wrap PHYSFS functions to provide a more user-friendly interface and to limit the dire...
Definition filesystem.h:35
File openRead(const std::string &path)
Definition filesystem.h:247
bool init(const char *argv0)
Definition filesystem.h:37
const char * getPrefDir(const char *org, const char *app)
Definition filesystem.h:62
const char * getDirSeparator()
Definition filesystem.h:47
SDL_RWops * openBufferedRWops(const std::string &path, PHYSFS_uint64 bufferSize=2048)
Creates a buffered SDL_RWops.
Definition filesystem.h:274
bool setWriteDir(const std::string &path)
Sets the write directory.
Definition filesystem.h:73
bool mkdir(const std::string &path)
Creates a directory in the write path.
Definition filesystem.h:120
const char * getUserDir()
Definition filesystem.h:57
File openWrite(const std::string &path)
Definition filesystem.h:237
bool isDirectory(const std::string &path)
Checks whether the given path is a directory.
Definition filesystem.h:107
bool addToSearchPath(const std::string &path, bool append)
Adds a directory or archive to the search path.
Definition filesystem.h:85
File openAppend(const std::string &path)
Definition filesystem.h:242
const char * getLastError()
Definition filesystem.h:252
bool exists(const std::string &path)
Checks whether the given file or directory exists in the search path.
Definition filesystem.h:93
void * loadFile(const std::string &path, size_t &datasize)
Definition filesystem.h:288
SDL_RWops * openRWops(const std::string &path)
Definition filesystem.h:261
const char * getBaseDir()
Definition filesystem.h:52
void deinit()
Definition filesystem.h:42
std::optional< const char * > getRealDir(const std::string &path)
Definition filesystem.h:98
Files enumerateFiles(const std::string &dir)
Returns a list of files in the given directory.
Definition filesystem.h:153
SDL_RWops * PHYSFSRWOPS_openRead(const char *fname)
Open a platform-independent filename for reading, and make it accessible via an SDL_RWops structure.
SDL_RWops * PHYSFSRWOPS_makeRWops(PHYSFS_File *handle)
Make a SDL_RWops from an existing PhysicsFS file handle.