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

Generated by: LCOV version 1.14