00001 /****************************************************************************** 00002 * Copyright (c) 1998, Frank Warmerdam 00003 * 00004 * Permission is hereby granted, free of charge, to any person obtaining a 00005 * copy of this software and associated documentation files (the "Software"), 00006 * to deal in the Software without restriction, including without limitation 00007 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 00008 * and/or sell copies of the Software, and to permit persons to whom the 00009 * Software is furnished to do so, subject to the following conditions: 00010 * 00011 * The above copyright notice and this permission notice shall be included 00012 * in all copies or substantial portions of the Software. 00013 * 00014 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 00015 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00016 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 00017 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00018 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 00019 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 00020 * DEALINGS IN THE SOFTWARE. 00021 ****************************************************************************** 00022 * 00023 * gdaldrivermanager.cpp 00024 * 00025 * The GDALDriverManager class from gdal_priv.h. 00026 * 00027 * $Log: gdaldrivermanager_cpp-source.html,v $ 00027 * Revision 1.13 2002/12/21 19:13:13 warmerda 00027 * updated 00027 * 00028 * Revision 1.14 2002/12/03 04:41:41 warmerda 00029 * call CPLFinderClean() to cleanup memory 00030 * 00031 * Revision 1.13 2002/10/21 18:05:42 warmerda 00032 * added AutoSkipDrivers() method on driver manager 00033 * 00034 * Revision 1.12 2002/09/04 06:52:35 warmerda 00035 * added GDALDestroyDriverManager 00036 * 00037 * Revision 1.11 2002/07/09 20:33:12 warmerda 00038 * expand tabs 00039 * 00040 * Revision 1.10 2002/06/12 21:13:27 warmerda 00041 * use metadata based driver info 00042 * 00043 * Revision 1.9 2002/05/14 21:38:32 warmerda 00044 * make INST_DATA overidable with binary patch 00045 * 00046 * Revision 1.8 2001/07/18 04:04:30 warmerda 00047 * added CPL_CVSID 00048 * 00049 * Revision 1.7 2000/08/29 21:09:15 warmerda 00050 * added logic to push INST_DATA on data file search stack 00051 * 00052 * Revision 1.6 2000/04/22 12:25:41 warmerda 00053 * Documented AutoLoadDrivers(). 00054 * 00055 * Revision 1.5 2000/04/04 23:44:29 warmerda 00056 * added AutoLoadDrivers() to GDALDriverManager 00057 * 00058 * Revision 1.4 2000/03/06 02:21:39 warmerda 00059 * added GDALRegisterDriver func 00060 * 00061 * Revision 1.3 1999/10/21 13:24:08 warmerda 00062 * Added documentation and C callable functions. 00063 * 00064 * Revision 1.2 1998/12/31 18:53:33 warmerda 00065 * Add GDALGetDriverByName 00066 * 00067 * Revision 1.1 1998/12/03 18:32:01 warmerda 00068 * New 00069 * 00070 */ 00071 00072 #include "gdal_priv.h" 00073 #include "cpl_string.h" 00074 00075 CPL_CVSID("$Id: gdaldrivermanager_cpp-source.html,v 1.13 2002/12/21 19:13:13 warmerda Exp $"); 00076 00077 static char *pszUpdatableINST_DATA = 00078 "__INST_DATA_TARGET: "; 00079 00080 /************************************************************************/ 00081 /* ==================================================================== */ 00082 /* GDALDriverManager */ 00083 /* ==================================================================== */ 00084 /************************************************************************/ 00085 00086 static GDALDriverManager *poDM = NULL; 00087 00088 /************************************************************************/ 00089 /* GetGDALDriverManager() */ 00090 /* */ 00091 /* A freestanding function to get the only instance of the */ 00092 /* GDALDriverManager. */ 00093 /************************************************************************/ 00094 00105 GDALDriverManager *GetGDALDriverManager() 00106 00107 { 00108 if( poDM == NULL ) 00109 new GDALDriverManager(); 00110 00111 return( poDM ); 00112 } 00113 00114 /************************************************************************/ 00115 /* GDALDriverManager() */ 00116 /************************************************************************/ 00117 00118 GDALDriverManager::GDALDriverManager() 00119 00120 { 00121 nDrivers = 0; 00122 papoDrivers = NULL; 00123 pszHome = CPLStrdup(""); 00124 00125 CPLAssert( poDM == NULL ); 00126 poDM = this; 00127 00128 /* -------------------------------------------------------------------- */ 00129 /* We want to push a location to search for data files */ 00130 /* supporting GDAL/OGR such as EPSG csv files, S-57 definition */ 00131 /* files, and so forth. The static pszUpdateableINST_DATA */ 00132 /* string can be updated within the shared library or */ 00133 /* executable during an install to point installed data */ 00134 /* directory. If it isn't burned in here then we use the */ 00135 /* INST_DATA macro (setup at configure time) if */ 00136 /* available. Otherwise we don't push anything and we hope */ 00137 /* other mechanisms such as environment variables will have */ 00138 /* been employed. */ 00139 /* -------------------------------------------------------------------- */ 00140 if( pszUpdatableINST_DATA[19] != ' ' ) 00141 { 00142 CPLPushFinderLocation( pszUpdatableINST_DATA + 19 ); 00143 } 00144 else 00145 { 00146 #ifdef INST_DATA 00147 CPLPushFinderLocation( INST_DATA ); 00148 #endif 00149 } 00150 } 00151 00152 /************************************************************************/ 00153 /* ~GDALDriverManager() */ 00154 /* */ 00155 /* Eventually this should also likely clean up all open */ 00156 /* datasets. Or perhaps the drivers that own them should do */ 00157 /* that in their destructor? */ 00158 /************************************************************************/ 00159 00160 GDALDriverManager::~GDALDriverManager() 00161 00162 { 00163 /* -------------------------------------------------------------------- */ 00164 /* Destroy the existing drivers. */ 00165 /* -------------------------------------------------------------------- */ 00166 while( GetDriverCount() > 0 ) 00167 { 00168 GDALDriver *poDriver = GetDriver(0); 00169 00170 DeregisterDriver(poDriver); 00171 delete poDriver; 00172 } 00173 00174 /* -------------------------------------------------------------------- */ 00175 /* Cleanup local memory. */ 00176 /* -------------------------------------------------------------------- */ 00177 VSIFree( papoDrivers ); 00178 VSIFree( pszHome ); 00179 00180 /* -------------------------------------------------------------------- */ 00181 /* Blow away all the finder hints paths. We really shouldn't */ 00182 /* be doing all of them, but it is currently hard to keep track */ 00183 /* of those that actually belong to us. */ 00184 /* -------------------------------------------------------------------- */ 00185 CPLFinderClean(); 00186 00187 /* -------------------------------------------------------------------- */ 00188 /* Ensure the global driver manager pointer is NULLed out. */ 00189 /* -------------------------------------------------------------------- */ 00190 if( poDM == this ) 00191 poDM = NULL; 00192 } 00193 00194 /************************************************************************/ 00195 /* GetDriverCount() */ 00196 /************************************************************************/ 00197 00206 int GDALDriverManager::GetDriverCount() 00207 00208 { 00209 return( nDrivers ); 00210 } 00211 00212 /************************************************************************/ 00213 /* GDALGetDriverCount() */ 00214 /************************************************************************/ 00215 00216 int GDALGetDriverCount() 00217 00218 { 00219 return GetGDALDriverManager()->GetDriverCount(); 00220 } 00221 00222 /************************************************************************/ 00223 /* GetDriver() */ 00224 /************************************************************************/ 00225 00236 GDALDriver * GDALDriverManager::GetDriver( int iDriver ) 00237 00238 { 00239 if( iDriver < 0 || iDriver >= nDrivers ) 00240 return NULL; 00241 else 00242 return papoDrivers[iDriver]; 00243 } 00244 00245 /************************************************************************/ 00246 /* GDALGetDriver() */ 00247 /************************************************************************/ 00248 00249 GDALDriverH GDALGetDriver( int iDriver ) 00250 00251 { 00252 return (GDALDriverH) GetGDALDriverManager()->GetDriver(iDriver); 00253 } 00254 00255 /************************************************************************/ 00256 /* RegisterDriver() */ 00257 /************************************************************************/ 00258 00278 int GDALDriverManager::RegisterDriver( GDALDriver * poDriver ) 00279 00280 { 00281 /* -------------------------------------------------------------------- */ 00282 /* If it is already registered, just return the existing */ 00283 /* index. */ 00284 /* -------------------------------------------------------------------- */ 00285 if( GetDriverByName( poDriver->GetDescription() ) != NULL ) 00286 { 00287 int i; 00288 00289 for( i = 0; i < nDrivers; i++ ) 00290 { 00291 if( papoDrivers[i] == poDriver ) 00292 return i; 00293 } 00294 00295 CPLAssert( FALSE ); 00296 } 00297 00298 /* -------------------------------------------------------------------- */ 00299 /* Otherwise grow the list to hold the new entry. */ 00300 /* -------------------------------------------------------------------- */ 00301 papoDrivers = (GDALDriver **) 00302 VSIRealloc(papoDrivers, sizeof(GDALDriver *) * (nDrivers+1)); 00303 00304 papoDrivers[nDrivers] = poDriver; 00305 nDrivers++; 00306 00307 if( poDriver->pfnCreate != NULL ) 00308 poDriver->SetMetadataItem( GDAL_DCAP_CREATE, "YES" ); 00309 00310 if( poDriver->pfnCreateCopy != NULL ) 00311 poDriver->SetMetadataItem( GDAL_DCAP_CREATECOPY, "YES" ); 00312 00313 return( nDrivers - 1 ); 00314 } 00315 00316 /************************************************************************/ 00317 /* GDALRegisterDriver() */ 00318 /************************************************************************/ 00319 00320 int GDALRegisterDriver( GDALDriverH hDriver ) 00321 00322 { 00323 return GetGDALDriverManager()->RegisterDriver( (GDALDriver *) hDriver ); 00324 } 00325 00326 00327 /************************************************************************/ 00328 /* DeregisterDriver() */ 00329 /************************************************************************/ 00330 00341 void GDALDriverManager::DeregisterDriver( GDALDriver * poDriver ) 00342 00343 { 00344 int i; 00345 00346 for( i = 0; i < nDrivers; i++ ) 00347 { 00348 if( papoDrivers[i] == poDriver ) 00349 break; 00350 } 00351 00352 if( i == nDrivers ) 00353 return; 00354 00355 while( i < nDrivers-1 ) 00356 { 00357 papoDrivers[i] = papoDrivers[i+1]; 00358 i++; 00359 } 00360 nDrivers--; 00361 } 00362 00363 /************************************************************************/ 00364 /* GDALDeregisterDriver() */ 00365 /************************************************************************/ 00366 00367 void GDALDeregisterDriver( GDALDriverH hDriver ) 00368 00369 { 00370 GetGDALDriverManager()->DeregisterDriver( (GDALDriver *) hDriver ); 00371 } 00372 00373 00374 /************************************************************************/ 00375 /* GetDriverByName() */ 00376 /************************************************************************/ 00377 00388 GDALDriver * GDALDriverManager::GetDriverByName( const char * pszName ) 00389 00390 { 00391 int i; 00392 00393 for( i = 0; i < nDrivers; i++ ) 00394 { 00395 if( EQUAL(papoDrivers[i]->GetDescription(), pszName) ) 00396 return papoDrivers[i]; 00397 } 00398 00399 return NULL; 00400 } 00401 00402 /************************************************************************/ 00403 /* GDALGetDriverByName() */ 00404 /************************************************************************/ 00405 00406 GDALDriverH GDALGetDriverByName( const char * pszName ) 00407 00408 { 00409 return( GetGDALDriverManager()->GetDriverByName( pszName ) ); 00410 } 00411 00412 /************************************************************************/ 00413 /* GetHome() */ 00414 /************************************************************************/ 00415 00416 const char *GDALDriverManager::GetHome() 00417 00418 { 00419 return pszHome; 00420 } 00421 00422 /************************************************************************/ 00423 /* SetHome() */ 00424 /************************************************************************/ 00425 00426 void GDALDriverManager::SetHome( const char * pszNewHome ) 00427 00428 { 00429 CPLFree( pszHome ); 00430 pszHome = CPLStrdup(pszNewHome); 00431 } 00432 00433 /************************************************************************/ 00434 /* AutoSkipDrivers() */ 00435 /************************************************************************/ 00436 00449 void GDALDriverManager::AutoSkipDrivers() 00450 00451 { 00452 if( getenv( "GDAL_SKIP" ) == NULL ) 00453 return; 00454 00455 char **papszList = CSLTokenizeString( getenv("GDAL_SKIP") ); 00456 00457 for( int i = 0; i < CSLCount(papszList); i++ ) 00458 { 00459 GDALDriver *poDriver = GetDriverByName( papszList[i] ); 00460 00461 if( poDriver == NULL ) 00462 CPLError( CE_Warning, CPLE_AppDefined, 00463 "Unable to find driver %s to unload from GDAL_SKIP environment variable.", 00464 papszList[i] ); 00465 else 00466 { 00467 CPLDebug( "GDAL", "AutoSkipDriver(%s)", papszList[i] ); 00468 DeregisterDriver( poDriver ); 00469 delete poDriver; 00470 } 00471 00472 } 00473 00474 CSLDestroy( papszList ); 00475 } 00476 00477 /************************************************************************/ 00478 /* AutoLoadDrivers() */ 00479 /************************************************************************/ 00480 00498 void GDALDriverManager::AutoLoadDrivers() 00499 00500 { 00501 char **papszSearchPath = NULL; 00502 00503 /* -------------------------------------------------------------------- */ 00504 /* Where should we look for stuff? */ 00505 /* -------------------------------------------------------------------- */ 00506 if( getenv( "GDAL_DRIVER_PATH" ) != NULL ) 00507 { 00508 #ifdef WIN32 00509 papszSearchPath = 00510 CSLTokenizeStringComplex( getenv( "GDAL_DRIVER_PATH" ), ";", 00511 TRUE, FALSE ); 00512 #else 00513 papszSearchPath = 00514 CSLTokenizeStringComplex( getenv( "GDAL_DRIVER_PATH" ), ":", 00515 TRUE, FALSE ); 00516 #endif 00517 } 00518 else 00519 { 00520 papszSearchPath = CSLAddString( papszSearchPath, "/usr/local/lib" ); 00521 00522 if( strlen(GetHome()) > 0 ) 00523 { 00524 papszSearchPath = CSLAddString( papszSearchPath, 00525 CPLFormFilename( GetHome(), "lib", NULL ) ); 00526 } 00527 } 00528 00529 /* -------------------------------------------------------------------- */ 00530 /* Scan each directory looking for files starting with gdal_ */ 00531 /* -------------------------------------------------------------------- */ 00532 for( int iDir = 0; iDir < CSLCount(papszSearchPath); iDir++ ) 00533 { 00534 char **papszFiles = CPLReadDir( papszSearchPath[iDir] ); 00535 00536 for( int iFile = 0; iFile < CSLCount(papszFiles); iFile++ ) 00537 { 00538 char *pszFuncName; 00539 const char *pszFilename; 00540 void *pRegister; 00541 00542 if( !EQUALN(papszFiles[iFile],"gdal_",5) ) 00543 continue; 00544 00545 pszFuncName = (char *) CPLCalloc(strlen(papszFiles[iFile])+20,1); 00546 sprintf( pszFuncName, "GDALRegister_%s", 00547 CPLGetBasename(papszFiles[iFile]) + 5 ); 00548 00549 pszFilename = 00550 CPLFormFilename( papszSearchPath[iDir], 00551 papszFiles[iFile], NULL ); 00552 00553 pRegister = CPLGetSymbol( pszFilename, pszFuncName ); 00554 if( pRegister == NULL ) 00555 { 00556 strcpy( pszFuncName, "GDALRegisterMe" ); 00557 pRegister = CPLGetSymbol( pszFilename, pszFuncName ); 00558 } 00559 00560 if( pRegister != NULL ) 00561 { 00562 CPLDebug( "GDAL", "Auto register %s using %s\n", 00563 pszFilename, pszFuncName ); 00564 00565 ((void (*)()) pRegister)(); 00566 } 00567 00568 CPLFree( pszFuncName ); 00569 } 00570 00571 CSLDestroy( papszFiles ); 00572 } 00573 00574 CSLDestroy( papszSearchPath ); 00575 } 00576 00577 /************************************************************************/ 00578 /* GDALDestroyDriverManager() */ 00579 /************************************************************************/ 00580 00587 void GDALDestroyDriverManager( void ) 00588 00589 { 00590 if( poDM != NULL ) 00591 delete poDM; 00592 }