2015-07-16 18:24:54 +00:00
/*
* This file is part of the Colobot : Gold Edition source code
2015-08-22 14:40:02 +00:00
* Copyright ( C ) 2001 - 2015 , Daniel Roux , EPSITEC SA & TerranovaTeam
* http : //epsitec.ch; http://colobot.info; http://github.com/colobot
2015-07-16 18:24:54 +00:00
*
* This program is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , either version 3 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE .
* See the GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program . If not , see http : //gnu.org/licenses
*/
# include "common/resources/sdl_file_wrapper.h"
# include "common/logger.h"
# include <physfs.h>
namespace
{
const Uint32 PHYSFS_RWOPS_TYPE = 0xc010b04f ;
}
CSDLFileWrapper : : CSDLFileWrapper ( const std : : string & filename )
: m_rwops ( nullptr )
{
if ( ! PHYSFS_isInit ( ) )
{
2015-07-16 19:30:55 +00:00
GetLogger ( ) - > Error ( " PHYSFS not initialized! \n " ) ;
2015-07-16 18:24:54 +00:00
return ;
}
PHYSFS_File * file = PHYSFS_openRead ( filename . c_str ( ) ) ;
if ( file = = nullptr )
{
2015-07-16 19:30:55 +00:00
GetLogger ( ) - > Error ( " Error opening file with PHYSFS: \" %s \" \n " , filename . c_str ( ) ) ;
2015-07-16 18:24:54 +00:00
return ;
}
m_rwops = SDL_AllocRW ( ) ;
if ( m_rwops = = nullptr )
{
2015-07-16 19:30:55 +00:00
GetLogger ( ) - > Error ( " Unable to allocate SDL_RWops for \" %s \" \n " , filename . c_str ( ) ) ;
2015-07-16 18:24:54 +00:00
return ;
}
2015-09-24 19:09:46 +00:00
m_rwops - > type = PHYSFS_RWOPS_TYPE ; //TODO: Documentation recommends to leave SDL_RWOPS_UNKNOWN here for application-defined RWops. Did that change in SDL2?
2015-07-16 18:24:54 +00:00
m_rwops - > hidden . unknown . data1 = file ;
m_rwops - > seek = SDLSeek ;
m_rwops - > read = SDLRead ;
m_rwops - > write = SDLWrite ;
2015-09-24 19:09:46 +00:00
m_rwops - > size = SDLSize ;
2015-07-16 18:24:54 +00:00
// This is safe because SDL_FreeRW will be called in destructor
m_rwops - > close = SDLCloseWithoutFreeRW ;
}
CSDLFileWrapper : : ~ CSDLFileWrapper ( )
{
SDLCloseWithFreeRW ( m_rwops ) ;
}
SDL_RWops * CSDLFileWrapper : : GetHandler ( )
{
return m_rwops ;
}
bool CSDLFileWrapper : : IsOpen ( ) const
{
return m_rwops ! = nullptr ;
}
int CSDLFileWrapper : : SDLClose ( SDL_RWops * context , bool freeRW )
{
if ( context = = nullptr )
return 0 ;
2015-08-12 19:07:16 +00:00
if ( ! CheckSDLContext ( context ) )
return 1 ;
2015-07-16 18:24:54 +00:00
2015-08-12 19:07:16 +00:00
if ( context - > hidden . unknown . data1 ! = nullptr )
{
PHYSFS_close ( static_cast < PHYSFS_File * > ( context - > hidden . unknown . data1 ) ) ;
context - > hidden . unknown . data1 = nullptr ;
2015-07-16 18:24:54 +00:00
}
2015-08-12 19:07:16 +00:00
if ( freeRW )
SDL_FreeRW ( context ) ;
return 0 ;
2015-07-16 18:24:54 +00:00
}
int CSDLFileWrapper : : SDLCloseWithoutFreeRW ( SDL_RWops * context )
{
return SDLClose ( context , false ) ;
}
int CSDLFileWrapper : : SDLCloseWithFreeRW ( SDL_RWops * context )
{
return SDLClose ( context , true ) ;
}
bool CSDLFileWrapper : : CheckSDLContext ( SDL_RWops * context )
{
if ( context - > type ! = PHYSFS_RWOPS_TYPE )
{
SDL_SetError ( " Wrong kind of RWops " ) ;
return false ;
}
return true ;
}
2015-09-24 19:09:46 +00:00
Sint64 CSDLFileWrapper : : SDLSeek ( SDL_RWops * context , Sint64 offset , int whence )
2015-07-16 18:24:54 +00:00
{
if ( CheckSDLContext ( context ) )
{
PHYSFS_File * file = static_cast < PHYSFS_File * > ( context - > hidden . unknown . data1 ) ;
switch ( whence )
{
default :
case RW_SEEK_SET :
{
2015-08-30 20:18:49 +00:00
auto result = PHYSFS_seek ( file , offset ) ;
2015-08-30 20:11:50 +00:00
return ( result ! = 0 ) ? offset : - 1 ;
2015-07-16 18:24:54 +00:00
}
case RW_SEEK_CUR :
{
int position = offset + PHYSFS_tell ( file ) ;
2015-08-30 20:18:49 +00:00
auto result = PHYSFS_seek ( file , position ) ;
2015-08-30 20:11:50 +00:00
return ( result ! = 0 ) ? position : - 1 ;
2015-07-16 18:24:54 +00:00
}
case RW_SEEK_END :
{
int position = PHYSFS_fileLength ( file ) - offset ;
2015-08-30 20:11:50 +00:00
auto result = PHYSFS_seek ( file , position ) ;
return ( result ! = 0 ) ? position : - 1 ;
2015-07-16 18:24:54 +00:00
}
}
}
return - 1 ;
}
2015-09-24 19:09:46 +00:00
Sint64 CSDLFileWrapper : : SDLSize ( SDL_RWops * context )
{
return - 1 ; // Not needed for now
}
size_t CSDLFileWrapper : : SDLRead ( SDL_RWops * context , void * ptr , size_t size , size_t maxnum )
2015-07-16 18:24:54 +00:00
{
if ( CheckSDLContext ( context ) )
{
PHYSFS_File * file = static_cast < PHYSFS_File * > ( context - > hidden . unknown . data1 ) ;
SDL_memset ( ptr , 0 , size * maxnum ) ;
2015-08-30 20:18:49 +00:00
auto result = PHYSFS_read ( file , ptr , size , maxnum ) ;
return ( result > = 0 ) ? result : 0 ;
2015-07-16 18:24:54 +00:00
}
return 0 ;
}
2015-09-24 19:09:46 +00:00
size_t CSDLFileWrapper : : SDLWrite ( SDL_RWops * context , const void * ptr , size_t size , size_t num )
2015-07-16 18:24:54 +00:00
{
2015-09-24 19:09:46 +00:00
assert ( ! ! " Writing to CSDLFileWrapper is currently not supported " ) ;
2015-07-16 18:24:54 +00:00
return 0 ;
}