载入中...
搜索中...
未找到
FileApi.cpp
浏览该文件的文档.
2
3#include <simplesquirrel/simplesquirrel.hpp>
4
5#include <cstring>
6#include <fstream>
7#include <iterator>
8#include <string>
9
10#include "physfs/physfs.h"
11
12namespace eve {
13namespace filesystem {
14namespace physfs {
15namespace {
16
17bool readViaPhysFS(const char* path, std::string& out) {
18 if (!PHYSFS_isInit() || !PHYSFS_exists(path)) return false;
19 PHYSFS_file* f = PHYSFS_openRead(path);
20 if (!f) return false;
21 const PHYSFS_uint64 len = PHYSFS_fileLength(f);
22 out.resize(static_cast<size_t>(len));
23 if (len > 0 && PHYSFS_readBytes(f, out.data(), len) != len) {
24 PHYSFS_close(f);
25 out.clear();
26 return false;
27 }
28 PHYSFS_close(f);
29 return true;
30}
31
32bool readViaOS(const char* path, std::string& out) {
33 std::ifstream ifs(path, std::ios::binary);
34 if (!ifs) return false;
35 out.assign(std::istreambuf_iterator<char>(ifs), std::istreambuf_iterator<char>());
36 return true;
37}
38
39bool readFileContent(const char* path, std::string& out) {
40 if (readViaPhysFS(path, out) && !out.empty()) return true;
41 out.clear();
42 return readViaOS(path, out);
43}
44
45// Shared implementation of dofile (execute) and loadfile (return closure).
46SQInteger compileAndMaybeRun(HSQUIRRELVM vm, bool run) {
47 const SQChar* path = nullptr;
48 if (SQ_FAILED(sq_getstring(vm, 2, &path)) || !path)
49 return sq_throwerror(vm, "expected a script filename");
50
51 std::string content;
52 if (!readFileContent(path, content))
53 return sq_throwerror(vm, "cannot open script");
54
55 // Squirrel's sq_readscripfile skips a UTF-8 BOM; sq_compilebuffer does not.
56 if (content.size() >= 3 && (unsigned char)content[0] == 0xEF &&
57 (unsigned char)content[1] == 0xBB && (unsigned char)content[2] == 0xBF)
58 content.erase(0, 3);
59
60 if (SQ_FAILED(sq_compilebuffer(vm, content.c_str(), static_cast<SQInteger>(content.size()),
61 path, SQTrue)))
62 return SQ_ERROR;
63
64 if (!run) return 1; // leave the closure on the stack
65
66 sq_pushroottable(vm);
67 if (SQ_FAILED(sq_call(vm, 1, SQFalse, SQTrue))) return SQ_ERROR;
68 sq_pop(vm, 1);
69 return 0;
70}
71
72SQInteger sq_dofile(HSQUIRRELVM vm) { return compileAndMaybeRun(vm, true); }
73SQInteger sq_loadfile(HSQUIRRELVM vm) { return compileAndMaybeRun(vm, false); }
74
75// --- file() handle: a lightweight PhysFS-backed file table ---
76
77bool getThisStr(HSQUIRRELVM vm, const SQChar* field, std::string& out) {
78 sq_pushstring(vm, field, -1);
79 if (SQ_SUCCEEDED(sq_get(vm, 1))) {
80 const SQChar* s = nullptr;
81 if (SQ_SUCCEEDED(sq_getstring(vm, -1, &s)) && s) out = s;
82 sq_pop(vm, 1);
83 return !out.empty();
84 }
85 return false;
86}
87
88SQInteger sq_f_close(HSQUIRRELVM vm) {
89 sq_pushnull(vm);
90 return 1;
91}
92
93SQInteger sq_f_read(HSQUIRRELVM vm) {
94 std::string data;
95 if (!getThisStr(vm, _SC("_data"), data)) return sq_throwerror(vm, "file not readable");
96 sq_pushstring(vm, data.c_str(), static_cast<SQInteger>(data.size()));
97 return 1;
98}
99
100SQInteger sq_f_getSize(HSQUIRRELVM vm) {
101 std::string data;
102 if (!getThisStr(vm, _SC("_data"), data)) return sq_throwerror(vm, "file not readable");
103 sq_pushinteger(vm, static_cast<SQInteger>(data.size()));
104 return 1;
105}
106
107SQInteger sq_f_isEOF(HSQUIRRELVM vm) {
108 sq_pushbool(vm, SQTrue);
109 return 1;
110}
111
112SQInteger sq_f_tell(HSQUIRRELVM vm) {
113 sq_pushinteger(vm, 0);
114 return 1;
115}
116
117SQInteger sq_f_seek(HSQUIRRELVM vm) {
118 sq_pushbool(vm, SQTrue);
119 return 1;
120}
121
122SQInteger sq_f_getFilename(HSQUIRRELVM vm) {
123 std::string path;
124 getThisStr(vm, _SC("_path"), path);
125 sq_pushstring(vm, path.c_str(), static_cast<SQInteger>(path.size()));
126 return 1;
127}
128
129SQInteger sq_file(HSQUIRRELVM vm) {
130 const SQChar* path = nullptr;
131 const SQChar* mode = nullptr;
132 if (SQ_FAILED(sq_getstring(vm, 2, &path)) || SQ_FAILED(sq_getstring(vm, 3, &mode)))
133 return sq_throwerror(vm, "file: expected (path, mode)");
134
135 std::string m(mode ? mode : "");
136 const bool writing = m.find('w') != std::string::npos || m.find('a') != std::string::npos;
137
138 std::string content;
139 if (!writing) {
140 // A missing file must fail here, otherwise `file_exists()` (which tries
141 // file(path, "r")) returns an empty handle and reports true.
142 if (!readFileContent(path, content))
143 return sq_throwerror(vm, "cannot open file");
144 }
145
146 sq_newtable(vm); // the handle table (becomes 'this')
147 sq_pushstring(vm, path, -1); // _path
148 sq_newslot(vm, -3, SQFalse);
149 sq_pushstring(vm, content.c_str(), static_cast<SQInteger>(content.size())); // _data
150 sq_newslot(vm, -3, SQFalse);
151
152 struct { const SQChar* name; SQFUNCTION fn; } methods[] = {
153 {_SC("close"), sq_f_close},
154 {_SC("read"), sq_f_read},
155 {_SC("readString"), sq_f_read},
156 {_SC("getSize"), sq_f_getSize},
157 {_SC("isEOF"), sq_f_isEOF},
158 {_SC("tell"), sq_f_tell},
159 {_SC("seek"), sq_f_seek},
160 {_SC("getFilename"), sq_f_getFilename},
161 };
162 for (const auto& mth : methods) {
163 sq_pushstring(vm, mth.name, -1);
164 sq_newclosure(vm, mth.fn, 0);
165 sq_newslot(vm, -3, SQFalse);
166 }
167 return 1;
168}
169
170} // namespace
171
172void installScriptFileApi(ssq::VM& vm) {
173 HSQUIRRELVM h = vm.getHandle();
174 const SQInteger top = sq_gettop(h);
175
176 struct { const SQChar* name; SQFUNCTION fn; } globals[] = {
177 {_SC("dofile"), sq_dofile},
178 {_SC("loadfile"), sq_loadfile},
179 {_SC("file"), sq_file},
180 };
181 for (const auto& g : globals) {
182 sq_pushroottable(h);
183 sq_pushstring(h, g.name, -1);
184 sq_newclosure(h, g.fn, 0);
185 sq_newslot(h, -3, SQTrue);
186 sq_pop(h, 1);
187 }
188
189 sq_settop(h, top);
190}
191
192} // namespace physfs
193} // namespace filesystem
194} // namespace eve
struct SQVM * HSQUIRRELVM
HSQUIRRELVM vm
Definition ECS.cpp:20
int h
float f
Light2D::Data * data
const char * name
Definition RockMesh.cpp:21
SettlementPipeline::Stage fn
float m[16]
uint32_t s
Definition Weather.cpp:28
void installScriptFileApi(ssq::VM &vm)
用 PhysFS 版本覆盖 Squirrel 的 file / dofile / loadfile 全局, 使脚本与资源从已挂载的游戏源(真实目录或内存挂载的 .eve 归档)解析; PhysFS 中不...
Definition FileApi.cpp:172
Definition Build.cpp:11