载入中...
搜索中...
未找到
File.cpp
浏览该文件的文档.
1
3
4#include <cstring>
5
6#include "common/Exception.h"
9
10namespace eve {
11namespace filesystem {
12
13static bool hack_setupWriteDirectory() {
14 if (auto* f = getModInst(filesystem,Filesystem))
15 return f->setupWriteDirectory();
16 return false;
17}
18
19namespace physfs {
20
21File::File(std::string filename)
22 : filename(filename), file(nullptr), mode("c"), bufferMode("none"), bufferSize(0) {}
23
25 if (mode != "c") close();
26}
27
28bool File::open(std::string requestedMode) {
29 if (requestedMode == "c") return true;
30
31 // Love-style aliases → PhysFS binary modes.
32 if (requestedMode == "r") requestedMode = "rb";
33 else if (requestedMode == "w") requestedMode = "wb";
34 else if (requestedMode == "a") requestedMode = "ab";
35
36 if (!PHYSFS_isInit()) throw Exception("PhysFS is not initialized.");
37
38 // File must exist if read mode.
39 if ((requestedMode == "rb") && !PHYSFS_exists(filename.c_str()))
40 throw Exception("Could not open file %s. Does not exist.", filename.c_str());
41
42 // Check whether the write directory is set.
43 if ((requestedMode == "ab" || requestedMode == "wb") &&
44 (PHYSFS_getWriteDir() == nullptr) && !hack_setupWriteDirectory())
45 throw Exception("Could not set write directory.");
46
47 // File already open?
48 if (file != nullptr) return false;
49
50 PHYSFS_getLastErrorCode();
51 PHYSFS_File *handle = nullptr;
52
53 if (requestedMode == "rb") handle = PHYSFS_openRead(filename.c_str());
54 else if (requestedMode == "ab") handle = PHYSFS_openAppend(filename.c_str());
55 else if (requestedMode == "wb") handle = PHYSFS_openWrite(filename.c_str());
56 else
57 throw Exception("Invalid file mode %s.", requestedMode.c_str());
58
59 if (handle == nullptr) {
60 const char *err = PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode());
61 if (err == nullptr) err = "unknown error";
62 throw Exception("Could not open file %s (%s)", filename.c_str(), err);
63 }
64
65 file = handle;
66
67 this->mode = requestedMode;
68
69 if (file != nullptr && !setBuffer(bufferMode, bufferSize)) {
70 // Revert to buffer defaults if we don't successfully set the buffer.
71 bufferMode = "none";
72 bufferSize = 0;
73 }
74
75 return (file != nullptr);
76}
77
79 if (file == nullptr || !PHYSFS_close(file)) return false;
80
81 mode = "c";
82 file = nullptr;
83
84 return true;
85}
86
87bool File::isOpen() const { return mode != "c" && file != nullptr; }
88
89int64_t File::getSize() {
90 // If the file is closed, open it to
91 // check the size.
92 if (file == nullptr) {
93 open("rb");
94 int64_t size = (int64_t)PHYSFS_fileLength(file);
95 close();
96 return size;
97 }
98
99 return (int64_t)PHYSFS_fileLength(file);
100}
101
102int64_t File::read(void *dst, int64_t size) {
103 if (!file || mode != "rb") throw Exception("File is not opened for reading.");
104
105 int64_t max = (int64_t)PHYSFS_fileLength(file);
106 int64_t cur = (int64_t)PHYSFS_tell(file);
107 if (max < 0 || cur < 0) throw Exception("Could not read from file.");
108 if (cur > max) return 0;
109
110 int64_t remaining = max - cur;
111 size = (size == ALL) ? remaining : size;
112 if (size > remaining) size = remaining;
113
114 if (size < 0) throw Exception("Invalid read size.");
115
116 return PHYSFS_readBytes(file, dst, (PHYSFS_uint64)size);
117}
118
119bool File::write(const void *data, int64_t size) {
120 if (!file || (mode != "wb" && mode != "ab")) throw Exception("File is not opened for writing.");
121
122 if (size < 0) throw Exception("Invalid write size.");
123
124 // Try to write.
125 int64_t written = PHYSFS_writeBytes(file, data, (PHYSFS_uint64)size);
126
127 // Check that correct amount of data was written.
128 if (written != size) return false;
129
130 // Manually flush the buffer in BUFFER_LINE mode if we find a newline.
131 if (bufferMode == "newline" && bufferSize > size) {
132 if (memchr(data, '\n', (size_t)size) != nullptr) flush();
133 }
134
135 return true;
136}
137
139 if (!file || (mode != "wb" && mode != "ab")) throw Exception("File is not opened for writing.");
140
141 return PHYSFS_flush(file) != 0;
142}
143
144#ifdef EVENGINE_WINDOWS
145inline bool test_eof(File *f, PHYSFS_File *) {
146 int64_t pos = f->tell();
147 int64_t size = f->getSize();
148 return pos == -1 || size == -1 || pos >= size;
149}
150#else
151inline bool test_eof(File *, PHYSFS_File *file) { return PHYSFS_eof(file); }
152#endif
153
154bool File::isEOF() { return file == nullptr || test_eof(this, file); }
155
156int64_t File::tell() {
157 if (file == nullptr) return -1;
158
159 return (int64_t)PHYSFS_tell(file);
160}
161
162bool File::seek(uint64_t pos) { return file != nullptr && PHYSFS_seek(file, (PHYSFS_uint64)pos) != 0; }
163
164bool File::setBuffer(std::string bufmode, int64_t size) {
165 if (size < 0) return false;
166
167 // If the file isn't open, we'll make sure the buffer values are set in
168 // File::open.
169 if (!isOpen()) {
170 bufferMode = bufmode;
171 bufferSize = size;
172 return true;
173 }
174
175 int ret = 1;
176 if (bufferMode == "newline" || bufferMode == "full") {
177 ret = PHYSFS_setBuffer(file, size);
178 } else {
179 ret = PHYSFS_setBuffer(file, 0);
180 size = 0;
181 }
182
183 if (ret == 0) return false;
184
185 bufferMode = bufmode;
186 bufferSize = size;
187
188 return true;
189}
190
191std::string File::getBuffer(int64_t &size) const {
192 size = bufferSize;
193 return bufferMode;
194}
195
196std::string File::getFilename() const { return filename; }
197
198std::string File::getMode() const { return mode; }
199
200} // namespace physfs
201} // namespace filesystem
202} // namespace eve
filesystem::File * file
#define getModInst(N, T)
Definition Module.h:38
float f
PrimitiveHandle handle
float size
Definition TreeMesh.cpp:156
EVENGINE_API_FOUNDATION public API.
Definition Exception.h:13
static const int64_t ALL
Used to indicate ALL data in a file.
Definition File.h:19
File public API.
Definition File.h:17
bool isEOF() override
True when eof.
Definition File.cpp:154
std::string getFilename() const override
Full filename including extension.
Definition File.cpp:196
std::string getMode() const override
Returns the mode.
Definition File.cpp:198
bool close() override
Closes close.
Definition File.cpp:78
bool open(std::string mode) override
Opens open.
Definition File.cpp:28
bool seek(uint64_t pos) override
Seeks seek.
Definition File.cpp:162
bool setBuffer(std::string bufmode, int64_t size) override
Sets the buffer.
Definition File.cpp:164
virtual ~File()
Releases File resources.
Definition File.cpp:24
File(std::string filename)
Constructs an File with the given ilename.
Definition File.cpp:21
bool write(const void *data, int64_t size) override
Writes write.
Definition File.cpp:119
int64_t read(void *dst, int64_t size) override
Reads read.
Definition File.cpp:102
bool flush() override
Flushes flush.
Definition File.cpp:138
int64_t getSize() override
Byte length of the owned buffer.
Definition File.cpp:89
int64_t tell() override
Returns the current tell.
Definition File.cpp:156
bool isOpen() const override
True when open.
Definition File.cpp:87
std::string getBuffer(int64_t &size) const override
Returns the buffer.
Definition File.cpp:191
bool test_eof(File *, PHYSFS_File *file)
Definition File.cpp:151
Build metadata (engine git commit, build time, third-party version).
Definition Build.cpp:16