2014-06-01 17:55:23 +00:00
/*
2018-09-02 00:57:29 +00:00
* This file is part of the DXX - Rebirth project < https : //www.dxx-rebirth.com/>.
2014-06-01 17:55:23 +00:00
* It is copyright by its individual contributors , as recorded in the
* project ' s Git history . See COPYING . txt at the top level for license
* terms and a link to the Git history .
*/
2006-03-20 17:12:09 +00:00
/*
*
* Some simple physfs extensions
*
*/
2015-01-12 00:26:03 +00:00
# pragma once
2006-03-20 17:12:09 +00:00
2013-12-19 21:32:40 +00:00
# include <cstddef>
2014-07-20 03:48:27 +00:00
# include <memory>
2006-03-20 17:12:09 +00:00
# include <string.h>
# include <stdarg.h>
2017-06-25 20:46:03 +00:00
# include <type_traits>
2006-03-20 17:12:09 +00:00
2010-09-17 10:44:21 +00:00
// When PhysicsFS can *easily* be built as a framework on Mac OS X,
// the framework form will be supported again -kreatordxx
# if 1 //!(defined(__APPLE__) && defined(__MACH__))
2006-03-20 17:12:09 +00:00
# include <physfs.h>
2007-04-09 02:41:45 +00:00
# else
# include <physfs/physfs.h>
# endif
2006-03-20 17:12:09 +00:00
2013-12-08 23:37:40 +00:00
# include "fmtcheck.h"
2013-06-27 02:35:22 +00:00
# include "dxxsconf.h"
2016-03-19 19:08:10 +00:00
# include "dsx-ns.h"
2012-07-07 18:35:06 +00:00
# include "dxxerror.h"
2006-03-20 17:12:09 +00:00
# include "vecmat.h"
2014-07-03 01:47:29 +00:00
# include "byteutil.h"
2006-10-02 13:55:58 +00:00
2012-11-11 22:12:51 +00:00
# ifdef __cplusplus
2014-12-20 04:36:10 +00:00
# include <stdexcept>
2014-06-22 03:54:35 +00:00
# include "u_mem.h"
# include "pack.h"
2015-01-12 00:26:02 +00:00
# include "ntstring.h"
2020-06-10 02:25:32 +00:00
# include "fwd-partial_range.h"
2020-05-02 21:18:42 +00:00
# include <array>
2020-05-02 21:18:43 +00:00
# include <memory>
2014-06-22 03:54:35 +00:00
2016-11-12 18:10:09 +00:00
# ifdef DXX_CONSTANT_TRUE
2015-07-29 03:05:28 +00:00
# define _DXX_PHYSFS_CHECK_SIZE_CONSTANT(S,v) DXX_CONSTANT_TRUE((S) > (v))
2014-09-20 23:47:27 +00:00
# define _DXX_PHYSFS_CHECK_SIZE(S,C,v) _DXX_PHYSFS_CHECK_SIZE_CONSTANT(static_cast<size_t>(S) * static_cast<size_t>(C), v)
# define DXX_PHYSFS_CHECK_READ_SIZE_OBJECT_SIZE(S,C,v) \
( 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 ) )
# define DXX_PHYSFS_CHECK_READ_SIZE_ARRAY_SIZE(S,C) \
( void ) ( _DXX_PHYSFS_CHECK_SIZE ( S , C , sizeof ( v ) ) & & ( DXX_ALWAYS_ERROR_FUNCTION ( dxx_trap_overwrite , " read size exceeds array size " ) , 0 ) )
# define DXX_PHYSFS_CHECK_WRITE_SIZE_OBJECT_SIZE(S,C,v) \
( 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 ) )
2014-06-22 03:54:35 +00:00
# define DXX_PHYSFS_CHECK_WRITE_ELEMENT_SIZE_CONSTANT(S,C) \
2014-07-31 03:52:57 +00:00
( ( void ) ( dxx_builtin_constant_p ( S ) | | dxx_builtin_constant_p ( C ) | | \
( DXX_ALWAYS_ERROR_FUNCTION ( dxx_trap_nonconstant_size , " array element size is not constant " ) , 0 ) ) )
2014-06-22 03:54:35 +00:00
# define DXX_PHYSFS_CHECK_WRITE_SIZE_ARRAY_SIZE(S,C) \
2014-09-20 23:47:27 +00:00
( ( void ) ( _DXX_PHYSFS_CHECK_SIZE ( S , C , sizeof ( v ) ) & & \
2014-07-31 03:52:57 +00:00
( DXX_ALWAYS_ERROR_FUNCTION ( dxx_trap_overread , " write size exceeds array size " ) , 0 ) ) )
2014-06-22 03:54:35 +00:00
# else
2014-09-20 23:47:27 +00:00
# define DXX_PHYSFS_CHECK_READ_SIZE_OBJECT_SIZE(S,C,v) ((void)0)
# define DXX_PHYSFS_CHECK_READ_SIZE_ARRAY_SIZE(S,C) ((void)0)
2014-09-22 03:34:08 +00:00
# define DXX_PHYSFS_CHECK_WRITE_SIZE_OBJECT_SIZE(S,C,v) ((void)0)
2014-07-31 03:52:57 +00:00
# define DXX_PHYSFS_CHECK_WRITE_ELEMENT_SIZE_CONSTANT(S,C) ((void)0)
# define DXX_PHYSFS_CHECK_WRITE_SIZE_ARRAY_SIZE(S,C) ((void)0)
2014-06-22 03:54:35 +00:00
# endif
# define DXX_PHYSFS_CHECK_WRITE_CONSTANTS(S,C) \
2014-07-31 03:52:57 +00:00
( ( void ) ( DXX_PHYSFS_CHECK_WRITE_ELEMENT_SIZE_CONSTANT ( S , C ) , \
DXX_PHYSFS_CHECK_WRITE_SIZE_ARRAY_SIZE ( S , C ) , 0 ) ) \
2014-06-22 03:54:35 +00:00
2015-12-13 18:00:49 +00:00
namespace dcx {
2015-12-13 18:00:48 +00:00
2014-06-22 03:54:35 +00:00
template < typename V >
2015-04-26 20:15:50 +00:00
__attribute_always_inline ( )
2020-05-17 23:35:25 +00:00
static inline PHYSFS_sint64 PHYSFSX_check_read ( PHYSFS_File * file , V * v , const PHYSFS_uint32 S , const PHYSFS_uint32 C )
2014-06-22 03:54:35 +00:00
{
2020-05-17 23:35:25 +00:00
if constexpr ( std : : is_integral < V > : : value )
static_assert ( std : : is_pod < V > : : value , " non-POD integral value read " ) ;
else
static_assert ( std : : is_pod < V > : : value , " non-POD non-integral value read " ) ;
2014-09-20 23:47:27 +00:00
DXX_PHYSFS_CHECK_READ_SIZE_OBJECT_SIZE ( S , C , v ) ;
2014-06-22 03:54:35 +00:00
return PHYSFS_read ( file , v , S , C ) ;
}
template < typename V , std : : size_t N >
2015-04-26 20:15:50 +00:00
__attribute_always_inline ( )
2020-05-02 21:18:42 +00:00
static inline PHYSFS_sint64 PHYSFSX_check_read ( PHYSFS_File * file , std : : array < V , N > & v , PHYSFS_uint32 S , PHYSFS_uint32 C )
2014-06-22 03:54:35 +00:00
{
2017-06-25 20:46:03 +00:00
static_assert ( std : : is_pod < V > : : value , " C++ array of non-POD elements read " ) ;
2014-09-20 23:47:27 +00:00
DXX_PHYSFS_CHECK_READ_SIZE_ARRAY_SIZE ( S , C ) ;
2014-06-22 03:54:35 +00:00
return PHYSFSX_check_read ( file , & v [ 0 ] , S , C ) ;
}
2014-07-20 03:48:27 +00:00
template < typename V , typename D >
2015-04-26 20:15:50 +00:00
__attribute_always_inline ( )
2016-01-09 16:38:14 +00:00
static inline PHYSFS_sint64 PHYSFSX_check_read ( PHYSFS_File * file , const std : : unique_ptr < V , D > & v , PHYSFS_uint32 S , PHYSFS_uint32 C )
2014-07-20 03:48:27 +00:00
{
2014-09-20 23:47:27 +00:00
return PHYSFSX_check_read ( file , v . get ( ) , S , C ) ;
2014-07-20 03:48:27 +00:00
}
2014-06-22 03:54:35 +00:00
template < typename V >
2015-04-26 20:15:50 +00:00
__attribute_always_inline ( )
2020-05-17 23:35:25 +00:00
static inline PHYSFS_sint64 PHYSFSX_check_write ( PHYSFS_File * file , const V * v , const PHYSFS_uint32 S , const PHYSFS_uint32 C )
2014-06-22 03:54:35 +00:00
{
2020-05-17 23:35:25 +00:00
if constexpr ( std : : is_integral < V > : : value )
{
static_assert ( std : : is_pod < V > : : value , " non-POD integral value written " ) ;
DXX_PHYSFS_CHECK_WRITE_ELEMENT_SIZE_CONSTANT ( S , C ) ;
}
else
static_assert ( std : : is_pod < V > : : value , " non-POD non-integral value written " ) ;
2014-09-28 21:37:37 +00:00
DXX_PHYSFS_CHECK_WRITE_SIZE_OBJECT_SIZE ( S , C , v ) ;
2014-06-22 03:54:35 +00:00
return PHYSFS_write ( file , v , S , C ) ;
}
template < typename V , std : : size_t N >
2015-04-26 20:15:50 +00:00
__attribute_always_inline ( )
2020-05-02 21:18:42 +00:00
static inline PHYSFS_sint64 PHYSFSX_check_write ( PHYSFS_File * file , const std : : array < V , N > & v , PHYSFS_uint32 S , PHYSFS_uint32 C )
2014-06-22 03:54:35 +00:00
{
2017-06-25 20:46:03 +00:00
static_assert ( std : : is_pod < V > : : value , " C++ array of non-POD elements written " ) ;
2014-06-22 03:54:35 +00:00
DXX_PHYSFS_CHECK_WRITE_CONSTANTS ( S , C ) ;
return PHYSFSX_check_write ( file , & v [ 0 ] , S , C ) ;
}
2014-07-24 03:12:57 +00:00
template < typename T , typename D >
2015-04-26 20:15:50 +00:00
__attribute_always_inline ( )
2016-01-09 16:38:14 +00:00
static inline PHYSFS_sint64 PHYSFSX_check_write ( PHYSFS_File * file , const std : : unique_ptr < T , D > & p , PHYSFS_uint32 S , PHYSFS_uint32 C )
2014-07-24 03:12:57 +00:00
{
2014-09-20 23:47:27 +00:00
return PHYSFSX_check_write ( file , p . get ( ) , S , C ) ;
2014-07-24 03:12:57 +00:00
}
2014-06-22 03:54:35 +00:00
template < typename V >
2016-01-09 16:38:14 +00:00
PHYSFS_sint64 PHYSFSX_check_read ( PHYSFS_File * file , exact_type < V > v , PHYSFS_uint32 S , PHYSFS_uint32 C ) = delete ;
2014-06-22 03:54:35 +00:00
template < typename V >
2016-01-09 16:38:14 +00:00
PHYSFS_sint64 PHYSFSX_check_write ( PHYSFS_File * file , exact_type < V > v , PHYSFS_uint32 S , PHYSFS_uint32 C ) = delete ;
2014-09-28 21:41:06 +00:00
template < typename V >
2016-01-09 16:38:14 +00:00
PHYSFS_sint64 PHYSFSX_check_read ( PHYSFS_File * file , V * * v , PHYSFS_uint32 S , PHYSFS_uint32 C ) = delete ;
2014-09-28 21:41:06 +00:00
template < typename V >
2016-01-09 16:38:14 +00:00
PHYSFS_sint64 PHYSFSX_check_write ( PHYSFS_File * file , V * * v , PHYSFS_uint32 S , PHYSFS_uint32 C ) = delete ;
2014-06-22 03:54:35 +00:00
# define PHYSFS_read(F,V,S,C) PHYSFSX_check_read(F,V,S,C)
2014-06-22 03:54:35 +00:00
# define PHYSFS_write(F,V,S,C) PHYSFSX_check_write(F,V,S,C)
2012-11-11 22:12:51 +00:00
2016-01-09 16:38:14 +00:00
static inline PHYSFS_sint16 PHYSFSX_readSXE16 ( PHYSFS_File * file , int swap )
2009-10-05 02:51:37 +00:00
{
PHYSFS_sint16 val ;
2010-06-14 08:13:16 +00:00
2009-10-05 02:51:37 +00:00
PHYSFS_read ( file , & val , sizeof ( val ) , 1 ) ;
2010-06-14 08:13:16 +00:00
2009-10-05 02:51:37 +00:00
return swap ? SWAPSHORT ( val ) : val ;
}
2016-01-09 16:38:14 +00:00
static inline PHYSFS_sint32 PHYSFSX_readSXE32 ( PHYSFS_File * file , int swap )
2009-10-05 02:51:37 +00:00
{
PHYSFS_sint32 val ;
2010-06-14 08:13:16 +00:00
2009-10-05 02:51:37 +00:00
PHYSFS_read ( file , & val , sizeof ( val ) , 1 ) ;
2010-06-14 08:13:16 +00:00
2009-10-05 02:51:37 +00:00
return swap ? SWAPINT ( val ) : val ;
}
2016-01-09 16:38:14 +00:00
static inline int PHYSFSX_writeU8 ( PHYSFS_File * file , PHYSFS_uint8 val )
2006-03-20 17:12:09 +00:00
{
return PHYSFS_write ( file , & val , 1 , 1 ) ;
}
2016-01-09 16:38:14 +00:00
static inline int PHYSFSX_writeString ( PHYSFS_File * file , const char * s )
2006-03-20 17:12:09 +00:00
{
return PHYSFS_write ( file , s , 1 , strlen ( s ) + 1 ) ;
}
2016-01-09 16:38:14 +00:00
static inline int PHYSFSX_puts ( PHYSFS_File * file , const char * s , size_t len ) __attribute_nonnull ( ) ;
static inline int PHYSFSX_puts ( PHYSFS_File * file , const char * s , size_t len )
2006-03-20 17:12:09 +00:00
{
2013-12-19 21:32:40 +00:00
return PHYSFS_write ( file , s , 1 , len ) ;
2006-03-20 17:12:09 +00:00
}
2013-12-19 21:32:40 +00:00
template < size_t len >
2016-01-09 16:38:14 +00:00
static inline int PHYSFSX_puts_literal ( PHYSFS_File * file , const char ( & s ) [ len ] ) __attribute_nonnull ( ) ;
2013-12-19 21:32:40 +00:00
template < size_t len >
2016-01-09 16:38:14 +00:00
static inline int PHYSFSX_puts_literal ( PHYSFS_File * file , const char ( & s ) [ len ] )
2013-12-19 21:32:40 +00:00
{
2014-08-26 02:41:33 +00:00
return PHYSFSX_puts ( file , s , len - 1 ) ;
2013-12-19 21:32:40 +00:00
}
# define PHYSFSX_puts(A1,S,...) (PHYSFSX_puts(A1,S, _dxx_call_puts_parameter2(1, ## __VA_ARGS__, strlen(S))))
2016-01-09 16:38:14 +00:00
static inline int PHYSFSX_fgetc ( PHYSFS_File * const fp )
2011-06-01 07:59:55 +00:00
{
unsigned char c ;
if ( PHYSFS_read ( fp , & c , 1 , 1 ) ! = 1 )
return EOF ;
return c ;
}
2016-01-09 16:38:14 +00:00
static inline int PHYSFSX_fseek ( PHYSFS_File * fp , long int offset , int where )
2011-06-01 07:59:55 +00:00
{
int c , goal_position ;
switch ( where )
{
case SEEK_SET :
goal_position = offset ;
break ;
case SEEK_CUR :
goal_position = PHYSFS_tell ( fp ) + offset ;
break ;
case SEEK_END :
goal_position = PHYSFS_fileLength ( fp ) + offset ;
break ;
default :
return 1 ;
}
c = PHYSFS_seek ( fp , goal_position ) ;
return ! c ;
}
2014-09-07 19:48:10 +00:00
template < std : : size_t N >
struct PHYSFSX_gets_line_t
{
PHYSFSX_gets_line_t ( ) = default ;
PHYSFSX_gets_line_t ( const PHYSFSX_gets_line_t & ) = delete ;
2014-12-18 04:12:38 +00:00
PHYSFSX_gets_line_t & operator = ( const PHYSFSX_gets_line_t & ) = delete ;
PHYSFSX_gets_line_t ( PHYSFSX_gets_line_t & & ) = default ;
PHYSFSX_gets_line_t & operator = ( PHYSFSX_gets_line_t & & ) = default ;
2020-05-02 21:18:42 +00:00
using line_t = std : : array < char , N > ;
2016-10-08 23:24:21 +00:00
# if DXX_HAVE_POISON
2014-09-07 19:48:10 +00:00
/* Force onto heap to improve checker accuracy */
std : : unique_ptr < line_t > m_line ;
2014-12-20 04:36:10 +00:00
const line_t & line ( ) const { return * m_line . get ( ) ; }
line_t & line ( ) { return * m_line . get ( ) ; }
line_t & next ( )
2014-09-07 19:48:10 +00:00
{
2020-05-02 21:18:42 +00:00
m_line = std : : make_unique < line_t > ( ) ;
2014-12-20 04:36:10 +00:00
return * m_line . get ( ) ;
2014-09-07 19:48:10 +00:00
}
# else
line_t m_line ;
2014-12-20 04:36:10 +00:00
const line_t & line ( ) const { return m_line ; }
line_t & line ( ) { return m_line ; }
line_t & next ( ) { return m_line ; }
2014-09-07 19:48:10 +00:00
# endif
2014-12-20 04:36:10 +00:00
operator line_t & ( ) { return line ( ) ; }
operator const line_t & ( ) const { return line ( ) ; }
operator char * ( ) { return line ( ) . data ( ) ; }
operator const char * ( ) const { return line ( ) . data ( ) ; }
typename line_t : : reference operator [ ] ( typename line_t : : size_type i ) { return line ( ) [ i ] ; }
2015-01-03 23:44:32 +00:00
typename line_t : : reference operator [ ] ( int i ) { return operator [ ] ( static_cast < typename line_t : : size_type > ( i ) ) ; }
2014-12-20 04:36:10 +00:00
typename line_t : : const_reference operator [ ] ( typename line_t : : size_type i ) const { return line ( ) [ i ] ; }
2015-01-03 23:44:32 +00:00
typename line_t : : const_reference operator [ ] ( int i ) const { return operator [ ] ( static_cast < typename line_t : : size_type > ( i ) ) ; }
2014-12-20 04:36:10 +00:00
constexpr std : : size_t size ( ) const { return N ; }
2014-12-22 04:35:48 +00:00
typename line_t : : const_iterator begin ( ) const { return line ( ) . begin ( ) ; }
typename line_t : : const_iterator end ( ) const { return line ( ) . end ( ) ; }
2014-09-07 19:48:10 +00:00
} ;
template < >
struct PHYSFSX_gets_line_t < 0 >
{
2020-05-02 21:18:42 +00:00
# define DXX_ALLOCATE_PHYSFS_LINE(n) std::make_unique<char[]>(n)
2014-09-07 19:48:10 +00:00
std : : unique_ptr < char [ ] > m_line ;
std : : size_t m_length ;
PHYSFSX_gets_line_t ( std : : size_t n ) :
2016-10-08 23:24:21 +00:00
# if !DXX_HAVE_POISON
2016-08-06 19:55:24 +00:00
m_line ( DXX_ALLOCATE_PHYSFS_LINE ( n ) ) ,
2014-12-20 04:36:10 +00:00
# endif
2014-09-07 19:48:10 +00:00
m_length ( n )
{
}
char * line ( ) { return m_line . get ( ) ; }
2014-12-20 04:36:10 +00:00
const char * line ( ) const { return m_line . get ( ) ; }
2014-09-07 19:48:10 +00:00
char * next ( )
{
2016-10-08 23:24:21 +00:00
# if DXX_HAVE_POISON
2016-08-06 19:55:24 +00:00
/* Reallocate to tell checker to undefine the buffer */
m_line = DXX_ALLOCATE_PHYSFS_LINE ( m_length ) ;
2014-09-07 19:48:10 +00:00
# endif
2014-12-20 04:36:10 +00:00
return m_line . get ( ) ;
2014-09-07 19:48:10 +00:00
}
std : : size_t size ( ) const { return m_length ; }
operator const char * ( ) const { return m_line . get ( ) ; }
const char * begin ( ) const { return * this ; }
const char * end ( ) const { return begin ( ) + m_length ; }
2014-10-12 22:11:28 +00:00
operator const void * ( ) const = delete ;
2016-08-06 19:55:24 +00:00
# undef DXX_ALLOCATE_PHYSFS_LINE
2014-09-07 19:48:10 +00:00
} ;
2015-01-12 00:26:03 +00:00
class PHYSFSX_fgets_t
2015-01-12 00:26:02 +00:00
{
2016-01-09 16:38:14 +00:00
static char * get ( char * buf , std : : size_t n , PHYSFS_File * const fp ) ;
static char * get ( char * buf , std : : size_t offset , std : : size_t n , PHYSFS_File * const fp )
2015-01-12 00:26:03 +00:00
{
if ( offset > n )
throw std : : invalid_argument ( " offset too large " ) ;
return get ( & buf [ offset ] , n - offset , fp ) ;
}
public :
template < std : : size_t n >
__attribute_nonnull ( )
2016-01-09 16:38:14 +00:00
char * operator ( ) ( PHYSFSX_gets_line_t < n > & buf , PHYSFS_File * const fp , std : : size_t offset = 0 ) const
2015-01-12 00:26:03 +00:00
{
return get ( & buf . next ( ) [ 0 ] , offset , buf . size ( ) , fp ) ;
}
template < std : : size_t n >
__attribute_nonnull ( )
2016-01-09 16:38:14 +00:00
char * operator ( ) ( ntstring < n > & buf , PHYSFS_File * const fp , std : : size_t offset = 0 ) const
2015-01-12 00:26:03 +00:00
{
auto r = get ( & buf . data ( ) [ 0 ] , offset , buf . size ( ) , fp ) ;
buf . back ( ) = 0 ;
return r ;
}
} ;
2015-01-12 00:26:02 +00:00
2015-12-13 18:00:48 +00:00
constexpr PHYSFSX_fgets_t PHYSFSX_fgets { } ;
2013-11-23 00:13:36 +00:00
2016-01-09 16:38:14 +00:00
static inline int PHYSFSX_printf ( PHYSFS_File * file , const char * format , . . . ) __attribute_format_printf ( 2 , 3 ) ;
static inline int PHYSFSX_printf ( PHYSFS_File * file , const char * format , . . . )
2013-12-19 21:32:40 +00:00
# define PHYSFSX_printf(A1,F,...) dxx_call_printf_checked(PHYSFSX_printf,PHYSFSX_puts_literal,(A1),(F),##__VA_ARGS__)
2006-03-20 17:12:09 +00:00
{
char buffer [ 1024 ] ;
va_list args ;
va_start ( args , format ) ;
2013-12-19 21:32:40 +00:00
size_t len = vsnprintf ( buffer , sizeof ( buffer ) , format , args ) ;
2013-12-01 18:27:54 +00:00
va_end ( args ) ;
2006-03-20 17:12:09 +00:00
2013-12-19 21:32:40 +00:00
return PHYSFSX_puts ( file , buffer , len ) ;
2006-03-20 17:12:09 +00:00
}
# define PHYSFSX_writeFix PHYSFS_writeSLE32
# define PHYSFSX_writeFixAng PHYSFS_writeSLE16
2016-01-09 16:38:14 +00:00
static inline int PHYSFSX_writeVector ( PHYSFS_File * file , const vms_vector & v )
2006-03-20 17:12:09 +00:00
{
2014-10-26 22:08:58 +00:00
if ( PHYSFSX_writeFix ( file , v . x ) < 1 | |
PHYSFSX_writeFix ( file , v . y ) < 1 | |
PHYSFSX_writeFix ( file , v . z ) < 1 )
2006-03-20 17:12:09 +00:00
return 0 ;
return 1 ;
}
2016-10-28 03:39:40 +00:00
__attribute_cold
2016-10-17 03:49:31 +00:00
__attribute_noreturn
void PHYSFSX_read_helper_report_error ( const char * const filename , const unsigned line , const char * const func , PHYSFS_File * const file ) ;
2011-06-01 07:59:55 +00:00
2016-10-17 03:49:31 +00:00
template < typename T , int ( * F ) ( PHYSFS_File * , T * ) >
static T PHYSFSX_read_helper ( const char * const filename , const unsigned line , const char * const func , PHYSFS_File * const file )
2011-06-01 07:59:55 +00:00
{
2016-10-17 03:49:31 +00:00
T i ;
if ( ! F ( file , & i ) )
PHYSFSX_read_helper_report_error ( filename , line , func , file ) ;
return i ;
2011-06-01 07:59:55 +00:00
}
2016-10-17 03:49:31 +00:00
template < typename T1 , int ( * F ) ( PHYSFS_File * , T1 * ) , typename T2 , T1 T2 : : * m1 , T1 T2 : : * m2 , T1 T2 : : * m3 >
static void PHYSFSX_read_sequence_helper ( const char * const filename , const unsigned line , const char * const func , PHYSFS_File * const file , T2 * const i )
2011-06-01 07:59:55 +00:00
{
2016-10-28 03:39:40 +00:00
if ( unlikely ( ! F ( file , & ( i - > * m1 ) ) | |
2016-10-17 03:49:31 +00:00
! F ( file , & ( i - > * m2 ) ) | |
2016-10-28 03:39:40 +00:00
! F ( file , & ( i - > * m3 ) ) ) )
2016-10-17 03:49:31 +00:00
PHYSFSX_read_helper_report_error ( filename , line , func , file ) ;
2011-06-01 07:59:55 +00:00
}
2016-10-17 03:49:31 +00:00
static inline int PHYSFSX_readS8 ( PHYSFS_File * const file , int8_t * const b )
2011-06-01 07:59:55 +00:00
{
2016-10-17 03:49:31 +00:00
return ( PHYSFS_read ( file , b , sizeof ( * b ) , 1 ) = = 1 ) ;
2011-06-01 07:59:55 +00:00
}
2016-10-17 03:49:31 +00:00
# define PHYSFSX_readByte(F) (PHYSFSX_read_helper<int8_t, PHYSFSX_readS8>(__FILE__, __LINE__, __func__, (F)))
# define PHYSFSX_readShort(F) (PHYSFSX_read_helper<int16_t, PHYSFS_readSLE16>(__FILE__, __LINE__, __func__, (F)))
# define PHYSFSX_readInt(F) (PHYSFSX_read_helper<int32_t, PHYSFS_readSLE32>(__FILE__, __LINE__, __func__, (F)))
# define PHYSFSX_readFix(F) (PHYSFSX_read_helper<fix, PHYSFS_readSLE32>(__FILE__, __LINE__, __func__, (F)))
# define PHYSFSX_readFixAng(F) (PHYSFSX_read_helper<fixang, PHYSFS_readSLE16>(__FILE__, __LINE__, __func__, (F)))
# 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)))
# 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)))
static inline void PHYSFSX_readMatrix ( const char * const filename , const unsigned line , const char * const func , vms_matrix * const m , PHYSFS_File * const file )
2011-06-01 07:59:55 +00:00
{
2016-10-17 03:49:31 +00:00
auto & PHYSFSX_readVector = PHYSFSX_read_sequence_helper < fix , PHYSFS_readSLE32 , vms_vector , & vms_vector : : x , & vms_vector : : y , & vms_vector : : z > ;
( PHYSFSX_readVector ) ( filename , line , func , file , & m - > rvec ) ;
( PHYSFSX_readVector ) ( filename , line , func , file , & m - > uvec ) ;
( PHYSFSX_readVector ) ( filename , line , func , file , & m - > fvec ) ;
2011-06-01 07:59:55 +00:00
}
2015-10-11 22:21:00 +00:00
# define PHYSFSX_readMatrix(M,F) ((PHYSFSX_readMatrix)(__FILE__, __LINE__, __func__, (M), (F)))
2011-06-01 07:59:55 +00:00
2012-03-03 08:03:03 +00:00
# define PHYSFSX_contfile_init PHYSFSX_addRelToSearchPath
# define PHYSFSX_contfile_close PHYSFSX_removeRelFromSearchPath
2015-01-17 18:31:42 +00:00
class PHYSFS_File_deleter
{
public :
int operator ( ) ( PHYSFS_File * fp ) const
{
return PHYSFS_close ( fp ) ;
}
} ;
class RAIIPHYSFS_File : public std : : unique_ptr < PHYSFS_File , PHYSFS_File_deleter >
{
typedef std : : unique_ptr < PHYSFS_File , PHYSFS_File_deleter > base_t ;
public :
DXX_INHERIT_CONSTRUCTORS ( RAIIPHYSFS_File , base_t ) ;
using base_t : : operator bool ;
2015-01-29 00:58:53 +00:00
operator PHYSFS_File * ( ) const & & = delete ;
2016-12-10 17:51:07 +00:00
operator PHYSFS_File * ( ) const &
2015-01-29 00:58:53 +00:00
{
return get ( ) ;
}
2015-01-17 18:31:42 +00:00
int close ( )
{
/* Like reset(), but returns result */
int r = get_deleter ( ) ( get ( ) ) ;
if ( r )
release ( ) ;
return r ;
}
template < typename T >
bool operator = = ( T ) const = delete ;
template < typename T >
bool operator ! = ( T ) const = delete ;
} ;
2013-11-26 22:19:52 +00:00
typedef char file_extension_t [ 5 ] ;
2015-02-14 22:48:28 +00:00
__attribute_nonnull ( )
__attribute_warn_unused_result
2015-08-14 03:02:04 +00:00
int PHYSFSX_checkMatchingExtension ( const char * filename , const partial_range_t < const file_extension_t * > ) ;
2015-02-14 22:48:28 +00:00
template < std : : size_t count >
__attribute_nonnull ( )
__attribute_warn_unused_result
2020-05-02 21:18:42 +00:00
static inline int PHYSFSX_checkMatchingExtension ( const std : : array < file_extension_t , count > & exts , const char * filename )
2015-02-14 22:48:28 +00:00
{
2015-08-14 03:02:04 +00:00
return PHYSFSX_checkMatchingExtension ( filename , exts ) ;
2015-02-14 22:48:28 +00:00
}
2012-07-22 23:17:54 +00:00
extern int PHYSFSX_addRelToSearchPath ( const char * relname , int add_to_end ) ;
extern int PHYSFSX_removeRelFromSearchPath ( const char * relname ) ;
extern int PHYSFSX_fsize ( const char * hogname ) ;
2010-11-26 11:50:18 +00:00
extern void PHYSFSX_listSearchPathContent ( ) ;
2015-10-11 22:21:00 +00:00
int PHYSFSX_getRealPath ( const char * stdPath , char * realPath , std : : size_t ) ;
template < std : : size_t N >
2020-05-02 21:18:42 +00:00
static inline int PHYSFSX_getRealPath ( const char * stdPath , std : : array < char , N > & realPath )
2015-10-11 22:21:00 +00:00
{
return PHYSFSX_getRealPath ( stdPath , realPath . data ( ) , N ) ;
}
2012-07-22 23:17:54 +00:00
extern int PHYSFSX_isNewPath ( const char * path ) ;
extern int PHYSFSX_rename ( const char * oldpath , const char * newpath ) ;
2015-01-23 03:55:05 +00:00
2015-05-09 17:39:02 +00:00
# define PHYSFSX_exists(F,I) ((I) ? PHYSFSX_exists_ignorecase(F) : PHYSFS_exists(F))
int PHYSFSX_exists_ignorecase ( const char * filename ) ;
2015-01-17 18:31:42 +00:00
RAIIPHYSFS_File PHYSFSX_openReadBuffered ( const char * filename ) ;
RAIIPHYSFS_File PHYSFSX_openWriteBuffered ( const char * filename ) ;
2010-08-15 06:57:51 +00:00
extern void PHYSFSX_addArchiveContent ( ) ;
extern void PHYSFSX_removeArchiveContent ( ) ;
2015-12-13 18:00:48 +00:00
}
2016-01-09 16:38:15 +00:00
# ifdef dsx
2015-12-13 18:00:49 +00:00
namespace dsx {
2015-12-13 18:00:48 +00:00
bool PHYSFSX_init ( int argc , char * argv [ ] ) ;
int PHYSFSX_checkSupportedArchiveTypes ( ) ;
}
# endif
2007-05-20 02:00:57 +00:00
2012-11-11 22:12:51 +00:00
# endif