Subversion Repositories Games.Descent

Rev

Blame | Last modification | View Log | Download | RSS feed

  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
  473.