13static bool hack_setupWriteDirectory() {
15 return f->setupWriteDirectory();
22 : filename(filename),
file(nullptr), mode(
"c"), bufferMode(
"none"), bufferSize(0) {}
25 if (mode !=
"c")
close();
29 if (mode ==
"c")
return true;
32 if (mode ==
"r") mode =
"rb";
33 else if (mode ==
"w") mode =
"wb";
34 else if (mode ==
"a") mode =
"ab";
36 if (!PHYSFS_isInit())
throw Exception(
"PhysFS is not initialized.");
39 if ((mode ==
"rb") && !PHYSFS_exists(filename.c_str()))
40 throw Exception(
"Could not open file %s. Does not exist.", filename.c_str());
43 if ((mode ==
"ab" || mode ==
"wb") && (PHYSFS_getWriteDir() ==
nullptr) && !hack_setupWriteDirectory())
44 throw Exception(
"Could not set write directory.");
47 if (file !=
nullptr)
return false;
49 PHYSFS_getLastErrorCode();
50 PHYSFS_File *handle =
nullptr;
52 if (mode ==
"rb") handle = PHYSFS_openRead(filename.c_str());
53 else if (mode ==
"ab") handle = PHYSFS_openAppend(filename.c_str());
54 else if (mode ==
"wb") handle = PHYSFS_openWrite(filename.c_str());
56 throw Exception(
"Invalid file mode %s.", mode.c_str());
58 if (handle ==
nullptr) {
59 const char *err = PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode());
60 if (err ==
nullptr) err =
"unknown error";
61 throw Exception(
"Could not open file %s (%s)", filename.c_str(), err);
68 if (file !=
nullptr && !
setBuffer(bufferMode, bufferSize)) {
74 return (file !=
nullptr);
78 if (file ==
nullptr || !PHYSFS_close(file))
return false;
86bool File::isOpen()
const {
return mode !=
"c" && file !=
nullptr; }
91 if (file ==
nullptr) {
93 int64_t size = (int64_t)PHYSFS_fileLength(file);
98 return (int64_t)PHYSFS_fileLength(file);
102 if (!file || mode !=
"rb")
throw Exception(
"File is not opened for reading.");
104 int64_t max = (int64_t)PHYSFS_fileLength(file);
105 int64_t cur = (int64_t)PHYSFS_tell(file);
106 if (max < 0 || cur < 0)
throw Exception(
"Could not read from file.");
107 if (cur > max)
return 0;
109 int64_t remaining = max - cur;
110 size = (size ==
ALL) ? remaining : size;
111 if (size > remaining) size = remaining;
113 if (size < 0)
throw Exception(
"Invalid read size.");
115 return PHYSFS_readBytes(file, dst, (PHYSFS_uint64)size);
119 if (!file || (mode !=
"wb" && mode !=
"ab"))
throw Exception(
"File is not opened for writing.");
121 if (size < 0)
throw Exception(
"Invalid write size.");
124 int64_t written = PHYSFS_writeBytes(file,
data, (PHYSFS_uint64)size);
127 if (written != size)
return false;
130 if (bufferMode ==
"newline" && bufferSize > size) {
131 if (memchr(
data,
'\n', (
size_t)size) !=
nullptr)
flush();
138 if (!file || (mode !=
"wb" && mode !=
"ab"))
throw Exception(
"File is not opened for writing.");
140 return PHYSFS_flush(file) != 0;
143#ifdef EVENGINE_WINDOWS
145 int64_t
pos =
f->tell();
146 int64_t size =
f->getSize();
147 return pos == -1 || size == -1 ||
pos >= size;
156 if (file ==
nullptr)
return -1;
158 return (int64_t)PHYSFS_tell(file);
161bool File::seek(uint64_t
pos) {
return file !=
nullptr && PHYSFS_seek(file, (PHYSFS_uint64)
pos) != 0; }
164 if (size < 0)
return false;
169 bufferMode = bufmode;
175 if (bufferMode ==
"newline" || bufferMode ==
"full") {
176 ret = PHYSFS_setBuffer(file, size);
178 ret = PHYSFS_setBuffer(file, 0);
182 if (ret == 0)
return false;
184 bufferMode = bufmode;
static const int64_t ALL
Used to indicate ALL data in a file.
bool isEOF() override
Checks whether we are currently at end-of-file.
std::string getFilename() const override
Gets the filename for this File, or empty string if none.
std::string getMode() const override
Gets the current mode of the File.
bool close() override
Closes the file.
bool open(std::string mode) override
Opens the file in a certain mode.
bool seek(uint64_t pos) override
Seeks to a certain position in the File.
bool setBuffer(std::string bufmode, int64_t size) override
Sets the buffering mode for the file. When buffering is enabled,
virtual ~File()
Destructor.
File(std::string filename)
Constructs an File with the given ilename.
bool write(const void *data, int64_t size) override
Writes data into the File.
int64_t read(void *dst, int64_t size) override
Reads data into the destination buffer.
bool flush() override
Flushes the currently buffered file data to disk. Only applicable in write mode.
int64_t getSize() override
Gets the size of the file.
int64_t tell() override
Gets the current position in the File.
bool isOpen() const override
Gets whether the file is open.
std::string getBuffer(int64_t &size) const override
bool test_eof(File *, PHYSFS_File *file)