Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1 | pmbaty | 1 | /* |
2 | * This file is part of the DXX-Rebirth project <https://www.dxx-rebirth.com/>. |
||
3 | * It is copyright by its individual contributors, as recorded in the |
||
4 | * project's Git history. See COPYING.txt at the top level for license |
||
5 | * terms and a link to the Git history. |
||
6 | */ |
||
7 | |||
8 | /* |
||
9 | * |
||
10 | * Some simple physfs extensions |
||
11 | * |
||
12 | */ |
||
13 | |||
14 | #pragma once |
||
15 | |||
16 | #include <cstddef> |
||
17 | #include <memory> |
||
18 | #include <string.h> |
||
19 | #include <stdarg.h> |
||
20 | #include <type_traits> |
||
21 | |||
22 | // When PhysicsFS can *easily* be built as a framework on Mac OS X, |
||
23 | // the framework form will be supported again -kreatordxx |
||
24 | #if 1 //!(defined(__APPLE__) && defined(__MACH__)) |
||
25 | #include <physfs.h> |
||
26 | #else |
||
27 | #include <physfs/physfs.h> |
||
28 | #endif |
||
29 | |||
30 | #include "fmtcheck.h" |
||
31 | #include "dxxsconf.h" |
||
32 | #include "dsx-ns.h" |
||
33 | #include "dxxerror.h" |
||
34 | #include "vecmat.h" |
||
35 | #include "byteutil.h" |
||
36 | |||
37 | #ifdef __cplusplus |
||
38 | #include <stdexcept> |
||
39 | #include "u_mem.h" |
||
40 | #include "pack.h" |
||
41 | #include "ntstring.h" |
||
42 | #include "fwd-partial_range.h" |
||
43 | #include <array> |
||
44 | #include <memory> |
||
45 | |||
46 | #ifdef DXX_CONSTANT_TRUE |
||
47 | #define _DXX_PHYSFS_CHECK_SIZE_CONSTANT(S,v) DXX_CONSTANT_TRUE((S) > (v)) |
||
48 | #define _DXX_PHYSFS_CHECK_SIZE(S,C,v) _DXX_PHYSFS_CHECK_SIZE_CONSTANT(static_cast<size_t>(S) * static_cast<size_t>(C), v) |
||
49 | #define DXX_PHYSFS_CHECK_READ_SIZE_OBJECT_SIZE(S,C,v) \ |
||
50 | (void)(__builtin_object_size(v, 1) != static_cast<size_t>(-1) && _DXX_PHYSFS_CHECK_SIZE(S,C,__builtin_object_size(v, 1)) && (DXX_ALWAYS_ERROR_FUNCTION(dxx_trap_overwrite, "read size exceeds element size"), 0)) |
||
51 | #define DXX_PHYSFS_CHECK_READ_SIZE_ARRAY_SIZE(S,C) \ |
||
52 | (void)(_DXX_PHYSFS_CHECK_SIZE(S,C,sizeof(v)) && (DXX_ALWAYS_ERROR_FUNCTION(dxx_trap_overwrite, "read size exceeds array size"), 0)) |
||
53 | #define DXX_PHYSFS_CHECK_WRITE_SIZE_OBJECT_SIZE(S,C,v) \ |
||
54 | (void)(__builtin_object_size(v, 1) != static_cast<size_t>(-1) && _DXX_PHYSFS_CHECK_SIZE(S,C,__builtin_object_size(v, 1)) && (DXX_ALWAYS_ERROR_FUNCTION(dxx_trap_overwrite, "write size exceeds element size"), 0)) |
||
55 | #define DXX_PHYSFS_CHECK_WRITE_ELEMENT_SIZE_CONSTANT(S,C) \ |
||
56 | ((void)(dxx_builtin_constant_p(S) || dxx_builtin_constant_p(C) || \ |
||
57 | (DXX_ALWAYS_ERROR_FUNCTION(dxx_trap_nonconstant_size, "array element size is not constant"), 0))) |
||
58 | #define DXX_PHYSFS_CHECK_WRITE_SIZE_ARRAY_SIZE(S,C) \ |
||
59 | ((void)(_DXX_PHYSFS_CHECK_SIZE(S,C,sizeof(v)) && \ |
||
60 | (DXX_ALWAYS_ERROR_FUNCTION(dxx_trap_overread, "write size exceeds array size"), 0))) |
||
61 | #else |
||
62 | #define DXX_PHYSFS_CHECK_READ_SIZE_OBJECT_SIZE(S,C,v) ((void)0) |
||
63 | #define DXX_PHYSFS_CHECK_READ_SIZE_ARRAY_SIZE(S,C) ((void)0) |
||
64 | #define DXX_PHYSFS_CHECK_WRITE_SIZE_OBJECT_SIZE(S,C,v) ((void)0) |
||
65 | #define DXX_PHYSFS_CHECK_WRITE_ELEMENT_SIZE_CONSTANT(S,C) ((void)0) |
||
66 | #define DXX_PHYSFS_CHECK_WRITE_SIZE_ARRAY_SIZE(S,C) ((void)0) |
||
67 | #endif |
||
68 | |||
69 | #define DXX_PHYSFS_CHECK_WRITE_CONSTANTS(S,C) \ |
||
70 | ((void)(DXX_PHYSFS_CHECK_WRITE_ELEMENT_SIZE_CONSTANT(S,C), \ |
||
71 | DXX_PHYSFS_CHECK_WRITE_SIZE_ARRAY_SIZE(S,C), 0)) \ |
||
72 | |||
73 | namespace dcx { |
||
74 | |||
75 | template <typename V> |
||
76 | __attribute_always_inline() |
||
77 | static inline PHYSFS_sint64 PHYSFSX_check_read(PHYSFS_File *file, V *v, const PHYSFS_uint32 S, const PHYSFS_uint32 C) |
||
78 | { |
||
79 | if constexpr (std::is_integral<V>::value) |
||
80 | static_assert(std::is_pod<V>::value, "non-POD integral value read"); |
||
81 | else |
||
82 | static_assert(std::is_pod<V>::value, "non-POD non-integral value read"); |
||
83 | DXX_PHYSFS_CHECK_READ_SIZE_OBJECT_SIZE(S, C, v); |
||
84 | return (S == 0 ? 0 : PHYSFS_readBytes(file, v, S * C) / S); // Pierre-Marie Baty -- work around PHYSFS_read() deprecation |
||
85 | } |
||
86 | |||
87 | template <typename V, std::size_t N> |
||
88 | __attribute_always_inline() |
||
89 | static inline PHYSFS_sint64 PHYSFSX_check_read(PHYSFS_File *file, std::array<V, N> &v, PHYSFS_uint32 S, PHYSFS_uint32 C) |
||
90 | { |
||
91 | static_assert(std::is_pod<V>::value, "C++ array of non-POD elements read"); |
||
92 | DXX_PHYSFS_CHECK_READ_SIZE_ARRAY_SIZE(S, C); |
||
93 | return PHYSFSX_check_read(file, &v[0], S, C); |
||
94 | } |
||
95 | |||
96 | template <typename V, typename D> |
||
97 | __attribute_always_inline() |
||
98 | static inline PHYSFS_sint64 PHYSFSX_check_read(PHYSFS_File *file, const std::unique_ptr<V, D> &v, PHYSFS_uint32 S, PHYSFS_uint32 C) |
||
99 | { |
||
100 | return PHYSFSX_check_read(file, v.get(), S, C); |
||
101 | } |
||
102 | |||
103 | template <typename V> |
||
104 | __attribute_always_inline() |
||
105 | static inline PHYSFS_sint64 PHYSFSX_check_write(PHYSFS_File *file, const V *v, const PHYSFS_uint32 S, const PHYSFS_uint32 C) |
||
106 | { |
||
107 | if constexpr (std::is_integral<V>::value) |
||
108 | { |
||
109 | static_assert(std::is_pod<V>::value, "non-POD integral value written"); |
||
110 | DXX_PHYSFS_CHECK_WRITE_ELEMENT_SIZE_CONSTANT(S,C); |
||
111 | } |
||
112 | else |
||
113 | static_assert(std::is_pod<V>::value, "non-POD non-integral value written"); |
||
114 | DXX_PHYSFS_CHECK_WRITE_SIZE_OBJECT_SIZE(S, C, v); |
||
115 | return (S == 0 ? 0 : PHYSFS_writeBytes(file, v, S * C) / S); // Pierre-Marie Baty -- work around PHYSFS_write() deprecation |
||
116 | } |
||
117 | |||
118 | template <typename V, std::size_t N> |
||
119 | __attribute_always_inline() |
||
120 | static inline PHYSFS_sint64 PHYSFSX_check_write(PHYSFS_File *file, const std::array<V, N> &v, PHYSFS_uint32 S, PHYSFS_uint32 C) |
||
121 | { |
||
122 | static_assert(std::is_pod<V>::value, "C++ array of non-POD elements written"); |
||
123 | DXX_PHYSFS_CHECK_WRITE_CONSTANTS(S,C); |
||
124 | return PHYSFSX_check_write(file, &v[0], S, C); |
||
125 | } |
||
126 | |||
127 | template <typename T, typename D> |
||
128 | __attribute_always_inline() |
||
129 | static inline PHYSFS_sint64 PHYSFSX_check_write(PHYSFS_File *file, const std::unique_ptr<T, D> &p, PHYSFS_uint32 S, PHYSFS_uint32 C) |
||
130 | { |
||
131 | return PHYSFSX_check_write(file, p.get(), S, C); |
||
132 | } |
||
133 | |||
134 | template <typename V> |
||
135 | PHYSFS_sint64 PHYSFSX_check_read(PHYSFS_File *file, exact_type<V> v, PHYSFS_uint32 S, PHYSFS_uint32 C) = delete; |
||
136 | template <typename V> |
||
137 | PHYSFS_sint64 PHYSFSX_check_write(PHYSFS_File *file, exact_type<V> v, PHYSFS_uint32 S, PHYSFS_uint32 C) = delete; |
||
138 | |||
139 | template <typename V> |
||
140 | PHYSFS_sint64 PHYSFSX_check_read(PHYSFS_File *file, V **v, PHYSFS_uint32 S, PHYSFS_uint32 C) = delete; |
||
141 | template <typename V> |
||
142 | PHYSFS_sint64 PHYSFSX_check_write(PHYSFS_File *file, V **v, PHYSFS_uint32 S, PHYSFS_uint32 C) = delete; |
||
143 | #define PHYSFS_read(F,V,S,C) PHYSFSX_check_read(F,V,S,C) |
||
144 | #define PHYSFS_write(F,V,S,C) PHYSFSX_check_write(F,V,S,C) |
||
145 | |||
146 | static inline PHYSFS_sint16 PHYSFSX_readSXE16(PHYSFS_File *file, int swap) |
||
147 | { |
||
148 | PHYSFS_sint16 val; |
||
149 | |||
150 | PHYSFS_read(file, &val, sizeof(val), 1); |
||
151 | |||
152 | return swap ? SWAPSHORT(val) : val; |
||
153 | } |
||
154 | |||
155 | static inline PHYSFS_sint32 PHYSFSX_readSXE32(PHYSFS_File *file, int swap) |
||
156 | { |
||
157 | PHYSFS_sint32 val; |
||
158 | |||
159 | PHYSFS_read(file, &val, sizeof(val), 1); |
||
160 | |||
161 | return swap ? SWAPINT(val) : val; |
||
162 | } |
||
163 | |||
164 | static inline int PHYSFSX_writeU8(PHYSFS_File *file, PHYSFS_uint8 val) |
||
165 | { |
||
166 | return PHYSFS_write(file, &val, 1, 1); |
||
167 | } |
||
168 | |||
169 | static inline int PHYSFSX_writeString(PHYSFS_File *file, const char *s) |
||
170 | { |
||
171 | return PHYSFS_write(file, s, 1, strlen(s) + 1); |
||
172 | } |
||
173 | |||
174 | static inline int PHYSFSX_puts(PHYSFS_File *file, const char *s, size_t len) __attribute_nonnull(); |
||
175 | static inline int PHYSFSX_puts(PHYSFS_File *file, const char *s, size_t len) |
||
176 | { |
||
177 | return PHYSFS_write(file, s, 1, len); |
||
178 | } |
||
179 | |||
180 | template <size_t len> |
||
181 | static inline int PHYSFSX_puts_literal(PHYSFS_File *file, const char (&s)[len]) __attribute_nonnull(); |
||
182 | template <size_t len> |
||
183 | static inline int PHYSFSX_puts_literal(PHYSFS_File *file, const char (&s)[len]) |
||
184 | { |
||
185 | return PHYSFSX_puts(file, s, len - 1); |
||
186 | } |
||
187 | #define PHYSFSX_puts(A1,S,...) (PHYSFSX_puts(A1,S, _dxx_call_puts_parameter2(1, ## __VA_ARGS__, strlen(S)))) |
||
188 | |||
189 | static inline int PHYSFSX_fgetc(PHYSFS_File *const fp) |
||
190 | { |
||
191 | unsigned char c; |
||
192 | |||
193 | if (PHYSFS_read(fp, &c, 1, 1) != 1) |
||
194 | return EOF; |
||
195 | |||
196 | return c; |
||
197 | } |
||
198 | |||
199 | static inline int PHYSFSX_fseek(PHYSFS_File *fp, long int offset, int where) |
||
200 | { |
||
201 | int c, goal_position; |
||
202 | |||
203 | switch(where) |
||
204 | { |
||
205 | case SEEK_SET: |
||
206 | goal_position = offset; |
||
207 | break; |
||
208 | case SEEK_CUR: |
||
209 | goal_position = PHYSFS_tell(fp) + offset; |
||
210 | break; |
||
211 | case SEEK_END: |
||
212 | goal_position = PHYSFS_fileLength(fp) + offset; |
||
213 | break; |
||
214 | default: |
||
215 | return 1; |
||
216 | } |
||
217 | c = PHYSFS_seek(fp, goal_position); |
||
218 | return !c; |
||
219 | } |
||
220 | |||
221 | template <std::size_t N> |
||
222 | struct PHYSFSX_gets_line_t |
||
223 | { |
||
224 | PHYSFSX_gets_line_t() = default; |
||
225 | PHYSFSX_gets_line_t(const PHYSFSX_gets_line_t &) = delete; |
||
226 | PHYSFSX_gets_line_t &operator=(const PHYSFSX_gets_line_t &) = delete; |
||
227 | PHYSFSX_gets_line_t(PHYSFSX_gets_line_t &&) = default; |
||
228 | PHYSFSX_gets_line_t &operator=(PHYSFSX_gets_line_t &&) = default; |
||
229 | using line_t = std::array<char, N>; |
||
230 | #if DXX_HAVE_POISON |
||
231 | /* Force onto heap to improve checker accuracy */ |
||
232 | std::unique_ptr<line_t> m_line; |
||
233 | const line_t &line() const { return *m_line.get(); } |
||
234 | line_t &line() { return *m_line.get(); } |
||
235 | line_t &next() |
||
236 | { |
||
237 | m_line = std::make_unique<line_t>(); |
||
238 | return *m_line.get(); |
||
239 | } |
||
240 | #else |
||
241 | line_t m_line; |
||
242 | const line_t &line() const { return m_line; } |
||
243 | line_t &line() { return m_line; } |
||
244 | line_t &next() { return m_line; } |
||
245 | #endif |
||
246 | operator line_t &() { return line(); } |
||
247 | operator const line_t &() const { return line(); } |
||
248 | operator char *() { return line().data(); } |
||
249 | operator const char *() const { return line().data(); } |
||
250 | typename line_t::reference operator[](typename line_t::size_type i) { return line()[i]; } |
||
251 | typename line_t::reference operator[](int i) { return operator[](static_cast<typename line_t::size_type>(i)); } |
||
252 | typename line_t::const_reference operator[](typename line_t::size_type i) const { return line()[i]; } |
||
253 | typename line_t::const_reference operator[](int i) const { return operator[](static_cast<typename line_t::size_type>(i)); } |
||
254 | constexpr std::size_t size() const { return N; } |
||
255 | typename line_t::const_iterator begin() const { return line().begin(); } |
||
256 | typename line_t::const_iterator end() const { return line().end(); } |
||
257 | }; |
||
258 | |||
259 | template <> |
||
260 | struct PHYSFSX_gets_line_t<0> |
||
261 | { |
||
262 | #define DXX_ALLOCATE_PHYSFS_LINE(n) std::make_unique<char[]>(n) |
||
263 | std::unique_ptr<char[]> m_line; |
||
264 | std::size_t m_length; |
||
265 | PHYSFSX_gets_line_t(std::size_t n) : |
||
266 | #if !DXX_HAVE_POISON |
||
267 | m_line(DXX_ALLOCATE_PHYSFS_LINE(n)), |
||
268 | #endif |
||
269 | m_length(n) |
||
270 | { |
||
271 | } |
||
272 | char *line() { return m_line.get(); } |
||
273 | const char *line() const { return m_line.get(); } |
||
274 | char *next() |
||
275 | { |
||
276 | #if DXX_HAVE_POISON |
||
277 | /* Reallocate to tell checker to undefine the buffer */ |
||
278 | m_line = DXX_ALLOCATE_PHYSFS_LINE(m_length); |
||
279 | #endif |
||
280 | return m_line.get(); |
||
281 | } |
||
282 | std::size_t size() const { return m_length; } |
||
283 | operator const char *() const { return m_line.get(); } |
||
284 | const char *begin() const { return *this; } |
||
285 | const char *end() const { return begin() + m_length; } |
||
286 | operator const void *() const = delete; |
||
287 | #undef DXX_ALLOCATE_PHYSFS_LINE |
||
288 | }; |
||
289 | |||
290 | class PHYSFSX_fgets_t |
||
291 | { |
||
292 | static char *get(char *buf, std::size_t n, PHYSFS_File *const fp); |
||
293 | static char *get(char *buf, std::size_t offset, std::size_t n, PHYSFS_File *const fp) |
||
294 | { |
||
295 | if (offset > n) |
||
296 | throw std::invalid_argument("offset too large"); |
||
297 | return get(&buf[offset], n - offset, fp); |
||
298 | } |
||
299 | public: |
||
300 | template <std::size_t n> |
||
301 | __attribute_nonnull() |
||
302 | char *operator()(PHYSFSX_gets_line_t<n> &buf, PHYSFS_File *const fp, std::size_t offset = 0) const |
||
303 | { |
||
304 | return get(&buf.next()[0], offset, buf.size(), fp); |
||
305 | } |
||
306 | template <std::size_t n> |
||
307 | __attribute_nonnull() |
||
308 | char *operator()(ntstring<n> &buf, PHYSFS_File *const fp, std::size_t offset = 0) const |
||
309 | { |
||
310 | auto r = get(&buf.data()[0], offset, buf.size(), fp); |
||
311 | buf.back() = 0; |
||
312 | return r; |
||
313 | } |
||
314 | }; |
||
315 | |||
316 | constexpr PHYSFSX_fgets_t PHYSFSX_fgets{}; |
||
317 | |||
318 | static inline int PHYSFSX_printf(PHYSFS_File *file, const char *format, ...) __attribute_format_printf(2, 3); |
||
319 | static inline int PHYSFSX_printf(PHYSFS_File *file, const char *format, ...) |
||
320 | #define PHYSFSX_printf(A1,F,...) dxx_call_printf_checked(PHYSFSX_printf,PHYSFSX_puts_literal,(A1),(F),##__VA_ARGS__) |
||
321 | { |
||
322 | char buffer[1024]; |
||
323 | va_list args; |
||
324 | |||
325 | va_start(args, format); |
||
326 | size_t len = vsnprintf(buffer, sizeof(buffer), format, args); |
||
327 | va_end(args); |
||
328 | |||
329 | return PHYSFSX_puts(file, buffer, len); |
||
330 | } |
||
331 | |||
332 | #define PHYSFSX_writeFix PHYSFS_writeSLE32 |
||
333 | #define PHYSFSX_writeFixAng PHYSFS_writeSLE16 |
||
334 | |||
335 | static inline int PHYSFSX_writeVector(PHYSFS_File *file, const vms_vector &v) |
||
336 | { |
||
337 | if (PHYSFSX_writeFix(file, v.x) < 1 || |
||
338 | PHYSFSX_writeFix(file, v.y) < 1 || |
||
339 | PHYSFSX_writeFix(file, v.z) < 1) |
||
340 | return 0; |
||
341 | |||
342 | return 1; |
||
343 | } |
||
344 | |||
345 | __attribute_cold |
||
346 | __attribute_noreturn |
||
347 | void PHYSFSX_read_helper_report_error(const char *const filename, const unsigned line, const char *const func, PHYSFS_File *const file); |
||
348 | |||
349 | template <typename T, int (*F)(PHYSFS_File *, T *)> |
||
350 | static T PHYSFSX_read_helper(const char *const filename, const unsigned line, const char *const func, PHYSFS_File *const file) |
||
351 | { |
||
352 | T i; |
||
353 | if (!F(file, &i)) |
||
354 | PHYSFSX_read_helper_report_error(filename, line, func, file); |
||
355 | return i; |
||
356 | } |
||
357 | |||
358 | template <typename T1, int (*F)(PHYSFS_File *, T1 *), typename T2, T1 T2::*m1, T1 T2::*m2, T1 T2::*m3> |
||
359 | static void PHYSFSX_read_sequence_helper(const char *const filename, const unsigned line, const char *const func, PHYSFS_File *const file, T2 *const i) |
||
360 | { |
||
361 | if (unlikely(!F(file, &(i->*m1)) || |
||
362 | !F(file, &(i->*m2)) || |
||
363 | !F(file, &(i->*m3)))) |
||
364 | PHYSFSX_read_helper_report_error(filename, line, func, file); |
||
365 | } |
||
366 | |||
367 | static inline int PHYSFSX_readS8(PHYSFS_File *const file, int8_t *const b) |
||
368 | { |
||
369 | return (PHYSFS_read(file, b, sizeof(*b), 1) == 1); |
||
370 | } |
||
371 | |||
372 | #define PHYSFSX_readByte(F) (PHYSFSX_read_helper<int8_t, PHYSFSX_readS8>(__FILE__, __LINE__, __func__, (F))) |
||
373 | #define PHYSFSX_readShort(F) (PHYSFSX_read_helper<int16_t, PHYSFS_readSLE16>(__FILE__, __LINE__, __func__, (F))) |
||
374 | #define PHYSFSX_readInt(F) (PHYSFSX_read_helper<int32_t, PHYSFS_readSLE32>(__FILE__, __LINE__, __func__, (F))) |
||
375 | #define PHYSFSX_readFix(F) (PHYSFSX_read_helper<fix, PHYSFS_readSLE32>(__FILE__, __LINE__, __func__, (F))) |
||
376 | #define PHYSFSX_readFixAng(F) (PHYSFSX_read_helper<fixang, PHYSFS_readSLE16>(__FILE__, __LINE__, __func__, (F))) |
||
377 | #define PHYSFSX_readVector(F,V) (PHYSFSX_read_sequence_helper<fix, PHYSFS_readSLE32, vms_vector, &vms_vector::x, &vms_vector::y, &vms_vector::z>(__FILE__, __LINE__, __func__, (F), &(V))) |
||
378 | #define PHYSFSX_readAngleVec(V,F) (PHYSFSX_read_sequence_helper<fixang, PHYSFS_readSLE16, vms_angvec, &vms_angvec::p, &vms_angvec::b, &vms_angvec::h>(__FILE__, __LINE__, __func__, (F), (V))) |
||
379 | |||
380 | static inline void PHYSFSX_readMatrix(const char *const filename, const unsigned line, const char *const func, vms_matrix *const m, PHYSFS_File *const file) |
||
381 | { |
||
382 | auto &PHYSFSX_readVector = PHYSFSX_read_sequence_helper<fix, PHYSFS_readSLE32, vms_vector, &vms_vector::x, &vms_vector::y, &vms_vector::z>; |
||
383 | (PHYSFSX_readVector)(filename, line, func, file, &m->rvec); |
||
384 | (PHYSFSX_readVector)(filename, line, func, file, &m->uvec); |
||
385 | (PHYSFSX_readVector)(filename, line, func, file, &m->fvec); |
||
386 | } |
||
387 | |||
388 | #define PHYSFSX_readMatrix(M,F) ((PHYSFSX_readMatrix)(__FILE__, __LINE__, __func__, (M), (F))) |
||
389 | |||
390 | #define PHYSFSX_contfile_init PHYSFSX_addRelToSearchPath |
||
391 | #define PHYSFSX_contfile_close PHYSFSX_removeRelFromSearchPath |
||
392 | |||
393 | class PHYSFS_File_deleter |
||
394 | { |
||
395 | public: |
||
396 | int operator()(PHYSFS_File *fp) const |
||
397 | { |
||
398 | return PHYSFS_close(fp); |
||
399 | } |
||
400 | }; |
||
401 | |||
402 | class RAIIPHYSFS_File : public std::unique_ptr<PHYSFS_File, PHYSFS_File_deleter> |
||
403 | { |
||
404 | typedef std::unique_ptr<PHYSFS_File, PHYSFS_File_deleter> base_t; |
||
405 | public: |
||
406 | DXX_INHERIT_CONSTRUCTORS(RAIIPHYSFS_File, base_t); |
||
407 | using base_t::operator bool; |
||
408 | operator PHYSFS_File *() const && = delete; |
||
409 | operator PHYSFS_File *() const & |
||
410 | { |
||
411 | return get(); |
||
412 | } |
||
413 | int close() |
||
414 | { |
||
415 | /* Like reset(), but returns result */ |
||
416 | int r = get_deleter()(get()); |
||
417 | if (r) |
||
418 | release(); |
||
419 | return r; |
||
420 | } |
||
421 | template <typename T> |
||
422 | bool operator==(T) const = delete; |
||
423 | template <typename T> |
||
424 | bool operator!=(T) const = delete; |
||
425 | }; |
||
426 | |||
427 | typedef char file_extension_t[5]; |
||
428 | __attribute_nonnull() |
||
429 | __attribute_warn_unused_result |
||
430 | int PHYSFSX_checkMatchingExtension(const char *filename, const partial_range_t<const file_extension_t *>); |
||
431 | |||
432 | template <std::size_t count> |
||
433 | __attribute_nonnull() |
||
434 | __attribute_warn_unused_result |
||
435 | static inline int PHYSFSX_checkMatchingExtension(const std::array<file_extension_t, count> &exts, const char *filename) |
||
436 | { |
||
437 | return PHYSFSX_checkMatchingExtension(filename, exts); |
||
438 | } |
||
439 | |||
440 | extern int PHYSFSX_addRelToSearchPath(const char *relname, int add_to_end); |
||
441 | extern int PHYSFSX_removeRelFromSearchPath(const char *relname); |
||
442 | extern int PHYSFSX_fsize(const char *hogname); |
||
443 | extern void PHYSFSX_listSearchPathContent(); |
||
444 | int PHYSFSX_getRealPath(const char *stdPath, char *realPath, std::size_t); |
||
445 | |||
446 | template <std::size_t N> |
||
447 | static inline int PHYSFSX_getRealPath(const char *stdPath, std::array<char, N> &realPath) |
||
448 | { |
||
449 | return PHYSFSX_getRealPath(stdPath, realPath.data(), N); |
||
450 | } |
||
451 | |||
452 | extern int PHYSFSX_isNewPath(const char *path); |
||
453 | extern int PHYSFSX_rename(const char *oldpath, const char *newpath); |
||
454 | |||
455 | #define PHYSFSX_exists(F,I) ((I) ? PHYSFSX_exists_ignorecase(F) : PHYSFS_exists(F)) |
||
456 | int PHYSFSX_exists_ignorecase(const char *filename); |
||
457 | RAIIPHYSFS_File PHYSFSX_openReadBuffered(const char *filename); |
||
458 | RAIIPHYSFS_File PHYSFSX_openWriteBuffered(const char *filename); |
||
459 | extern void PHYSFSX_addArchiveContent(); |
||
460 | extern void PHYSFSX_removeArchiveContent(); |
||
461 | } |
||
462 | |||
463 | #ifdef dsx |
||
464 | namespace dsx { |
||
465 | |||
466 | bool PHYSFSX_init(int argc, char *argv[]); |
||
467 | int PHYSFSX_checkSupportedArchiveTypes(); |
||
468 | |||
469 | } |
||
470 | #endif |
||
471 | |||
472 | #endif |