LCOV - code coverage report
Current view: top level - port - cpl_findfile.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 87 102 85.3 %
Date: 2024-11-21 22:18:42 Functions: 10 12 83.3 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  CPL - Common Portability Library
       4             :  * Purpose:  Generic data file location finder, with application hooking.
       5             :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2000, Frank Warmerdam
       9             :  * Copyright (c) 2009-2010, Even Rouault <even dot rouault at spatialys.com>
      10             :  *
      11             :  * SPDX-License-Identifier: MIT
      12             :  ****************************************************************************/
      13             : 
      14             : #include "cpl_port.h"
      15             : #include "cpl_conv.h"
      16             : 
      17             : #include <cstddef>
      18             : 
      19             : #include "cpl_multiproc.h"
      20             : #include "cpl_string.h"
      21             : #include "cpl_vsi.h"
      22             : 
      23             : typedef struct
      24             : {
      25             :     bool bFinderInitialized;
      26             :     int nFileFinders;
      27             :     CPLFileFinder *papfnFinders;
      28             :     char **papszFinderLocations;
      29             : } FindFileTLS;
      30             : 
      31             : /************************************************************************/
      32             : /*                      CPLFindFileDeinitTLS()                          */
      33             : /************************************************************************/
      34             : 
      35             : static void CPLPopFinderLocationInternal(FindFileTLS *pTLSData);
      36             : static CPLFileFinder CPLPopFileFinderInternal(FindFileTLS *pTLSData);
      37             : 
      38         933 : static void CPLFindFileFreeTLS(void *pData)
      39             : {
      40         933 :     FindFileTLS *pTLSData = reinterpret_cast<FindFileTLS *>(pData);
      41         933 :     if (pTLSData != nullptr && pTLSData->bFinderInitialized)
      42             :     {
      43         384 :         while (pTLSData->papszFinderLocations != nullptr)
      44         256 :             CPLPopFinderLocationInternal(pTLSData);
      45         256 :         while (CPLPopFileFinderInternal(pTLSData) != nullptr)
      46             :         {
      47             :         }
      48             : 
      49         128 :         pTLSData->bFinderInitialized = false;
      50             :     }
      51         933 :     CPLFree(pTLSData);
      52         933 : }
      53             : 
      54             : /************************************************************************/
      55             : /*                       CPLGetFindFileTLS()                            */
      56             : /************************************************************************/
      57             : 
      58        7432 : static FindFileTLS *CPLGetFindFileTLS()
      59             : {
      60        7432 :     int bMemoryError = FALSE;
      61             :     FindFileTLS *pTLSData = reinterpret_cast<FindFileTLS *>(
      62        7432 :         CPLGetTLSEx(CTLS_FINDFILE, &bMemoryError));
      63        7432 :     if (bMemoryError)
      64           0 :         return nullptr;
      65        7432 :     if (pTLSData == nullptr)
      66             :     {
      67             :         pTLSData = static_cast<FindFileTLS *>(
      68        1012 :             VSI_CALLOC_VERBOSE(1, sizeof(FindFileTLS)));
      69        1012 :         if (pTLSData == nullptr)
      70           0 :             return nullptr;
      71        1012 :         CPLSetTLSWithFreeFunc(CTLS_FINDFILE, pTLSData, CPLFindFileFreeTLS);
      72             :     }
      73        7432 :     return pTLSData;
      74             : }
      75             : 
      76             : /************************************************************************/
      77             : /*                           CPLFinderInit()                            */
      78             : /************************************************************************/
      79             : 
      80        3563 : static FindFileTLS *CPLFinderInit()
      81             : 
      82             : {
      83        3563 :     FindFileTLS *pTLSData = CPLGetFindFileTLS();
      84        3563 :     if (pTLSData != nullptr && !pTLSData->bFinderInitialized)
      85             :     {
      86         207 :         pTLSData->bFinderInitialized = true;
      87         207 :         CPLPushFileFinder(CPLDefaultFindFile);
      88             : 
      89         207 :         CPLPushFinderLocation(".");
      90             : 
      91         207 :         if (CPLGetConfigOption("GDAL_DATA", nullptr) != nullptr)
      92             :         {
      93         205 :             CPLPushFinderLocation(CPLGetConfigOption("GDAL_DATA", nullptr));
      94             :         }
      95             :         else
      96             :         {
      97             : #ifdef INST_DATA
      98           2 :             CPLPushFinderLocation(INST_DATA);
      99             : #endif
     100             : #ifdef GDAL_PREFIX
     101             : #ifdef MACOSX_FRAMEWORK
     102             :             CPLPushFinderLocation(GDAL_PREFIX "/Resources/gdal");
     103             : #else
     104           2 :             CPLPushFinderLocation(GDAL_PREFIX "/share/gdal");
     105             : #endif
     106             : #endif
     107             :         }
     108             :     }
     109        3563 :     return pTLSData;
     110             : }
     111             : 
     112             : /************************************************************************/
     113             : /*                           CPLFinderClean()                           */
     114             : /************************************************************************/
     115             : 
     116             : /** CPLFinderClean */
     117         933 : void CPLFinderClean()
     118             : 
     119             : {
     120         933 :     FindFileTLS *pTLSData = CPLGetFindFileTLS();
     121         933 :     CPLFindFileFreeTLS(pTLSData);
     122         933 :     int bMemoryError = FALSE;
     123         933 :     CPLSetTLSWithFreeFuncEx(CTLS_FINDFILE, nullptr, nullptr, &bMemoryError);
     124             :     // TODO: if( bMemoryError ) {}
     125         933 : }
     126             : 
     127             : /************************************************************************/
     128             : /*                         CPLDefaultFindFile()                         */
     129             : /************************************************************************/
     130             : 
     131             : /** CPLDefaultFindFile */
     132        2936 : const char *CPLDefaultFindFile(const char *pszClass, const char *pszBasename)
     133             : 
     134             : {
     135        2936 :     FindFileTLS *pTLSData = CPLGetFindFileTLS();
     136        2936 :     if (pTLSData == nullptr)
     137           0 :         return nullptr;
     138        2936 :     const int nLocations = CSLCount(pTLSData->papszFinderLocations);
     139             : 
     140        3974 :     for (int i = nLocations - 1; i >= 0; i--)
     141             :     {
     142        6910 :         const char *pszResult = CPLFormFilename(
     143        3455 :             pTLSData->papszFinderLocations[i], pszBasename, nullptr);
     144             : 
     145             :         VSIStatBufL sStat;
     146        3455 :         if (VSIStatL(pszResult, &sStat) == 0)
     147        2417 :             return pszResult;
     148             :     }
     149             : 
     150         519 :     if (EQUAL(pszClass, "gdal") && !CPLGetConfigOption("GDAL_DATA", nullptr))
     151             :     {
     152           0 :         CPLError(CE_Warning, CPLE_FileIO,
     153             :                  "Cannot find %s (GDAL_DATA is not defined)", pszBasename);
     154             :     }
     155             : 
     156         519 :     return nullptr;
     157             : }
     158             : 
     159             : /************************************************************************/
     160             : /*                            CPLFindFile()                             */
     161             : /************************************************************************/
     162             : 
     163             : /** CPLFindFile */
     164        2936 : const char *CPLFindFile(const char *pszClass, const char *pszBasename)
     165             : 
     166             : {
     167        2936 :     FindFileTLS *pTLSData = CPLFinderInit();
     168        2936 :     if (pTLSData == nullptr)
     169           0 :         return nullptr;
     170             : 
     171        3455 :     for (int i = pTLSData->nFileFinders - 1; i >= 0; i--)
     172             :     {
     173             :         const char *pszResult =
     174        2936 :             (pTLSData->papfnFinders[i])(pszClass, pszBasename);
     175        2936 :         if (pszResult != nullptr)
     176        2417 :             return pszResult;
     177             :     }
     178             : 
     179         519 :     return nullptr;
     180             : }
     181             : 
     182             : /************************************************************************/
     183             : /*                         CPLPushFileFinder()                          */
     184             : /************************************************************************/
     185             : 
     186             : /** CPLPushFileFinder */
     187         207 : void CPLPushFileFinder(CPLFileFinder pfnFinder)
     188             : 
     189             : {
     190         207 :     FindFileTLS *pTLSData = CPLFinderInit();
     191         207 :     if (pTLSData == nullptr)
     192           0 :         return;
     193             : 
     194         414 :     pTLSData->papfnFinders = static_cast<CPLFileFinder *>(
     195         414 :         CPLRealloc(pTLSData->papfnFinders,
     196         207 :                    sizeof(CPLFileFinder) * ++pTLSData->nFileFinders));
     197         207 :     pTLSData->papfnFinders[pTLSData->nFileFinders - 1] = pfnFinder;
     198             : }
     199             : 
     200             : /************************************************************************/
     201             : /*                          CPLPopFileFinder()                          */
     202             : /************************************************************************/
     203             : 
     204         256 : CPLFileFinder CPLPopFileFinderInternal(FindFileTLS *pTLSData)
     205             : 
     206             : {
     207         256 :     if (pTLSData == nullptr)
     208           0 :         return nullptr;
     209         256 :     if (pTLSData->nFileFinders == 0)
     210         128 :         return nullptr;
     211             : 
     212         128 :     CPLFileFinder pfnReturn = pTLSData->papfnFinders[--pTLSData->nFileFinders];
     213             : 
     214         128 :     if (pTLSData->nFileFinders == 0)
     215             :     {
     216         128 :         CPLFree(pTLSData->papfnFinders);
     217         128 :         pTLSData->papfnFinders = nullptr;
     218             :     }
     219             : 
     220         128 :     return pfnReturn;
     221             : }
     222             : 
     223             : /** CPLPopFileFinder */
     224           0 : CPLFileFinder CPLPopFileFinder()
     225             : 
     226             : {
     227           0 :     return CPLPopFileFinderInternal(CPLFinderInit());
     228             : }
     229             : 
     230             : /************************************************************************/
     231             : /*                       CPLPushFinderLocation()                        */
     232             : /************************************************************************/
     233             : 
     234             : /** CPLPushFinderLocation */
     235         420 : void CPLPushFinderLocation(const char *pszLocation)
     236             : 
     237             : {
     238         420 :     FindFileTLS *pTLSData = CPLFinderInit();
     239         420 :     if (pTLSData == nullptr)
     240           0 :         return;
     241             :     // Check if location already is in list.
     242         420 :     if (CSLFindStringCaseSensitive(pTLSData->papszFinderLocations,
     243         420 :                                    pszLocation) > -1)
     244           6 :         return;
     245         414 :     pTLSData->papszFinderLocations =
     246         414 :         CSLAddStringMayFail(pTLSData->papszFinderLocations, pszLocation);
     247             : }
     248             : 
     249             : /************************************************************************/
     250             : /*                       CPLPopFinderLocation()                         */
     251             : /************************************************************************/
     252             : 
     253         256 : static void CPLPopFinderLocationInternal(FindFileTLS *pTLSData)
     254             : 
     255             : {
     256         256 :     if (pTLSData == nullptr || pTLSData->papszFinderLocations == nullptr)
     257           0 :         return;
     258             : 
     259         256 :     const int nCount = CSLCount(pTLSData->papszFinderLocations);
     260         256 :     if (nCount == 0)
     261           0 :         return;
     262             : 
     263         256 :     CPLFree(pTLSData->papszFinderLocations[nCount - 1]);
     264         256 :     pTLSData->papszFinderLocations[nCount - 1] = nullptr;
     265             : 
     266         256 :     if (nCount == 1)
     267             :     {
     268         128 :         CPLFree(pTLSData->papszFinderLocations);
     269         128 :         pTLSData->papszFinderLocations = nullptr;
     270             :     }
     271             : }
     272             : 
     273             : /** CPLPopFinderLocation */
     274           0 : void CPLPopFinderLocation()
     275             : {
     276           0 :     CPLPopFinderLocationInternal(CPLFinderInit());
     277           0 : }

Generated by: LCOV version 1.14