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-04-29 01:40:10 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             :  * Permission is hereby granted, free of charge, to any person obtaining a
      12             :  * copy of this software and associated documentation files (the "Software"),
      13             :  * to deal in the Software without restriction, including without limitation
      14             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15             :  * and/or sell copies of the Software, and to permit persons to whom the
      16             :  * Software is furnished to do so, subject to the following conditions:
      17             :  *
      18             :  * The above copyright notice and this permission notice shall be included
      19             :  * in all copies or substantial portions of the Software.
      20             :  *
      21             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      22             :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      24             :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      27             :  * DEALINGS IN THE SOFTWARE.
      28             :  ****************************************************************************/
      29             : 
      30             : #include "cpl_port.h"
      31             : #include "cpl_conv.h"
      32             : 
      33             : #include <cstddef>
      34             : 
      35             : #include "cpl_multiproc.h"
      36             : #include "cpl_string.h"
      37             : #include "cpl_vsi.h"
      38             : 
      39             : typedef struct
      40             : {
      41             :     bool bFinderInitialized;
      42             :     int nFileFinders;
      43             :     CPLFileFinder *papfnFinders;
      44             :     char **papszFinderLocations;
      45             : } FindFileTLS;
      46             : 
      47             : /************************************************************************/
      48             : /*                      CPLFindFileDeinitTLS()                          */
      49             : /************************************************************************/
      50             : 
      51             : static void CPLPopFinderLocationInternal(FindFileTLS *pTLSData);
      52             : static CPLFileFinder CPLPopFileFinderInternal(FindFileTLS *pTLSData);
      53             : 
      54         852 : static void CPLFindFileFreeTLS(void *pData)
      55             : {
      56         852 :     FindFileTLS *pTLSData = reinterpret_cast<FindFileTLS *>(pData);
      57         852 :     if (pTLSData != nullptr && pTLSData->bFinderInitialized)
      58             :     {
      59         372 :         while (pTLSData->papszFinderLocations != nullptr)
      60         248 :             CPLPopFinderLocationInternal(pTLSData);
      61         248 :         while (CPLPopFileFinderInternal(pTLSData) != nullptr)
      62             :         {
      63             :         }
      64             : 
      65         124 :         pTLSData->bFinderInitialized = false;
      66             :     }
      67         852 :     CPLFree(pTLSData);
      68         852 : }
      69             : 
      70             : /************************************************************************/
      71             : /*                       CPLGetFindFileTLS()                            */
      72             : /************************************************************************/
      73             : 
      74        7094 : static FindFileTLS *CPLGetFindFileTLS()
      75             : {
      76        7094 :     int bMemoryError = FALSE;
      77             :     FindFileTLS *pTLSData = reinterpret_cast<FindFileTLS *>(
      78        7094 :         CPLGetTLSEx(CTLS_FINDFILE, &bMemoryError));
      79        7094 :     if (bMemoryError)
      80           0 :         return nullptr;
      81        7094 :     if (pTLSData == nullptr)
      82             :     {
      83             :         pTLSData = static_cast<FindFileTLS *>(
      84         926 :             VSI_CALLOC_VERBOSE(1, sizeof(FindFileTLS)));
      85         926 :         if (pTLSData == nullptr)
      86           0 :             return nullptr;
      87         926 :         CPLSetTLSWithFreeFunc(CTLS_FINDFILE, pTLSData, CPLFindFileFreeTLS);
      88             :     }
      89        7094 :     return pTLSData;
      90             : }
      91             : 
      92             : /************************************************************************/
      93             : /*                           CPLFinderInit()                            */
      94             : /************************************************************************/
      95             : 
      96        3421 : static FindFileTLS *CPLFinderInit()
      97             : 
      98             : {
      99        3421 :     FindFileTLS *pTLSData = CPLGetFindFileTLS();
     100        3421 :     if (pTLSData != nullptr && !pTLSData->bFinderInitialized)
     101             :     {
     102         198 :         pTLSData->bFinderInitialized = true;
     103         198 :         CPLPushFileFinder(CPLDefaultFindFile);
     104             : 
     105         198 :         CPLPushFinderLocation(".");
     106             : 
     107         198 :         if (CPLGetConfigOption("GDAL_DATA", nullptr) != nullptr)
     108             :         {
     109         196 :             CPLPushFinderLocation(CPLGetConfigOption("GDAL_DATA", nullptr));
     110             :         }
     111             :         else
     112             :         {
     113             : #ifdef INST_DATA
     114           2 :             CPLPushFinderLocation(INST_DATA);
     115             : #endif
     116             : #ifdef GDAL_PREFIX
     117             : #ifdef MACOSX_FRAMEWORK
     118             :             CPLPushFinderLocation(GDAL_PREFIX "/Resources/gdal");
     119             : #else
     120           2 :             CPLPushFinderLocation(GDAL_PREFIX "/share/gdal");
     121             : #endif
     122             : #endif
     123             :         }
     124             :     }
     125        3421 :     return pTLSData;
     126             : }
     127             : 
     128             : /************************************************************************/
     129             : /*                           CPLFinderClean()                           */
     130             : /************************************************************************/
     131             : 
     132             : /** CPLFinderClean */
     133         852 : void CPLFinderClean()
     134             : 
     135             : {
     136         852 :     FindFileTLS *pTLSData = CPLGetFindFileTLS();
     137         852 :     CPLFindFileFreeTLS(pTLSData);
     138         852 :     int bMemoryError = FALSE;
     139         852 :     CPLSetTLSWithFreeFuncEx(CTLS_FINDFILE, nullptr, nullptr, &bMemoryError);
     140             :     // TODO: if( bMemoryError ) {}
     141         852 : }
     142             : 
     143             : /************************************************************************/
     144             : /*                         CPLDefaultFindFile()                         */
     145             : /************************************************************************/
     146             : 
     147             : /** CPLDefaultFindFile */
     148        2821 : const char *CPLDefaultFindFile(const char *pszClass, const char *pszBasename)
     149             : 
     150             : {
     151        2821 :     FindFileTLS *pTLSData = CPLGetFindFileTLS();
     152        2821 :     if (pTLSData == nullptr)
     153           0 :         return nullptr;
     154        2821 :     const int nLocations = CSLCount(pTLSData->papszFinderLocations);
     155             : 
     156        3859 :     for (int i = nLocations - 1; i >= 0; i--)
     157             :     {
     158        6680 :         const char *pszResult = CPLFormFilename(
     159        3340 :             pTLSData->papszFinderLocations[i], pszBasename, nullptr);
     160             : 
     161             :         VSIStatBufL sStat;
     162        3340 :         if (VSIStatL(pszResult, &sStat) == 0)
     163        2302 :             return pszResult;
     164             :     }
     165             : 
     166         519 :     if (EQUAL(pszClass, "gdal") && !CPLGetConfigOption("GDAL_DATA", nullptr))
     167             :     {
     168           0 :         CPLError(CE_Warning, CPLE_FileIO,
     169             :                  "Cannot find %s (GDAL_DATA is not defined)", pszBasename);
     170             :     }
     171             : 
     172         519 :     return nullptr;
     173             : }
     174             : 
     175             : /************************************************************************/
     176             : /*                            CPLFindFile()                             */
     177             : /************************************************************************/
     178             : 
     179             : /** CPLFindFile */
     180        2821 : const char *CPLFindFile(const char *pszClass, const char *pszBasename)
     181             : 
     182             : {
     183        2821 :     FindFileTLS *pTLSData = CPLFinderInit();
     184        2821 :     if (pTLSData == nullptr)
     185           0 :         return nullptr;
     186             : 
     187        3340 :     for (int i = pTLSData->nFileFinders - 1; i >= 0; i--)
     188             :     {
     189             :         const char *pszResult =
     190        2821 :             (pTLSData->papfnFinders[i])(pszClass, pszBasename);
     191        2821 :         if (pszResult != nullptr)
     192        2302 :             return pszResult;
     193             :     }
     194             : 
     195         519 :     return nullptr;
     196             : }
     197             : 
     198             : /************************************************************************/
     199             : /*                         CPLPushFileFinder()                          */
     200             : /************************************************************************/
     201             : 
     202             : /** CPLPushFileFinder */
     203         198 : void CPLPushFileFinder(CPLFileFinder pfnFinder)
     204             : 
     205             : {
     206         198 :     FindFileTLS *pTLSData = CPLFinderInit();
     207         198 :     if (pTLSData == nullptr)
     208           0 :         return;
     209             : 
     210         396 :     pTLSData->papfnFinders = static_cast<CPLFileFinder *>(
     211         396 :         CPLRealloc(pTLSData->papfnFinders,
     212         198 :                    sizeof(CPLFileFinder) * ++pTLSData->nFileFinders));
     213         198 :     pTLSData->papfnFinders[pTLSData->nFileFinders - 1] = pfnFinder;
     214             : }
     215             : 
     216             : /************************************************************************/
     217             : /*                          CPLPopFileFinder()                          */
     218             : /************************************************************************/
     219             : 
     220         248 : CPLFileFinder CPLPopFileFinderInternal(FindFileTLS *pTLSData)
     221             : 
     222             : {
     223         248 :     if (pTLSData == nullptr)
     224           0 :         return nullptr;
     225         248 :     if (pTLSData->nFileFinders == 0)
     226         124 :         return nullptr;
     227             : 
     228         124 :     CPLFileFinder pfnReturn = pTLSData->papfnFinders[--pTLSData->nFileFinders];
     229             : 
     230         124 :     if (pTLSData->nFileFinders == 0)
     231             :     {
     232         124 :         CPLFree(pTLSData->papfnFinders);
     233         124 :         pTLSData->papfnFinders = nullptr;
     234             :     }
     235             : 
     236         124 :     return pfnReturn;
     237             : }
     238             : 
     239             : /** CPLPopFileFinder */
     240           0 : CPLFileFinder CPLPopFileFinder()
     241             : 
     242             : {
     243           0 :     return CPLPopFileFinderInternal(CPLFinderInit());
     244             : }
     245             : 
     246             : /************************************************************************/
     247             : /*                       CPLPushFinderLocation()                        */
     248             : /************************************************************************/
     249             : 
     250             : /** CPLPushFinderLocation */
     251         402 : void CPLPushFinderLocation(const char *pszLocation)
     252             : 
     253             : {
     254         402 :     FindFileTLS *pTLSData = CPLFinderInit();
     255         402 :     if (pTLSData == nullptr)
     256           0 :         return;
     257             :     // Check if location already is in list.
     258         402 :     if (CSLFindStringCaseSensitive(pTLSData->papszFinderLocations,
     259         402 :                                    pszLocation) > -1)
     260           6 :         return;
     261         396 :     pTLSData->papszFinderLocations =
     262         396 :         CSLAddStringMayFail(pTLSData->papszFinderLocations, pszLocation);
     263             : }
     264             : 
     265             : /************************************************************************/
     266             : /*                       CPLPopFinderLocation()                         */
     267             : /************************************************************************/
     268             : 
     269         248 : static void CPLPopFinderLocationInternal(FindFileTLS *pTLSData)
     270             : 
     271             : {
     272         248 :     if (pTLSData == nullptr || pTLSData->papszFinderLocations == nullptr)
     273           0 :         return;
     274             : 
     275         248 :     const int nCount = CSLCount(pTLSData->papszFinderLocations);
     276         248 :     if (nCount == 0)
     277           0 :         return;
     278             : 
     279         248 :     CPLFree(pTLSData->papszFinderLocations[nCount - 1]);
     280         248 :     pTLSData->papszFinderLocations[nCount - 1] = nullptr;
     281             : 
     282         248 :     if (nCount == 1)
     283             :     {
     284         124 :         CPLFree(pTLSData->papszFinderLocations);
     285         124 :         pTLSData->papszFinderLocations = nullptr;
     286             :     }
     287             : }
     288             : 
     289             : /** CPLPopFinderLocation */
     290           0 : void CPLPopFinderLocation()
     291             : {
     292           0 :     CPLPopFinderLocationInternal(CPLFinderInit());
     293           0 : }

Generated by: LCOV version 1.14