Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

pgfilearchive.cpp

Go to the documentation of this file.
00001 /*
00002     ParaGUI - crossplatform widgetset
00003     Copyright (C) 2000,2001,2002  Alexander Pipelka
00004  
00005     This library is free software; you can redistribute it and/or
00006     modify it under the terms of the GNU Library General Public
00007     License as published by the Free Software Foundation; either
00008     version 2 of the License, or (at your option) any later version.
00009  
00010     This library is distributed in the hope that it will be useful,
00011     but WITHOUT ANY WARRANTY; without even the implied warranty of
00012     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013     Library General Public License for more details.
00014  
00015     You should have received a copy of the GNU Library General Public
00016     License along with this library; if not, write to the Free
00017     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00018  
00019     Alexander Pipelka
00020     pipelka@teleweb.at
00021  
00022     Last Update:      $Author: mbickel $
00023     Update Date:      $Date: 2008-02-01 22:15:09 $
00024     Source File:      $Source: /home/cvspsrv/cvsroot/games/asc/source/libs/paragui/src/core/pgfilearchive.cpp,v $
00025     CVS/RCS Revision: $Revision: 1.4 $
00026     Status:           $State: Exp $
00027 */
00028 
00029 #include "physfs.h"
00030 #include "pgfilearchive.h"
00031 #include "pgapplication.h"
00032 #include "pglog.h"
00033 #include "pgfont.h"
00034 
00036 #include "physfsrwops.h"
00037 #include <iostream>
00038 #include <cstring>
00039 #include "paragui.h"
00040 
00041 Uint32 PG_FileArchive::my_instance_count = 0;
00042 PG_SurfaceCache PG_FileArchive::my_cache;
00043 #ifdef PG_LOAD_SDL_IMAGE_DYNAMICALLY
00044 static void* SDL_image_obj = NULL;
00045 #else
00046 #include <SDL_image.h>
00047 #endif
00048 
00049 typedef SDL_Surface* (*IMG_Load_RW_FT)(SDL_RWops* src, int freesrc);
00050 static IMG_Load_RW_FT IMG_Load_RW_FUNC = NULL;
00051 
00052 void PG_FileArchive::init( const char* argv0 )
00053 {
00054    // First instance ? -> initialize PhysFS
00055    if(my_instance_count == 1) {
00056       if(PHYSFS_init(argv0) == 0) {
00057          std::cerr << "Unable to initialize PhysicsFS !" << std::endl;
00058          const char* errstr = PHYSFS_getLastError();
00059          if ( errstr )
00060             std::cerr << errstr;
00061          return;
00062       }
00063 
00064 #ifdef PG_LOAD_SDL_IMAGE_DYNAMICALLY
00065       // try different names to find SDL_image
00066       SDL_image_obj = SDL_LoadObject(SDLIMAGE_LIB);
00067       if(SDL_image_obj == NULL) {
00068          PG_LogMSG("SDL_image not found! Only bmp images can be loaded!");
00069       } else {
00070          IMG_Load_RW_FUNC = (IMG_Load_RW_FT)SDL_LoadFunction(SDL_image_obj, "IMG_Load_RW");
00071          if(IMG_Load_RW_FUNC == NULL) {
00072             PG_LogERR("Unable to load IMG_Load_RW function. SDL_image disabled!");
00073             SDL_UnloadObject(SDL_image_obj);
00074             SDL_image_obj = NULL;
00075          }
00076       }
00077 #else
00078          IMG_Load_RW_FUNC = IMG_Load_RW;
00079 #endif
00080    }
00081 }
00082 
00083 PG_FileArchive::PG_FileArchive() {
00084    // increment instance count
00085    my_instance_count++;
00086    
00087    init( "paragui" );
00088 }
00089 
00090 PG_FileArchive::PG_FileArchive( const char* argv0 ) {
00091    // increment instance count
00092    my_instance_count++;
00093    
00094    init( argv0 );
00095 }
00096 
00097 
00098 PG_FileArchive::~PG_FileArchive() {
00099 
00100         if(my_instance_count == 0) {
00101                 return;
00102         }
00103 
00104         // decrement instance count
00105         my_instance_count--;
00106 
00107         if(my_instance_count == 0) {
00108                 Deinit();
00109 #ifdef PG_LOAD_SDL_IMAGE_DYNAMICALLY
00110                 if(SDL_image_obj != NULL) {
00111                         SDL_UnloadObject(SDL_image_obj);
00112                         SDL_image_obj = NULL;
00113                 }
00114 #endif
00115         }
00116 }
00117 
00118 void PG_FileArchive::Deinit() {
00119         PHYSFS_deinit();
00120 }
00121 
00122 std::string *PG_FileArchive::PathToPlatform(const std::string& path) {
00123         std::string *newpath;
00124         const char* sep = GetDirSeparator();
00125         std::string::size_type pos = 0, incr;
00126         newpath = new std::string(path);
00127         incr = std::strlen(sep);
00128         if(incr == 1 && sep[0] == '/')
00129                 return newpath;
00130 
00131 #ifdef __MACOS__
00132 
00133         while( (pos = newpath->find(":", pos)) != std::string::npos) {
00134 #else
00135         while( (pos = newpath->find("/", pos)) != std::string::npos) {
00136 #endif
00137                 newpath->replace(pos, 1, sep);
00138                 pos += incr;
00139         }
00140         return newpath;
00141 }
00142 
00143 
00144 bool PG_FileArchive::AddArchive(const std::string& arch, bool append) {
00145         std::string *newpath = PathToPlatform(arch);
00146         bool ret = (PHYSFS_addToSearchPath(newpath->c_str(),  append) != 0);
00147         delete newpath;
00148         return ret;
00149 }
00150 
00151 bool PG_FileArchive::RemoveArchive(const std::string& arch) {
00152         std::string *newpath = PathToPlatform(arch);
00153         bool ret = (PHYSFS_removeFromSearchPath(newpath->c_str()) != 0);
00154         delete newpath;
00155         return ret;
00156 }
00157 
00158 char **PG_FileArchive::EnumerateFiles(const std::string& dir) {
00159         return PHYSFS_enumerateFiles(dir.c_str());
00160 }
00161 
00162 PG_FileList* PG_FileArchive::GetFileList(const std::string& dir, const std::string& wildcard) {
00163         char **tempList = EnumerateFiles(dir);
00164 
00165         if( tempList == NULL ) {
00166                 return NULL;
00167         }
00168 
00169         PG_FileList* retVal = new PG_FileList;
00170 
00171         for( char** i = tempList; *i != NULL; i++) {
00172                 if(fnmatch(wildcard.c_str(), *i, FNM_PATHNAME) == 0) {
00173                         retVal->push_back(std::string(*i));
00174                 }
00175         }
00176 
00177         // Clean up.
00178         PHYSFS_freeList(tempList);
00179 
00180         return retVal;
00181 }
00182 
00183 bool PG_FileArchive::Exists(const std::string& filename) {
00184         return PHYSFS_exists(filename.c_str()) != 0;
00185 }
00186 
00187 bool PG_FileArchive::IsDirectory(const std::string& filename) {
00188         return PHYSFS_isDirectory(filename.c_str()) != 0;
00189 }
00190 
00191 const char* PG_FileArchive::GetDirSeparator() {
00192         return PHYSFS_getDirSeparator();
00193 }
00194 
00195 const char* PG_FileArchive::GetRealDir(const std::string& filename) {
00196         return PHYSFS_getRealDir(filename.c_str());
00197 }
00198 
00199 const char* PG_FileArchive::GetLastError() {
00200         return PHYSFS_getLastError();
00201 }
00202 
00203 const char* PG_FileArchive::GetBaseDir() {
00204         return PHYSFS_getBaseDir();
00205 }
00206 
00207 const char* PG_FileArchive::GetUserDir() {
00208         return PHYSFS_getUserDir();
00209 }
00210 
00211 const char* PG_FileArchive::GetWriteDir() {
00212         return PHYSFS_getWriteDir();
00213 }
00214 
00215 PG_File* PG_FileArchive::OpenFile(const std::string& filename, Mode mode) {
00216         PHYSFS_file* file = 0;
00217         switch(mode) {
00218                 case READ:
00219                         file = PHYSFS_openRead(filename.c_str());
00220                         break;
00221                 case WRITE:
00222                         file = PHYSFS_openWrite(filename.c_str());
00223                         break;
00224                 case APPEND:
00225                         file = PHYSFS_openAppend(filename.c_str());
00226                         break;
00227         }
00228         if(file == NULL) {
00229                 return NULL;
00230         }
00231 
00232         return new PG_File(file);
00233 }
00234 
00235 SDL_RWops* PG_FileArchive::OpenFileRWops(const std::string& filename, Mode mode) {
00236         SDL_RWops* file = NULL;
00237         switch(mode) {
00238                 case READ:
00239                         file = PHYSFSRWOPS_openRead(filename.c_str());
00240                         break;
00241                 case WRITE:
00242                         file = PHYSFSRWOPS_openWrite(filename.c_str());
00243                         break;
00244                 case APPEND:
00245                         file = PHYSFSRWOPS_openAppend(filename.c_str());
00246                         break;
00247         }
00248 
00249         return file;
00250 }
00251 
00252 bool PG_FileArchive::MakeDir(const std::string& dir) {
00253         return PHYSFS_mkdir(dir.c_str()) == 1;
00254 }
00255 bool PG_FileArchive::SetWriteDir(const std::string& dir) {
00256         if(PHYSFS_setWriteDir(dir.c_str())) {
00257                 return PHYSFS_addToSearchPath(dir.c_str(), 0) == 1;
00258         } else {
00259                 return false;
00260         }
00261 }
00262 
00263 bool PG_FileArchive::SetSaneConfig(const std::string& organization,
00264                                    const std::string& appName,
00265                                    const std::string& archiveExt,
00266                                    bool includeCdRoms,
00267                                    bool archivesFirst) {
00268         return PHYSFS_setSaneConfig(organization.c_str(), appName.c_str(), archiveExt.c_str(),
00269                                     includeCdRoms, archivesFirst) == 1;
00270 }
00271 
00272 
00273 PG_DataContainer* PG_FileArchive::ReadFile(const std::string& filename) {
00274         PG_File *file = OpenFile(filename);
00275 
00276         if(!file) {
00277                 return 0;
00278         }
00279 
00280         int size = file->fileLength();
00281 
00282         if(size <= 0) {
00283                 delete file;
00284                 return 0;
00285         }
00286 
00287         PG_DataContainer* data = new PG_DataContainer(size);
00288 
00289         if(file->read(data->data(), size, 1) != 1) {
00290                 delete data;
00291                 delete file;
00292                 return NULL;
00293         }
00294 
00295         delete file;
00296 
00297         return data;
00298 }
00299 
00300 SDL_Surface* PG_FileArchive::LoadSurface(const std::string& filename, bool convert) {
00301         return LoadSurface(filename, false, 0, convert);
00302 }
00303 
00304 SDL_Surface* PG_FileArchive::LoadSurface(const std::string& filename, bool usekey, Uint32 colorkey, bool convert) {
00305         if(filename.empty() || filename == "none") {
00306                 return NULL;
00307         }
00308 
00309         // take a look into the cache
00310         SDL_Surface* surface = my_cache.FindSurface(filename);
00311 
00312         // return the cache surface if it has been found
00313         if(surface != NULL) {
00314                 my_cache.IncRef(filename);
00315                 return surface;
00316         }
00317 
00318         surface = NULL;
00319         SDL_RWops *rw = OpenFileRWops(filename);
00320 
00321         if(rw == NULL) {
00322                 PG_LogWRN("Unable to open '%s' !", filename.c_str());
00323                 return NULL;
00324         }
00325 
00326         if(IMG_Load_RW_FUNC != NULL) {
00327                 surface = IMG_Load_RW_FUNC(rw, 1);
00328         } else {
00329                 surface = SDL_LoadBMP_RW(rw, 1);
00330         }
00331 
00332         if(surface == NULL) {
00333                 PG_LogWRN("Failed to load imagedata from '%s' !", filename.c_str());
00334                 return NULL;
00335         }
00336 
00337         if(surface == NULL) {
00338                 PG_LogERR("Unable to load imagedata from '%s'", filename.c_str());
00339                 PG_LogERR("PhysFS reported: '%s'", PG_FileArchive::GetLastError());
00340                 PG_LogERR("SDL reported: '%s'", SDL_GetError());
00341         }
00342 
00343         if(usekey == true) {
00344                 SDL_SetColorKey(surface, SDL_SRCCOLORKEY, colorkey);
00345         }
00346 
00347         if(convert) {
00348                 SDL_Surface* tmpsrf = NULL;
00349                 if (surface->flags & SDL_SRCALPHA)
00350                         tmpsrf = SDL_DisplayFormatAlpha(surface);
00351                 else
00352                         tmpsrf = SDL_DisplayFormat(surface);
00353 
00354                 if(tmpsrf) {
00355                         SDL_FreeSurface(surface);
00356                         surface = tmpsrf;
00357                 }
00358         }
00359 
00360         // add the loaded surface to the cache and return result
00361         return my_cache.AddSurface(filename, surface);
00362 }
00363 
00364 bool PG_FileArchive::UnloadSurface(SDL_Surface* surface, bool bDeleteIfNotExists) {
00365         my_cache.DeleteSurface(surface, bDeleteIfNotExists);
00366         return true;
00367 }
00368 
00369 bool PG_FileArchive::RemoveAllArchives() {
00370         char** i = GetSearchPath();
00371         char** d;
00372         bool success = true;
00373 
00374         for(d = i; *d != NULL; d++) {
00375                 if(!RemoveArchive(*d)) {
00376                         PG_LogWRN("Unable to remove '%s' from searchpath!", *d);
00377                         success = false;
00378                 }
00379         }
00380 
00381         FreeList(i);
00382         return success;
00383 }
00384 
00385 char** PG_FileArchive::GetSearchPath() {
00386         return PHYSFS_getSearchPath();
00387 }
00388 
00389 PG_FileList* PG_FileArchive::GetSearchPathList() {
00390         char **tempList = PHYSFS_getSearchPath();
00391 
00392         if( tempList == NULL ) {
00393                 return NULL;
00394         }
00395 
00396         PG_FileList* retVal = NULL;
00397 
00398         // Scan through to get the length of the listing to get the proper vector size.
00399         Uint32 size = 0;
00400         for(; tempList[ size ] != NULL; ++size) {}
00401 
00402         // Now we're ready to initialize everything.
00403         retVal = new std::vector< std::string >;
00404         retVal->reserve( size );
00405         for( Uint32 i = 0; i < size; ++i ) {
00406                 retVal->push_back(std::string(tempList[ i ]));
00407         }
00408 
00409         // Clean up.
00410         PHYSFS_freeList(tempList);
00411 
00412         return retVal;
00413 }
00414 
00415 void PG_FileArchive::FreeList(void* list) {
00416         PHYSFS_freeList(list);
00417 }
00418 
00419 void PG_FileArchive::EnableSymlinks(bool followSymlinks) {
00420         PHYSFS_permitSymbolicLinks(followSymlinks);
00421 }
00422 
00423 /*
00424  * Local Variables:
00425  * c-basic-offset: 8
00426  * End:
00427  */

Generated on Tue Jun 24 01:27:47 2008 for Advanced Strategic Command by  doxygen 1.4.2