00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "OSDLUtils.h"
00028
00029 #include "OSDLEmbeddedFileSystemManager.h"
00030
00031 #include "Ceylan.h"
00032
00033
00034
00035 #ifdef OSDL_USES_CONFIG_H
00036 #include "OSDLConfig.h"
00037 #endif // OSDL_USES_CONFIG_H
00038
00039 #if OSDL_ARCH_NINTENDO_DS
00040 #include "OSDLConfigForNintendoDS.h"
00041 #endif // OSDL_ARCH_NINTENDO_DS
00042
00043
00044 #if OSDL_USES_SDL
00045 #include "SDL.h"
00046 #endif // OSDL_USES_SDL
00047
00048
00049 #if OSDL_USES_PHYSICSFS
00050 #include "physfs.h"
00051 #endif // OSDL_USES_PHYSICSFS
00052
00053
00054
00055 #include <cstdio>
00056
00057
00058 using namespace OSDL ;
00059 using namespace OSDL::Utils ;
00060
00061 using namespace Ceylan::Log ;
00062 using namespace Ceylan::System ;
00063
00064 using std::string ;
00065
00066
00067
00068
00069 const string OSDL::Utils::getBackendLastError()
00070 {
00071
00072 #if OSDL_USES_SDL
00073
00074 return SDL_GetError() ;
00075
00076 #else // OSDL_USES_SDL
00077
00078
00079 return Ceylan::System::explainError() ;
00080
00081 #endif // OSDL_USES_SDL
00082
00083 }
00084
00085
00086
00087 Ceylan::Latin1Char OSDL::Utils::getNativeDirectorySeparator()
00088 {
00089
00090 #if OSDL_USES_PHYSICSFS
00091
00092 string res( PHYSFS_getDirSeparator() );
00093
00094 switch( res.size() )
00095 {
00096
00097 case 0:
00098 throw OSDL::Exception( "OSDL::Utils::getNativeDirectorySeparator "
00099 "failed: empty separator found." ) ;
00100 break ;
00101
00102 case 1:
00103 return static_cast<Ceylan::Latin1Char>( res[0] ) ;
00104 break ;
00105
00106 default:
00107 throw OSDL::Exception( "OSDL::Utils::getNativeDirectorySeparator "
00108 "failed: multi-character separator found (" + res + ")." ) ;
00109 break ;
00110
00111 }
00112
00113
00114 return 0 ;
00115
00116 #else // OSDL_USES_PHYSICSFS
00117
00118 throw OSDL::Exception( "OSDL::Utils::getNativeDirectorySeparator "
00119 "failed: no PhysicsFS support available." ) ;
00120
00121 #endif // OSDL_USES_PHYSICSFS
00122
00123 }
00124
00125
00126
00127 std::string OSDL::Utils::getProgramPath()
00128 {
00129
00130 #if OSDL_USES_PHYSICSFS
00131
00132
00133 EmbeddedFileSystemManager::SecureEmbeddedFileSystemManager() ;
00134
00135 return std::string( PHYSFS_getBaseDir() ) ;
00136
00137 #else // OSDL_USES_PHYSICSFS
00138
00139 throw OSDL::Exception( "OSDL::Utils::getProgramPath failed:"
00140 "no PhysicsFS support available." ) ;
00141
00142 #endif // OSDL_USES_PHYSICSFS
00143
00144 }
00145
00146
00147
00148 std::string OSDL::Utils::getUserDirectory()
00149 {
00150
00151 #if OSDL_USES_PHYSICSFS
00152
00153
00154 EmbeddedFileSystemManager::SecureEmbeddedFileSystemManager() ;
00155
00156 return std::string( PHYSFS_getUserDir() ) ;
00157
00158 #else // OSDL_USES_PHYSICSFS
00159
00160 throw OSDL::Exception( "OSDL::Utils::getUserDirectory failed:"
00161 "no PhysicsFS support available." ) ;
00162
00163 #endif // OSDL_USES_PHYSICSFS
00164
00165 }
00166
00167
00168
00169
00170
00190 static int seekCallback( DataStream * datastream, int offset, int whence )
00191 {
00192
00193
00194
00195 Ceylan::System::File & myFile = * reinterpret_cast<Ceylan::System::File *>(
00196 datastream->hidden.unknown.data1 ) ;
00197
00198 Position pos ;
00199
00200 string seek ;
00201
00202 try
00203 {
00204
00205 switch( whence )
00206 {
00207
00208 case SEEK_SET:
00209
00210 pos = offset ;
00211 break ;
00212
00213 case SEEK_CUR:
00214
00215 pos = myFile.tell() + offset ;
00216 break ;
00217
00218 case SEEK_END:
00219
00220
00221
00222
00223
00224
00225 pos = myFile.size() + offset ;
00226 break ;
00227
00228 default:
00229 LogPlug::error( "OSDL::Utils seekCallback failed: "
00230 "unexpected 'whence' parameter." ) ;
00231 return -1 ;
00232 break ;
00233
00234 }
00235
00236 if ( pos < 0 )
00237 {
00238
00239 LogPlug::error( "OSDL::Utils seekCallback failed: "
00240 "attempt to seek past start of file." ) ;
00241
00242 return -1 ;
00243
00244 }
00245
00246
00247 myFile.seek( pos ) ;
00248
00249
00250
00251
00252
00253
00254
00255
00256 }
00257 catch( const Ceylan::Exception & e )
00258 {
00259
00260 LogPlug::error( "OSDL::Utils seekCallback failed: " + e.toString() ) ;
00261
00262 }
00263
00264
00265 return pos ;
00266
00267 }
00268
00269
00270
00271
00278 static int readCallback( DataStream * datastream, void *buffer, int chunkSize,
00279 int chunkCount )
00280 {
00281
00282
00283
00284 Ceylan::System::File & myFile = * reinterpret_cast<Ceylan::System::File *>(
00285 datastream->hidden.unknown.data1 ) ;
00286
00287 Size readSize ;
00288
00289 try
00290 {
00291
00292 readSize = myFile.read( static_cast<Ceylan::Byte*>( buffer ),
00293 chunkSize*chunkCount ) ;
00294
00295 }
00296 catch( const Ceylan::Exception & e )
00297 {
00298
00299 LogPlug::error( "OSDL::Utils readCallback failed: " + e.toString() ) ;
00300
00301 }
00302
00303 if ( readSize % chunkSize != 0 )
00304 {
00305
00306 LogPlug::error( "OSDL::Utils readCallback failed: "
00307 "fractional chunk read." ) ;
00308
00309 return -1 ;
00310
00311 }
00312
00313
00314
00315
00316
00317
00318
00319
00320 return ( readSize / chunkSize ) ;
00321
00322 }
00323
00324
00325
00332 static int writeCallback( DataStream * datastream, const void *buffer,
00333 int chunkSize, int chunkCount )
00334 {
00335
00336
00337
00338 Ceylan::System::File & myFile = * reinterpret_cast<Ceylan::System::File *>(
00339 datastream->hidden.unknown.data1 ) ;
00340
00341 Size writtenSize ;
00342
00343 try
00344 {
00345
00346 writtenSize = myFile.write( static_cast<const Ceylan::Byte*>( buffer ),
00347 chunkSize*chunkCount ) ;
00348
00349 }
00350 catch( const Ceylan::Exception & e )
00351 {
00352
00353 LogPlug::error( "OSDL::Utils writeCallback failed: " + e.toString() ) ;
00354
00355 }
00356
00357 if ( writtenSize % chunkSize != 0 )
00358 {
00359
00360 LogPlug::error( "OSDL::Utils writeCallback failed: "
00361 "fractional chunk read." ) ;
00362
00363 return -1 ;
00364
00365 }
00366
00367
00368 return ( writtenSize / chunkSize ) ;
00369
00370 }
00371
00372
00373
00380 static int closeCallback( DataStream * datastream )
00381 {
00382
00383
00384
00385 Ceylan::System::File & myFile = * reinterpret_cast<Ceylan::System::File *>(
00386 datastream->hidden.unknown.data1 ) ;
00387
00388 try
00389 {
00390
00391 myFile.close() ;
00392
00393 }
00394 catch( const Ceylan::Exception & e )
00395 {
00396
00397 LogPlug::error( "OSDL::Utils closeCallback failed: " + e.toString() ) ;
00398
00399 return -1 ;
00400
00401 }
00402
00403
00404
00405
00406
00407
00408 delete & myFile ;
00409
00410 SDL_FreeRW( datastream ) ;
00411
00412 return 0 ;
00413
00414 }
00415
00416
00417
00418 OSDL::Utils::DataStream & OSDL::Utils::createDataStreamFrom(
00419 Ceylan::System::File & sourceFile )
00420 {
00421
00422 #if OSDL_USES_SDL
00423
00424
00425
00426
00427
00428
00429
00430
00431 SDL_RWops * res = SDL_AllocRW() ;
00432
00433 if ( res == 0 )
00434 throw OSDL::Exception( "OSDL::Utils::createDataStreamFrom failed: "
00435 "unable to create a SDL_RWops." ) ;
00436
00437
00438
00439 res->seek = seekCallback ;
00440 res->read = readCallback ;
00441 res->write = writeCallback ;
00442 res->close = closeCallback ;
00443
00444 res->hidden.unknown.data1 = & sourceFile ;
00445
00446 return *res ;
00447
00448 #else // OSDL_USES_SDL
00449
00450 throw OSDL::Exception( "OSDL::Utils::createDataStreamFrom failed: "
00451 "no SDL support available." ) ;
00452
00453 #endif // OSDL_USES_SDL
00454
00455 }
00456
00457
00458
00459 void OSDL::Utils::deleteDataStream( DataStream & datastream )
00460 {
00461
00462 #if OSDL_USES_SDL
00463
00464 SDL_FreeRW( &datastream ) ;
00465
00466 #else // OSDL_USES_SDL
00467
00468 throw OSDL::Exception( "OSDL::Utils::deleteDataStream failed: "
00469 "no SDL support available." ) ;
00470
00471 #endif // OSDL_USES_SDL
00472
00473 }
00474