LCOV - code coverage report
Current view: top level - frmts/vrt - vrtrawrasterband.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 179 221 81.0 %
Date: 2025-11-16 02:02:06 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          38 : VRTRawRasterBand::VRTRawRasterBand(GDALDataset *poDSIn, int nBandIn,
      45          38 :                                    GDALDataType eType)
      46             :     : m_poRawRaster(nullptr), m_pszSourceFilename(nullptr),
      47          38 :       m_bRelativeToVRT(FALSE)
      48             : {
      49          38 :     if (!VRTDataset::IsRawRasterBandEnabled())
      50             :     {
      51             :         // Safety belt. Not supposed to happen, hence CE_Fatal
      52           0 :         CPLError(CE_Fatal, CPLE_NotSupported,
      53             :                  "Crashing process: VRTRawRasterBand constructor called "
      54             :                  "whereas not authorized");
      55           0 :         return;
      56             :     }
      57             : 
      58          38 :     Initialize(poDSIn->GetRasterXSize(), poDSIn->GetRasterYSize());
      59             : 
      60             :     // Declared in GDALRasterBand.
      61          38 :     poDS = poDSIn;
      62          38 :     nBand = nBandIn;
      63             : 
      64          38 :     if (eType != GDT_Unknown)
      65           6 :         eDataType = eType;
      66             : }
      67             : 
      68             : /************************************************************************/
      69             : /*                         ~VRTRawRasterBand()                          */
      70             : /************************************************************************/
      71             : 
      72          76 : VRTRawRasterBand::~VRTRawRasterBand()
      73             : 
      74             : {
      75          38 :     FlushCache(true);
      76          38 :     ClearRawLink();
      77          76 : }
      78             : 
      79             : /************************************************************************/
      80             : /*                             IRasterIO()                              */
      81             : /************************************************************************/
      82             : 
      83         265 : CPLErr VRTRawRasterBand::IRasterIO(GDALRWFlag eRWFlag, int nXOff, int nYOff,
      84             :                                    int nXSize, int nYSize, void *pData,
      85             :                                    int nBufXSize, int nBufYSize,
      86             :                                    GDALDataType eBufType, GSpacing nPixelSpace,
      87             :                                    GSpacing nLineSpace,
      88             :                                    GDALRasterIOExtraArg *psExtraArg)
      89             : {
      90         265 :     if (m_poRawRaster == nullptr)
      91             :     {
      92           0 :         CPLError(CE_Failure, CPLE_AppDefined,
      93             :                  "No raw raster band configured on VRTRawRasterBand.");
      94           0 :         return CE_Failure;
      95             :     }
      96             : 
      97         265 :     if (eRWFlag == GF_Write && eAccess == GA_ReadOnly)
      98             :     {
      99           0 :         CPLError(CE_Failure, CPLE_NoWriteAccess,
     100             :                  "Attempt to write to read only dataset in"
     101             :                  "VRTRawRasterBand::IRasterIO().");
     102             : 
     103           0 :         return CE_Failure;
     104             :     }
     105             : 
     106             :     /* -------------------------------------------------------------------- */
     107             :     /*      Do we have overviews that would be appropriate to satisfy       */
     108             :     /*      this request?                                                   */
     109             :     /* -------------------------------------------------------------------- */
     110         265 :     if ((nBufXSize < nXSize || nBufYSize < nYSize) && GetOverviewCount() > 0)
     111             :     {
     112           0 :         if (OverviewRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
     113             :                              nBufXSize, nBufYSize, eBufType, nPixelSpace,
     114           0 :                              nLineSpace, psExtraArg) == CE_None)
     115           0 :             return CE_None;
     116             :     }
     117             : 
     118         265 :     m_poRawRaster->SetAccess(eAccess);
     119             : 
     120         265 :     return m_poRawRaster->RasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
     121             :                                    nBufXSize, nBufYSize, eBufType, nPixelSpace,
     122         265 :                                    nLineSpace, psExtraArg);
     123             : }
     124             : 
     125             : /************************************************************************/
     126             : /*                             IReadBlock()                             */
     127             : /************************************************************************/
     128             : 
     129          70 : CPLErr VRTRawRasterBand::IReadBlock(int nBlockXOff, int nBlockYOff,
     130             :                                     void *pImage)
     131             : 
     132             : {
     133          70 :     if (m_poRawRaster == nullptr)
     134             :     {
     135           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     136             :                  "No raw raster band configured on VRTRawRasterBand.");
     137           0 :         return CE_Failure;
     138             :     }
     139             : 
     140          70 :     return m_poRawRaster->ReadBlock(nBlockXOff, nBlockYOff, pImage);
     141             : }
     142             : 
     143             : /************************************************************************/
     144             : /*                            IWriteBlock()                             */
     145             : /************************************************************************/
     146             : 
     147           0 : CPLErr VRTRawRasterBand::IWriteBlock(int nBlockXOff, int nBlockYOff,
     148             :                                      void *pImage)
     149             : 
     150             : {
     151           0 :     if (m_poRawRaster == nullptr)
     152             :     {
     153           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     154             :                  "No raw raster band configured on VRTRawRasterBand.");
     155           0 :         return CE_Failure;
     156             :     }
     157             : 
     158           0 :     m_poRawRaster->SetAccess(eAccess);
     159             : 
     160           0 :     return m_poRawRaster->WriteBlock(nBlockXOff, nBlockYOff, pImage);
     161             : }
     162             : 
     163             : /************************************************************************/
     164             : /*                             SetRawLink()                             */
     165             : /************************************************************************/
     166             : 
     167          38 : CPLErr VRTRawRasterBand::SetRawLink(const char *pszFilename,
     168             :                                     const char *pszVRTPath,
     169             :                                     int bRelativeToVRTIn,
     170             :                                     vsi_l_offset nImageOffset, int nPixelOffset,
     171             :                                     int nLineOffset, const char *pszByteOrder)
     172             : 
     173             : {
     174          38 :     ClearRawLink();
     175             : 
     176          38 :     static_cast<VRTDataset *>(poDS)->SetNeedsFlush();
     177             : 
     178             :     /* -------------------------------------------------------------------- */
     179             :     /*      Prepare filename.                                               */
     180             :     /* -------------------------------------------------------------------- */
     181          38 :     if (pszFilename == nullptr)
     182             :     {
     183           0 :         CPLError(CE_Warning, CPLE_AppDefined,
     184             :                  "Missing <SourceFilename> element in VRTRasterBand.");
     185           0 :         return CE_Failure;
     186             :     }
     187             : 
     188             :     const std::string osExpandedFilename =
     189          28 :         (pszVRTPath && bRelativeToVRTIn)
     190          38 :             ? CPLProjectRelativeFilenameSafe(pszVRTPath, pszFilename)
     191         132 :             : pszFilename;
     192             : 
     193             :     const char *pszAllowedPaths =
     194          38 :         CPLGetConfigOption("GDAL_VRT_RAWRASTERBAND_ALLOWED_SOURCE", nullptr);
     195          38 :     if (pszAllowedPaths == nullptr ||
     196          12 :         EQUAL(pszAllowedPaths, "SIBLING_OR_CHILD_OF_VRT_PATH"))
     197             :     {
     198          28 :         const char *pszErrorMsgPart =
     199             :             pszAllowedPaths
     200          28 :                 ? "GDAL_VRT_RAWRASTERBAND_ALLOWED_SOURCE=SIBLING_OR_CHILD_OF_"
     201             :                   "VRT_PATH"
     202             :                 : "the GDAL_VRT_RAWRASTERBAND_ALLOWED_SOURCE configuration "
     203             :                   "option is not set (and thus defaults to "
     204             :                   "SIBLING_OR_CHILD_OF_VRT_PATH. Consult "
     205             :                   "https://gdal.org/drivers/raster/"
     206             :                   "vrt.html#vrtrawrasterband_restricted_access for more "
     207             :                   "details)";
     208          28 :         if (!bRelativeToVRTIn)
     209             :         {
     210           1 :             CPLError(CE_Failure, CPLE_AppDefined,
     211             :                      "'%s' is invalid because the relativeToVRT flag is not "
     212             :                      "set and %s",
     213             :                      pszFilename, pszErrorMsgPart);
     214           1 :             return CE_Failure;
     215             :         }
     216          27 :         if (!CPLIsFilenameRelative(pszFilename))
     217             :         {
     218           1 :             CPLError(CE_Failure, CPLE_AppDefined,
     219             :                      "'%s' is invalid because it is not relative to the VRT "
     220             :                      "path and %s",
     221             :                      pszFilename, pszErrorMsgPart);
     222           1 :             return CE_Failure;
     223             :         }
     224          26 :         if (strstr(pszFilename, "../") || strstr(pszFilename, "..\\"))
     225             :         {
     226           1 :             CPLError(CE_Failure, CPLE_AppDefined,
     227             :                      "'%s' is invalid because it may not be a sibling or "
     228             :                      "child of the VRT path and %s",
     229             :                      pszFilename, pszErrorMsgPart);
     230           1 :             return CE_Failure;
     231          25 :         }
     232             :     }
     233          10 :     else if (EQUAL(pszAllowedPaths, "ALL"))
     234             :     {
     235             :         // ok
     236             :     }
     237           6 :     else if (EQUAL(pszAllowedPaths, "ONLY_REMOTE"))
     238             :     {
     239           2 :         if (VSIIsLocal(pszFilename))
     240             :         {
     241           1 :             CPLError(CE_Failure, CPLE_AppDefined,
     242             :                      "'%s' is a local file, whereas "
     243             :                      "GDAL_VRT_RAWRASTERBAND_ALLOWED_SOURCE=ONLY_REMOTE is set",
     244             :                      pszFilename);
     245           1 :             return CE_Failure;
     246             :         }
     247             :     }
     248             :     else
     249             :     {
     250           4 :         if (strstr(pszFilename, "../") || strstr(pszFilename, "..\\"))
     251             :         {
     252           1 :             CPLError(CE_Failure, CPLE_AppDefined,
     253             :                      "'%s' is invalid because the presence of ../ in it may "
     254             :                      "escape from the allowed path(s)",
     255             :                      pszFilename);
     256           3 :             return CE_Failure;
     257             :         }
     258             : #ifdef _WIN32
     259             :         constexpr const char *pszSep = ";";
     260             : #else
     261           3 :         constexpr const char *pszSep = ":";
     262             : #endif
     263           3 :         bool bOK = false;
     264             :         const CPLStringList aosPaths(
     265           3 :             CSLTokenizeString2(pszAllowedPaths, pszSep, 0));
     266           4 :         for (const char *pszPath : aosPaths)
     267             :         {
     268           3 :             if (CPLIsFilenameRelative(pszPath))
     269             :             {
     270           1 :                 CPLError(
     271             :                     CE_Failure, CPLE_AppDefined,
     272             :                     "Invalid value for GDAL_VRT_RAWRASTERBAND_ALLOWED_SOURCE. "
     273             :                     "'%s' is not an absolute path",
     274             :                     pszPath);
     275           1 :                 return CE_Failure;
     276             :             }
     277           2 :             if (STARTS_WITH(osExpandedFilename.c_str(), pszPath))
     278             :             {
     279           1 :                 bOK = true;
     280           1 :                 break;
     281             :             }
     282             :         }
     283           2 :         if (!bOK)
     284             :         {
     285           1 :             CPLError(CE_Failure, CPLE_AppDefined,
     286             :                      "'%s' is invalid because it is not contained in one of "
     287             :                      "the allowed path(s)",
     288             :                      pszFilename);
     289           1 :             return CE_Failure;
     290             :         }
     291             :     }
     292             : 
     293             :     /* -------------------------------------------------------------------- */
     294             :     /*      Try and open the file.  We always use the large file API.       */
     295             :     /* -------------------------------------------------------------------- */
     296          31 :     CPLPushErrorHandler(CPLQuietErrorHandler);
     297          31 :     FILE *fp = CPLOpenShared(osExpandedFilename.c_str(), "rb+", TRUE);
     298             : 
     299          31 :     if (fp == nullptr)
     300           5 :         fp = CPLOpenShared(osExpandedFilename.c_str(), "rb", TRUE);
     301             : 
     302          35 :     if (fp == nullptr &&
     303           4 :         static_cast<VRTDataset *>(poDS)->GetAccess() == GA_Update)
     304             :     {
     305           3 :         fp = CPLOpenShared(osExpandedFilename.c_str(), "wb+", TRUE);
     306             :     }
     307          31 :     CPLPopErrorHandler();
     308          31 :     CPLErrorReset();
     309             : 
     310          31 :     if (fp == nullptr)
     311             :     {
     312           1 :         CPLError(CE_Failure, CPLE_OpenFailed, "Unable to open %s.%s",
     313           1 :                  osExpandedFilename.c_str(), VSIStrerror(errno));
     314             : 
     315           1 :         return CE_Failure;
     316             :     }
     317             : 
     318          30 :     if (!RAWDatasetCheckMemoryUsage(
     319             :             nRasterXSize, nRasterYSize, 1,
     320             :             GDALGetDataTypeSizeBytes(GetRasterDataType()), nPixelOffset,
     321             :             nLineOffset, nImageOffset, 0, reinterpret_cast<VSILFILE *>(fp)))
     322             :     {
     323           2 :         CPLCloseShared(fp);
     324           2 :         return CE_Failure;
     325             :     }
     326             : 
     327          28 :     m_pszSourceFilename = CPLStrdup(pszFilename);
     328          28 :     m_bRelativeToVRT = bRelativeToVRTIn;
     329             : 
     330             :     /* -------------------------------------------------------------------- */
     331             :     /*      Work out if we are in native mode or not.                       */
     332             :     /* -------------------------------------------------------------------- */
     333             :     RawRasterBand::ByteOrder eByteOrder;
     334             :     if constexpr (CPL_IS_LSB)
     335          28 :         eByteOrder = RawRasterBand::ByteOrder::ORDER_LITTLE_ENDIAN;
     336             :     else
     337             :         eByteOrder = RawRasterBand::ByteOrder::ORDER_BIG_ENDIAN;
     338             : 
     339          28 :     if (pszByteOrder != nullptr)
     340             :     {
     341          26 :         if (EQUAL(pszByteOrder, "LSB"))
     342          14 :             eByteOrder = RawRasterBand::ByteOrder::ORDER_LITTLE_ENDIAN;
     343          12 :         else if (EQUAL(pszByteOrder, "MSB"))
     344           7 :             eByteOrder = RawRasterBand::ByteOrder::ORDER_BIG_ENDIAN;
     345           5 :         else if (EQUAL(pszByteOrder, "VAX"))
     346           4 :             eByteOrder = RawRasterBand::ByteOrder::ORDER_VAX;
     347             :         else
     348             :         {
     349           1 :             CPLError(CE_Failure, CPLE_AppDefined,
     350             :                      "Illegal ByteOrder value '%s', should be LSB, MSB or VAX.",
     351             :                      pszByteOrder);
     352           1 :             CPLCloseShared(fp);
     353           1 :             return CE_Failure;
     354             :         }
     355             :     }
     356             : 
     357             :     /* -------------------------------------------------------------------- */
     358             :     /*      Create a corresponding RawRasterBand.                           */
     359             :     /* -------------------------------------------------------------------- */
     360          27 :     m_poRawRaster =
     361          54 :         RawRasterBand::Create(reinterpret_cast<VSILFILE *>(fp), nImageOffset,
     362             :                               nPixelOffset, nLineOffset, GetRasterDataType(),
     363             :                               eByteOrder, GetXSize(), GetYSize(),
     364             :                               RawRasterBand::OwnFP::NO)
     365          27 :             .release();
     366          27 :     if (!m_poRawRaster)
     367             :     {
     368           0 :         CPLCloseShared(fp);
     369           0 :         return CE_Failure;
     370             :     }
     371             : 
     372             :     /* -------------------------------------------------------------------- */
     373             :     /*      Reset block size to match the raw raster.                       */
     374             :     /* -------------------------------------------------------------------- */
     375          27 :     m_poRawRaster->GetBlockSize(&nBlockXSize, &nBlockYSize);
     376             : 
     377          27 :     return CE_None;
     378             : }
     379             : 
     380             : /************************************************************************/
     381             : /*                            ClearRawLink()                            */
     382             : /************************************************************************/
     383             : 
     384          76 : void VRTRawRasterBand::ClearRawLink()
     385             : 
     386             : {
     387          76 :     if (m_poRawRaster != nullptr)
     388             :     {
     389          27 :         VSILFILE *fp = m_poRawRaster->GetFPL();
     390          27 :         delete m_poRawRaster;
     391          27 :         m_poRawRaster = nullptr;
     392             :         // We close the file after deleting the raster band
     393             :         // since data can be flushed in the destructor.
     394          27 :         if (fp != nullptr)
     395             :         {
     396          27 :             CPLCloseShared(reinterpret_cast<FILE *>(fp));
     397             :         }
     398             :     }
     399          76 :     CPLFree(m_pszSourceFilename);
     400          76 :     m_pszSourceFilename = nullptr;
     401          76 : }
     402             : 
     403             : /************************************************************************/
     404             : /*                            GetVirtualMemAuto()                       */
     405             : /************************************************************************/
     406             : 
     407           0 : CPLVirtualMem *VRTRawRasterBand::GetVirtualMemAuto(GDALRWFlag eRWFlag,
     408             :                                                    int *pnPixelSpace,
     409             :                                                    GIntBig *pnLineSpace,
     410             :                                                    char **papszOptions)
     411             : 
     412             : {
     413             :     // check the pointer to RawRasterBand
     414           0 :     if (m_poRawRaster == nullptr)
     415             :     {
     416             :         // use the super class method
     417           0 :         return VRTRasterBand::GetVirtualMemAuto(eRWFlag, pnPixelSpace,
     418           0 :                                                 pnLineSpace, papszOptions);
     419             :     }
     420             :     // if available, use the RawRasterBand method (use mmap if available)
     421           0 :     return m_poRawRaster->GetVirtualMemAuto(eRWFlag, pnPixelSpace, pnLineSpace,
     422           0 :                                             papszOptions);
     423             : }
     424             : 
     425             : /************************************************************************/
     426             : /*                              XMLInit()                               */
     427             : /************************************************************************/
     428             : 
     429          32 : CPLErr VRTRawRasterBand::XMLInit(const CPLXMLNode *psTree,
     430             :                                  const char *pszVRTPath,
     431             :                                  VRTMapSharedResources &oMapSharedSources)
     432             : 
     433             : {
     434             :     const CPLErr eErr =
     435          32 :         VRTRasterBand::XMLInit(psTree, pszVRTPath, oMapSharedSources);
     436          32 :     if (eErr != CE_None)
     437           0 :         return eErr;
     438             : 
     439             :     /* -------------------------------------------------------------------- */
     440             :     /*      Validate a bit.                                                 */
     441             :     /* -------------------------------------------------------------------- */
     442          32 :     if (psTree == nullptr || psTree->eType != CXT_Element ||
     443          96 :         !EQUAL(psTree->pszValue, "VRTRasterBand") ||
     444          32 :         !EQUAL(CPLGetXMLValue(psTree, "subClass", ""), "VRTRawRasterBand"))
     445             :     {
     446           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     447             :                  "Invalid node passed to VRTRawRasterBand::XMLInit().");
     448           0 :         return CE_Failure;
     449             :     }
     450             : 
     451             :     /* -------------------------------------------------------------------- */
     452             :     /*      Prepare filename.                                               */
     453             :     /* -------------------------------------------------------------------- */
     454          32 :     const char *pszFilename = CPLGetXMLValue(psTree, "SourceFilename", nullptr);
     455             : 
     456          32 :     if (pszFilename == nullptr)
     457             :     {
     458           0 :         CPLError(CE_Warning, CPLE_AppDefined,
     459             :                  "Missing <SourceFilename> element in VRTRasterBand.");
     460           0 :         return CE_Failure;
     461             :     }
     462             : 
     463          32 :     const bool l_bRelativeToVRT = CPLTestBool(
     464             :         CPLGetXMLValue(psTree, "SourceFilename.relativeToVRT", "1"));
     465             : 
     466             :     /* -------------------------------------------------------------------- */
     467             :     /*      Collect layout information.                                     */
     468             :     /* -------------------------------------------------------------------- */
     469          32 :     int nWordDataSize = GDALGetDataTypeSizeBytes(GetRasterDataType());
     470             : 
     471          32 :     const char *pszImageOffset = CPLGetXMLValue(psTree, "ImageOffset", "0");
     472          64 :     const vsi_l_offset nImageOffset = CPLScanUIntBig(
     473          32 :         pszImageOffset, static_cast<int>(strlen(pszImageOffset)));
     474             : 
     475          32 :     int nPixelOffset = nWordDataSize;
     476          32 :     const char *pszPixelOffset = CPLGetXMLValue(psTree, "PixelOffset", nullptr);
     477          32 :     if (pszPixelOffset != nullptr)
     478             :     {
     479          24 :         nPixelOffset = atoi(pszPixelOffset);
     480             :     }
     481          32 :     if (nPixelOffset <= 0)
     482             :     {
     483           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     484             :                  "Invalid value for <PixelOffset> element : %d", nPixelOffset);
     485           0 :         return CE_Failure;
     486             :     }
     487             : 
     488          32 :     int nLineOffset = 0;
     489          32 :     const char *pszLineOffset = CPLGetXMLValue(psTree, "LineOffset", nullptr);
     490          32 :     if (pszLineOffset == nullptr)
     491             :     {
     492           8 :         if (nPixelOffset > INT_MAX / GetXSize())
     493             :         {
     494           0 :             CPLError(CE_Failure, CPLE_AppDefined, "Int overflow");
     495           0 :             return CE_Failure;
     496             :         }
     497           8 :         nLineOffset = nPixelOffset * GetXSize();
     498             :     }
     499             :     else
     500          24 :         nLineOffset = atoi(pszLineOffset);
     501             : 
     502          32 :     const char *pszByteOrder = CPLGetXMLValue(psTree, "ByteOrder", nullptr);
     503             : 
     504             :     /* -------------------------------------------------------------------- */
     505             :     /*      Open the file, and setup the raw layer access to the data.      */
     506             :     /* -------------------------------------------------------------------- */
     507          32 :     return SetRawLink(pszFilename, pszVRTPath, l_bRelativeToVRT, nImageOffset,
     508          32 :                       nPixelOffset, nLineOffset, pszByteOrder);
     509             : }
     510             : 
     511             : /************************************************************************/
     512             : /*                           SerializeToXML()                           */
     513             : /************************************************************************/
     514             : 
     515           7 : CPLXMLNode *VRTRawRasterBand::SerializeToXML(const char *pszVRTPath,
     516             :                                              bool &bHasWarnedAboutRAMUsage,
     517             :                                              size_t &nAccRAMUsage)
     518             : 
     519             : {
     520             : 
     521             :     /* -------------------------------------------------------------------- */
     522             :     /*      We can't set the layout if there is no open rawband.            */
     523             :     /* -------------------------------------------------------------------- */
     524           7 :     if (m_poRawRaster == nullptr)
     525             :     {
     526           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     527             :                  "VRTRawRasterBand::SerializeToXML() fails because "
     528             :                  "m_poRawRaster is NULL.");
     529           0 :         return nullptr;
     530             :     }
     531             : 
     532           7 :     CPLXMLNode *psTree = VRTRasterBand::SerializeToXML(
     533             :         pszVRTPath, bHasWarnedAboutRAMUsage, nAccRAMUsage);
     534             : 
     535             :     /* -------------------------------------------------------------------- */
     536             :     /*      Set subclass.                                                   */
     537             :     /* -------------------------------------------------------------------- */
     538           7 :     CPLCreateXMLNode(CPLCreateXMLNode(psTree, CXT_Attribute, "subClass"),
     539             :                      CXT_Text, "VRTRawRasterBand");
     540             : 
     541             :     /* -------------------------------------------------------------------- */
     542             :     /*      Setup the filename with relative flag.                          */
     543             :     /* -------------------------------------------------------------------- */
     544          14 :     CPLXMLNode *psNode = CPLCreateXMLElementAndValue(psTree, "SourceFilename",
     545           7 :                                                      m_pszSourceFilename);
     546             : 
     547           7 :     CPLCreateXMLNode(CPLCreateXMLNode(psNode, CXT_Attribute, "relativeToVRT"),
     548           7 :                      CXT_Text, m_bRelativeToVRT ? "1" : "0");
     549             : 
     550             :     /* -------------------------------------------------------------------- */
     551             :     /*      Set other layout information.                                   */
     552             :     /* -------------------------------------------------------------------- */
     553             : 
     554           7 :     CPLCreateXMLElementAndValue(
     555             :         psTree, "ImageOffset",
     556           7 :         CPLSPrintf(CPL_FRMT_GUIB, m_poRawRaster->GetImgOffset()));
     557             : 
     558           7 :     CPLCreateXMLElementAndValue(
     559             :         psTree, "PixelOffset",
     560           7 :         CPLSPrintf("%d", m_poRawRaster->GetPixelOffset()));
     561             : 
     562           7 :     CPLCreateXMLElementAndValue(
     563           7 :         psTree, "LineOffset", CPLSPrintf("%d", m_poRawRaster->GetLineOffset()));
     564             : 
     565           7 :     switch (m_poRawRaster->GetByteOrder())
     566             :     {
     567           3 :         case RawRasterBand::ByteOrder::ORDER_LITTLE_ENDIAN:
     568           3 :             CPLCreateXMLElementAndValue(psTree, "ByteOrder", "LSB");
     569           3 :             break;
     570           4 :         case RawRasterBand::ByteOrder::ORDER_BIG_ENDIAN:
     571           4 :             CPLCreateXMLElementAndValue(psTree, "ByteOrder", "MSB");
     572           4 :             break;
     573           0 :         case RawRasterBand::ByteOrder::ORDER_VAX:
     574           0 :             CPLCreateXMLElementAndValue(psTree, "ByteOrder", "VAX");
     575           0 :             break;
     576             :     }
     577             : 
     578           7 :     return psTree;
     579             : }
     580             : 
     581             : /************************************************************************/
     582             : /*                             GetFileList()                            */
     583             : /************************************************************************/
     584             : 
     585           3 : void VRTRawRasterBand::GetFileList(char ***ppapszFileList, int *pnSize,
     586             :                                    int *pnMaxSize, CPLHashSet *hSetFiles)
     587             : {
     588           3 :     if (m_pszSourceFilename == nullptr)
     589           1 :         return;
     590             : 
     591             :     /* -------------------------------------------------------------------- */
     592             :     /*      Is it already in the list ?                                     */
     593             :     /* -------------------------------------------------------------------- */
     594           3 :     CPLString osSourceFilename;
     595           3 :     if (m_bRelativeToVRT && strlen(poDS->GetDescription()) > 0)
     596           3 :         osSourceFilename = CPLFormFilenameSafe(
     597           6 :             CPLGetDirnameSafe(poDS->GetDescription()).c_str(),
     598           6 :             m_pszSourceFilename, nullptr);
     599             :     else
     600           0 :         osSourceFilename = m_pszSourceFilename;
     601             : 
     602           3 :     if (CPLHashSetLookup(hSetFiles, osSourceFilename.c_str()) != nullptr)
     603           1 :         return;
     604             : 
     605             :     /* -------------------------------------------------------------------- */
     606             :     /*      Grow array if necessary                                         */
     607             :     /* -------------------------------------------------------------------- */
     608           2 :     if (*pnSize + 1 >= *pnMaxSize)
     609             :     {
     610           2 :         *pnMaxSize = 2 + 2 * (*pnMaxSize);
     611           2 :         *ppapszFileList = static_cast<char **>(
     612           2 :             CPLRealloc(*ppapszFileList, sizeof(char *) * (*pnMaxSize)));
     613             :     }
     614             : 
     615             :     /* -------------------------------------------------------------------- */
     616             :     /*      Add the string to the list                                      */
     617             :     /* -------------------------------------------------------------------- */
     618           2 :     (*ppapszFileList)[*pnSize] = CPLStrdup(osSourceFilename);
     619           2 :     (*ppapszFileList)[(*pnSize + 1)] = nullptr;
     620           2 :     CPLHashSetInsert(hSetFiles, (*ppapszFileList)[*pnSize]);
     621             : 
     622           2 :     (*pnSize)++;
     623             : 
     624           2 :     VRTRasterBand::GetFileList(ppapszFileList, pnSize, pnMaxSize, hSetFiles);
     625             : }
     626             : 
     627             : /*! @endcond */

Generated by: LCOV version 1.14