LCOV - code coverage report
Current view: top level - frmts/vrt - vrtrawrasterband.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 147 186 79.0 %
Date: 2024-05-07 17:03:27 Functions: 10 12 83.3 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  Virtual GDAL Datasets
       4             :  * Purpose:  Implementation of VRTRawRasterBand
       5             :  * Author:   Frank Warmerdam <warmerdam@pobox.com>
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2004, Frank Warmerdam <warmerdam@pobox.com>
       9             :  * Copyright (c) 2007-2013, 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 "rawdataset.h"
      32             : #include "vrtdataset.h"
      33             : 
      34             : #include <cerrno>
      35             : #include <cstdio>
      36             : #include <cstdlib>
      37             : #include <cstring>
      38             : 
      39             : #include "cpl_conv.h"
      40             : #include "cpl_error.h"
      41             : #include "cpl_hash_set.h"
      42             : #include "cpl_minixml.h"
      43             : #include "cpl_string.h"
      44             : #include "cpl_vsi.h"
      45             : #include "gdal.h"
      46             : #include "gdal_priv.h"
      47             : 
      48             : /*! @cond Doxygen_Suppress */
      49             : 
      50             : /************************************************************************/
      51             : /* ==================================================================== */
      52             : /*                          VRTRawRasterBand                            */
      53             : /* ==================================================================== */
      54             : /************************************************************************/
      55             : 
      56             : /************************************************************************/
      57             : /*                          VRTRawRasterBand()                          */
      58             : /************************************************************************/
      59             : 
      60          28 : VRTRawRasterBand::VRTRawRasterBand(GDALDataset *poDSIn, int nBandIn,
      61          28 :                                    GDALDataType eType)
      62             :     : m_poRawRaster(nullptr), m_pszSourceFilename(nullptr),
      63          28 :       m_bRelativeToVRT(FALSE)
      64             : {
      65          28 :     Initialize(poDSIn->GetRasterXSize(), poDSIn->GetRasterYSize());
      66             : 
      67             :     // Declared in GDALRasterBand.
      68          28 :     poDS = poDSIn;
      69          28 :     nBand = nBandIn;
      70             : 
      71          28 :     if (eType != GDT_Unknown)
      72           6 :         eDataType = eType;
      73          28 : }
      74             : 
      75             : /************************************************************************/
      76             : /*                         ~VRTRawRasterBand()                          */
      77             : /************************************************************************/
      78             : 
      79          56 : VRTRawRasterBand::~VRTRawRasterBand()
      80             : 
      81             : {
      82          28 :     FlushCache(true);
      83          28 :     ClearRawLink();
      84          56 : }
      85             : 
      86             : /************************************************************************/
      87             : /*                             IRasterIO()                              */
      88             : /************************************************************************/
      89             : 
      90         256 : CPLErr VRTRawRasterBand::IRasterIO(GDALRWFlag eRWFlag, int nXOff, int nYOff,
      91             :                                    int nXSize, int nYSize, void *pData,
      92             :                                    int nBufXSize, int nBufYSize,
      93             :                                    GDALDataType eBufType, GSpacing nPixelSpace,
      94             :                                    GSpacing nLineSpace,
      95             :                                    GDALRasterIOExtraArg *psExtraArg)
      96             : {
      97         256 :     if (m_poRawRaster == nullptr)
      98             :     {
      99           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     100             :                  "No raw raster band configured on VRTRawRasterBand.");
     101           0 :         return CE_Failure;
     102             :     }
     103             : 
     104         256 :     if (eRWFlag == GF_Write && eAccess == GA_ReadOnly)
     105             :     {
     106           0 :         CPLError(CE_Failure, CPLE_NoWriteAccess,
     107             :                  "Attempt to write to read only dataset in"
     108             :                  "VRTRawRasterBand::IRasterIO().");
     109             : 
     110           0 :         return CE_Failure;
     111             :     }
     112             : 
     113             :     /* -------------------------------------------------------------------- */
     114             :     /*      Do we have overviews that would be appropriate to satisfy       */
     115             :     /*      this request?                                                   */
     116             :     /* -------------------------------------------------------------------- */
     117         256 :     if ((nBufXSize < nXSize || nBufYSize < nYSize) && GetOverviewCount() > 0)
     118             :     {
     119           0 :         if (OverviewRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
     120             :                              nBufXSize, nBufYSize, eBufType, nPixelSpace,
     121           0 :                              nLineSpace, psExtraArg) == CE_None)
     122           0 :             return CE_None;
     123             :     }
     124             : 
     125         256 :     m_poRawRaster->SetAccess(eAccess);
     126             : 
     127         256 :     return m_poRawRaster->RasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
     128             :                                    nBufXSize, nBufYSize, eBufType, nPixelSpace,
     129         256 :                                    nLineSpace, psExtraArg);
     130             : }
     131             : 
     132             : /************************************************************************/
     133             : /*                             IReadBlock()                             */
     134             : /************************************************************************/
     135             : 
     136          70 : CPLErr VRTRawRasterBand::IReadBlock(int nBlockXOff, int nBlockYOff,
     137             :                                     void *pImage)
     138             : 
     139             : {
     140          70 :     if (m_poRawRaster == nullptr)
     141             :     {
     142           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     143             :                  "No raw raster band configured on VRTRawRasterBand.");
     144           0 :         return CE_Failure;
     145             :     }
     146             : 
     147          70 :     return m_poRawRaster->ReadBlock(nBlockXOff, nBlockYOff, pImage);
     148             : }
     149             : 
     150             : /************************************************************************/
     151             : /*                            IWriteBlock()                             */
     152             : /************************************************************************/
     153             : 
     154           0 : CPLErr VRTRawRasterBand::IWriteBlock(int nBlockXOff, int nBlockYOff,
     155             :                                      void *pImage)
     156             : 
     157             : {
     158           0 :     if (m_poRawRaster == nullptr)
     159             :     {
     160           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     161             :                  "No raw raster band configured on VRTRawRasterBand.");
     162           0 :         return CE_Failure;
     163             :     }
     164             : 
     165           0 :     m_poRawRaster->SetAccess(eAccess);
     166             : 
     167           0 :     return m_poRawRaster->WriteBlock(nBlockXOff, nBlockYOff, pImage);
     168             : }
     169             : 
     170             : /************************************************************************/
     171             : /*                             SetRawLink()                             */
     172             : /************************************************************************/
     173             : 
     174          28 : CPLErr VRTRawRasterBand::SetRawLink(const char *pszFilename,
     175             :                                     const char *pszVRTPath,
     176             :                                     int bRelativeToVRTIn,
     177             :                                     vsi_l_offset nImageOffset, int nPixelOffset,
     178             :                                     int nLineOffset, const char *pszByteOrder)
     179             : 
     180             : {
     181          28 :     ClearRawLink();
     182             : 
     183          28 :     static_cast<VRTDataset *>(poDS)->SetNeedsFlush();
     184             : 
     185             :     /* -------------------------------------------------------------------- */
     186             :     /*      Prepare filename.                                               */
     187             :     /* -------------------------------------------------------------------- */
     188          28 :     if (pszFilename == nullptr)
     189             :     {
     190           0 :         CPLError(CE_Warning, CPLE_AppDefined,
     191             :                  "Missing <SourceFilename> element in VRTRasterBand.");
     192           0 :         return CE_Failure;
     193             :     }
     194             : 
     195          28 :     char *pszExpandedFilename = nullptr;
     196          28 :     if (pszVRTPath != nullptr && bRelativeToVRTIn)
     197             :     {
     198          16 :         pszExpandedFilename =
     199          16 :             CPLStrdup(CPLProjectRelativeFilename(pszVRTPath, pszFilename));
     200             :     }
     201             :     else
     202             :     {
     203          12 :         pszExpandedFilename = CPLStrdup(pszFilename);
     204             :     }
     205             : 
     206             :     /* -------------------------------------------------------------------- */
     207             :     /*      Try and open the file.  We always use the large file API.       */
     208             :     /* -------------------------------------------------------------------- */
     209          28 :     CPLPushErrorHandler(CPLQuietErrorHandler);
     210          28 :     FILE *fp = CPLOpenShared(pszExpandedFilename, "rb+", TRUE);
     211             : 
     212          28 :     if (fp == nullptr)
     213           4 :         fp = CPLOpenShared(pszExpandedFilename, "rb", TRUE);
     214             : 
     215          32 :     if (fp == nullptr &&
     216           4 :         static_cast<VRTDataset *>(poDS)->GetAccess() == GA_Update)
     217             :     {
     218           3 :         fp = CPLOpenShared(pszExpandedFilename, "wb+", TRUE);
     219             :     }
     220          28 :     CPLPopErrorHandler();
     221          28 :     CPLErrorReset();
     222             : 
     223          28 :     if (fp == nullptr)
     224             :     {
     225           1 :         CPLError(CE_Failure, CPLE_OpenFailed, "Unable to open %s.%s",
     226           1 :                  pszExpandedFilename, VSIStrerror(errno));
     227             : 
     228           1 :         CPLFree(pszExpandedFilename);
     229           1 :         return CE_Failure;
     230             :     }
     231             : 
     232          27 :     CPLFree(pszExpandedFilename);
     233             : 
     234          27 :     if (!RAWDatasetCheckMemoryUsage(
     235             :             nRasterXSize, nRasterYSize, 1,
     236             :             GDALGetDataTypeSizeBytes(GetRasterDataType()), nPixelOffset,
     237             :             nLineOffset, nImageOffset, 0, reinterpret_cast<VSILFILE *>(fp)))
     238             :     {
     239           2 :         CPLCloseShared(fp);
     240           2 :         return CE_Failure;
     241             :     }
     242             : 
     243          25 :     m_pszSourceFilename = CPLStrdup(pszFilename);
     244          25 :     m_bRelativeToVRT = bRelativeToVRTIn;
     245             : 
     246             :     /* -------------------------------------------------------------------- */
     247             :     /*      Work out if we are in native mode or not.                       */
     248             :     /* -------------------------------------------------------------------- */
     249          25 :     RawRasterBand::ByteOrder eByteOrder =
     250             : #if CPL_IS_LSB
     251             :         RawRasterBand::ByteOrder::ORDER_LITTLE_ENDIAN;
     252             : #else
     253             :         RawRasterBand::ByteOrder::ORDER_BIG_ENDIAN;
     254             : #endif
     255             : 
     256          25 :     if (pszByteOrder != nullptr)
     257             :     {
     258          23 :         if (EQUAL(pszByteOrder, "LSB"))
     259          14 :             eByteOrder = RawRasterBand::ByteOrder::ORDER_LITTLE_ENDIAN;
     260           9 :         else if (EQUAL(pszByteOrder, "MSB"))
     261           7 :             eByteOrder = RawRasterBand::ByteOrder::ORDER_BIG_ENDIAN;
     262           2 :         else if (EQUAL(pszByteOrder, "VAX"))
     263           1 :             eByteOrder = RawRasterBand::ByteOrder::ORDER_VAX;
     264             :         else
     265             :         {
     266           1 :             CPLError(CE_Failure, CPLE_AppDefined,
     267             :                      "Illegal ByteOrder value '%s', should be LSB, MSB or VAX.",
     268             :                      pszByteOrder);
     269           1 :             CPLCloseShared(fp);
     270           1 :             return CE_Failure;
     271             :         }
     272             :     }
     273             : 
     274             :     /* -------------------------------------------------------------------- */
     275             :     /*      Create a corresponding RawRasterBand.                           */
     276             :     /* -------------------------------------------------------------------- */
     277          24 :     m_poRawRaster =
     278          48 :         RawRasterBand::Create(reinterpret_cast<VSILFILE *>(fp), nImageOffset,
     279             :                               nPixelOffset, nLineOffset, GetRasterDataType(),
     280             :                               eByteOrder, GetXSize(), GetYSize(),
     281             :                               RawRasterBand::OwnFP::NO)
     282          24 :             .release();
     283          24 :     if (!m_poRawRaster)
     284             :     {
     285           0 :         CPLCloseShared(fp);
     286           0 :         return CE_Failure;
     287             :     }
     288             : 
     289             :     /* -------------------------------------------------------------------- */
     290             :     /*      Reset block size to match the raw raster.                       */
     291             :     /* -------------------------------------------------------------------- */
     292          24 :     m_poRawRaster->GetBlockSize(&nBlockXSize, &nBlockYSize);
     293             : 
     294          24 :     return CE_None;
     295             : }
     296             : 
     297             : /************************************************************************/
     298             : /*                            ClearRawLink()                            */
     299             : /************************************************************************/
     300             : 
     301          56 : void VRTRawRasterBand::ClearRawLink()
     302             : 
     303             : {
     304          56 :     if (m_poRawRaster != nullptr)
     305             :     {
     306          24 :         VSILFILE *fp = m_poRawRaster->GetFPL();
     307          24 :         delete m_poRawRaster;
     308          24 :         m_poRawRaster = nullptr;
     309             :         // We close the file after deleting the raster band
     310             :         // since data can be flushed in the destructor.
     311          24 :         if (fp != nullptr)
     312             :         {
     313          24 :             CPLCloseShared(reinterpret_cast<FILE *>(fp));
     314             :         }
     315             :     }
     316          56 :     CPLFree(m_pszSourceFilename);
     317          56 :     m_pszSourceFilename = nullptr;
     318          56 : }
     319             : 
     320             : /************************************************************************/
     321             : /*                            GetVirtualMemAuto()                       */
     322             : /************************************************************************/
     323             : 
     324           0 : CPLVirtualMem *VRTRawRasterBand::GetVirtualMemAuto(GDALRWFlag eRWFlag,
     325             :                                                    int *pnPixelSpace,
     326             :                                                    GIntBig *pnLineSpace,
     327             :                                                    char **papszOptions)
     328             : 
     329             : {
     330             :     // check the pointer to RawRasterBand
     331           0 :     if (m_poRawRaster == nullptr)
     332             :     {
     333             :         // use the super class method
     334           0 :         return VRTRasterBand::GetVirtualMemAuto(eRWFlag, pnPixelSpace,
     335           0 :                                                 pnLineSpace, papszOptions);
     336             :     }
     337             :     // if available, use the RawRasterBand method (use mmap if available)
     338           0 :     return m_poRawRaster->GetVirtualMemAuto(eRWFlag, pnPixelSpace, pnLineSpace,
     339           0 :                                             papszOptions);
     340             : }
     341             : 
     342             : /************************************************************************/
     343             : /*                              XMLInit()                               */
     344             : /************************************************************************/
     345             : 
     346             : CPLErr
     347          22 : VRTRawRasterBand::XMLInit(const CPLXMLNode *psTree, const char *pszVRTPath,
     348             :                           std::map<CPLString, GDALDataset *> &oMapSharedSources)
     349             : 
     350             : {
     351             :     const CPLErr eErr =
     352          22 :         VRTRasterBand::XMLInit(psTree, pszVRTPath, oMapSharedSources);
     353          22 :     if (eErr != CE_None)
     354           0 :         return eErr;
     355             : 
     356             :     /* -------------------------------------------------------------------- */
     357             :     /*      Validate a bit.                                                 */
     358             :     /* -------------------------------------------------------------------- */
     359          22 :     if (psTree == nullptr || psTree->eType != CXT_Element ||
     360          66 :         !EQUAL(psTree->pszValue, "VRTRasterBand") ||
     361          22 :         !EQUAL(CPLGetXMLValue(psTree, "subClass", ""), "VRTRawRasterBand"))
     362             :     {
     363           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     364             :                  "Invalid node passed to VRTRawRasterBand::XMLInit().");
     365           0 :         return CE_Failure;
     366             :     }
     367             : 
     368             :     /* -------------------------------------------------------------------- */
     369             :     /*      Prepare filename.                                               */
     370             :     /* -------------------------------------------------------------------- */
     371          22 :     const char *pszFilename = CPLGetXMLValue(psTree, "SourceFilename", nullptr);
     372             : 
     373          22 :     if (pszFilename == nullptr)
     374             :     {
     375           0 :         CPLError(CE_Warning, CPLE_AppDefined,
     376             :                  "Missing <SourceFilename> element in VRTRasterBand.");
     377           0 :         return CE_Failure;
     378             :     }
     379             : 
     380          22 :     const bool l_bRelativeToVRT = CPLTestBool(
     381             :         CPLGetXMLValue(psTree, "SourceFilename.relativeToVRT", "1"));
     382             : 
     383             :     /* -------------------------------------------------------------------- */
     384             :     /*      Collect layout information.                                     */
     385             :     /* -------------------------------------------------------------------- */
     386          22 :     int nWordDataSize = GDALGetDataTypeSizeBytes(GetRasterDataType());
     387             : 
     388          22 :     const char *pszImageOffset = CPLGetXMLValue(psTree, "ImageOffset", "0");
     389          44 :     const vsi_l_offset nImageOffset = CPLScanUIntBig(
     390          22 :         pszImageOffset, static_cast<int>(strlen(pszImageOffset)));
     391             : 
     392          22 :     int nPixelOffset = nWordDataSize;
     393          22 :     const char *pszPixelOffset = CPLGetXMLValue(psTree, "PixelOffset", nullptr);
     394          22 :     if (pszPixelOffset != nullptr)
     395             :     {
     396          20 :         nPixelOffset = atoi(pszPixelOffset);
     397             :     }
     398          22 :     if (nPixelOffset <= 0)
     399             :     {
     400           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     401             :                  "Invalid value for <PixelOffset> element : %d", nPixelOffset);
     402           0 :         return CE_Failure;
     403             :     }
     404             : 
     405          22 :     int nLineOffset = 0;
     406          22 :     const char *pszLineOffset = CPLGetXMLValue(psTree, "LineOffset", nullptr);
     407          22 :     if (pszLineOffset == nullptr)
     408             :     {
     409           2 :         if (nPixelOffset > INT_MAX / GetXSize())
     410             :         {
     411           0 :             CPLError(CE_Failure, CPLE_AppDefined, "Int overflow");
     412           0 :             return CE_Failure;
     413             :         }
     414           2 :         nLineOffset = nPixelOffset * GetXSize();
     415             :     }
     416             :     else
     417          20 :         nLineOffset = atoi(pszLineOffset);
     418             : 
     419          22 :     const char *pszByteOrder = CPLGetXMLValue(psTree, "ByteOrder", nullptr);
     420             : 
     421             :     /* -------------------------------------------------------------------- */
     422             :     /*      Open the file, and setup the raw layer access to the data.      */
     423             :     /* -------------------------------------------------------------------- */
     424          22 :     return SetRawLink(pszFilename, pszVRTPath, l_bRelativeToVRT, nImageOffset,
     425          22 :                       nPixelOffset, nLineOffset, pszByteOrder);
     426             : }
     427             : 
     428             : /************************************************************************/
     429             : /*                           SerializeToXML()                           */
     430             : /************************************************************************/
     431             : 
     432           7 : CPLXMLNode *VRTRawRasterBand::SerializeToXML(const char *pszVRTPath,
     433             :                                              bool &bHasWarnedAboutRAMUsage,
     434             :                                              size_t &nAccRAMUsage)
     435             : 
     436             : {
     437             : 
     438             :     /* -------------------------------------------------------------------- */
     439             :     /*      We can't set the layout if there is no open rawband.            */
     440             :     /* -------------------------------------------------------------------- */
     441           7 :     if (m_poRawRaster == nullptr)
     442             :     {
     443           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     444             :                  "VRTRawRasterBand::SerializeToXML() fails because "
     445             :                  "m_poRawRaster is NULL.");
     446           0 :         return nullptr;
     447             :     }
     448             : 
     449           7 :     CPLXMLNode *psTree = VRTRasterBand::SerializeToXML(
     450             :         pszVRTPath, bHasWarnedAboutRAMUsage, nAccRAMUsage);
     451             : 
     452             :     /* -------------------------------------------------------------------- */
     453             :     /*      Set subclass.                                                   */
     454             :     /* -------------------------------------------------------------------- */
     455           7 :     CPLCreateXMLNode(CPLCreateXMLNode(psTree, CXT_Attribute, "subClass"),
     456             :                      CXT_Text, "VRTRawRasterBand");
     457             : 
     458             :     /* -------------------------------------------------------------------- */
     459             :     /*      Setup the filename with relative flag.                          */
     460             :     /* -------------------------------------------------------------------- */
     461          14 :     CPLXMLNode *psNode = CPLCreateXMLElementAndValue(psTree, "SourceFilename",
     462           7 :                                                      m_pszSourceFilename);
     463             : 
     464           7 :     CPLCreateXMLNode(CPLCreateXMLNode(psNode, CXT_Attribute, "relativeToVRT"),
     465           7 :                      CXT_Text, m_bRelativeToVRT ? "1" : "0");
     466             : 
     467             :     /* -------------------------------------------------------------------- */
     468             :     /*      Set other layout information.                                   */
     469             :     /* -------------------------------------------------------------------- */
     470             : 
     471           7 :     CPLCreateXMLElementAndValue(
     472             :         psTree, "ImageOffset",
     473           7 :         CPLSPrintf(CPL_FRMT_GUIB, m_poRawRaster->GetImgOffset()));
     474             : 
     475           7 :     CPLCreateXMLElementAndValue(
     476             :         psTree, "PixelOffset",
     477           7 :         CPLSPrintf("%d", m_poRawRaster->GetPixelOffset()));
     478             : 
     479           7 :     CPLCreateXMLElementAndValue(
     480           7 :         psTree, "LineOffset", CPLSPrintf("%d", m_poRawRaster->GetLineOffset()));
     481             : 
     482           7 :     switch (m_poRawRaster->GetByteOrder())
     483             :     {
     484           3 :         case RawRasterBand::ByteOrder::ORDER_LITTLE_ENDIAN:
     485           3 :             CPLCreateXMLElementAndValue(psTree, "ByteOrder", "LSB");
     486           3 :             break;
     487           4 :         case RawRasterBand::ByteOrder::ORDER_BIG_ENDIAN:
     488           4 :             CPLCreateXMLElementAndValue(psTree, "ByteOrder", "MSB");
     489           4 :             break;
     490           0 :         case RawRasterBand::ByteOrder::ORDER_VAX:
     491           0 :             CPLCreateXMLElementAndValue(psTree, "ByteOrder", "VAX");
     492           0 :             break;
     493             :     }
     494             : 
     495           7 :     return psTree;
     496             : }
     497             : 
     498             : /************************************************************************/
     499             : /*                             GetFileList()                            */
     500             : /************************************************************************/
     501             : 
     502           3 : void VRTRawRasterBand::GetFileList(char ***ppapszFileList, int *pnSize,
     503             :                                    int *pnMaxSize, CPLHashSet *hSetFiles)
     504             : {
     505           3 :     if (m_pszSourceFilename == nullptr)
     506           1 :         return;
     507             : 
     508             :     /* -------------------------------------------------------------------- */
     509             :     /*      Is it already in the list ?                                     */
     510             :     /* -------------------------------------------------------------------- */
     511           3 :     CPLString osSourceFilename;
     512           3 :     if (m_bRelativeToVRT && strlen(poDS->GetDescription()) > 0)
     513             :         osSourceFilename =
     514           2 :             CPLFormFilename(CPLGetDirname(poDS->GetDescription()),
     515           2 :                             m_pszSourceFilename, nullptr);
     516             :     else
     517           1 :         osSourceFilename = m_pszSourceFilename;
     518             : 
     519           3 :     if (CPLHashSetLookup(hSetFiles, osSourceFilename) != nullptr)
     520           1 :         return;
     521             : 
     522             :     /* -------------------------------------------------------------------- */
     523             :     /*      Grow array if necessary                                         */
     524             :     /* -------------------------------------------------------------------- */
     525           2 :     if (*pnSize + 1 >= *pnMaxSize)
     526             :     {
     527           2 :         *pnMaxSize = 2 + 2 * (*pnMaxSize);
     528           2 :         *ppapszFileList = static_cast<char **>(
     529           2 :             CPLRealloc(*ppapszFileList, sizeof(char *) * (*pnMaxSize)));
     530             :     }
     531             : 
     532             :     /* -------------------------------------------------------------------- */
     533             :     /*      Add the string to the list                                      */
     534             :     /* -------------------------------------------------------------------- */
     535           2 :     (*ppapszFileList)[*pnSize] = CPLStrdup(osSourceFilename);
     536           2 :     (*ppapszFileList)[(*pnSize + 1)] = nullptr;
     537           2 :     CPLHashSetInsert(hSetFiles, (*ppapszFileList)[*pnSize]);
     538             : 
     539           2 :     (*pnSize)++;
     540             : 
     541           2 :     VRTRasterBand::GetFileList(ppapszFileList, pnSize, pnMaxSize, hSetFiles);
     542             : }
     543             : 
     544             : /*! @endcond */

Generated by: LCOV version 1.14