LCOV - code coverage report
Current view: top level - frmts/pds - pds4dataset.h (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 55 61 90.2 %
Date: 2025-07-09 17:50:03 Functions: 28 32 87.5 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  PDS 4 Driver; Planetary Data System Format
       4             :  * Purpose:  Implementation of PDS4Dataset
       5             :  * Author:   Even Rouault, even.rouault at spatialys.com
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2019, Hobu Inc
       9             :  *
      10             :  * SPDX-License-Identifier: MIT
      11             :  ****************************************************************************/
      12             : 
      13             : #pragma once
      14             : 
      15             : #include "cpl_string.h"
      16             : #include "gdal_priv.h"
      17             : #include "gdal_proxy.h"
      18             : #include "ogreditablelayer.h"
      19             : #include "rawdataset.h"
      20             : #include "ogr_spatialref.h"
      21             : 
      22             : #include <array>
      23             : #include <vector>
      24             : 
      25             : class PDS4Dataset;
      26             : 
      27             : /************************************************************************/
      28             : /* ==================================================================== */
      29             : /*                        PDS4TableBaseLayer                            */
      30             : /* ==================================================================== */
      31             : /************************************************************************/
      32             : 
      33             : class PDS4TableBaseLayer CPL_NON_FINAL : public OGRLayer
      34             : {
      35             :   protected:
      36             :     PDS4Dataset *m_poDS = nullptr;
      37             :     OGRFeatureDefn *m_poRawFeatureDefn = nullptr;
      38             :     OGRFeatureDefn *m_poFeatureDefn = nullptr;
      39             :     CPLString m_osFilename{};
      40             :     int m_iLatField = -1;
      41             :     int m_iLongField = -1;
      42             :     int m_iAltField = -1;
      43             :     int m_iWKT = -1;
      44             :     bool m_bKeepGeomColmuns = false;
      45             :     bool m_bDirtyHeader = false;
      46             :     VSILFILE *m_fp = nullptr;
      47             :     GIntBig m_nFeatureCount = -1;
      48             :     GIntBig m_nFID = 1;
      49             :     vsi_l_offset m_nOffset = 0;
      50             :     CPLStringList m_aosLCO{};
      51             :     std::string m_osLineEnding{};
      52             : 
      53             :     void SetupGeomField();
      54             :     OGRFeature *AddGeometryFromFields(OGRFeature *poFeature);
      55             :     OGRFeature *AddFieldsFromGeometry(OGRFeature *poFeature);
      56             :     void MarkHeaderDirty();
      57             :     CPLXMLNode *RefreshFileAreaObservationalBeginningCommon(
      58             :         CPLXMLNode *psFAO, const CPLString &osPrefix,
      59             :         const char *pszTableEltName, CPLString &osDescription);
      60             :     void ParseLineEndingOption(CSLConstList papszOptions);
      61             : 
      62             :     CPL_DISALLOW_COPY_ASSIGN(PDS4TableBaseLayer)
      63             : 
      64             :   public:
      65             :     PDS4TableBaseLayer(PDS4Dataset *poDS, const char *pszName,
      66             :                        const char *pszFilename);
      67             :     ~PDS4TableBaseLayer();
      68             : 
      69        2703 :     OGRFeatureDefn *GetLayerDefn() override
      70             :     {
      71        2703 :         return m_poFeatureDefn;
      72             :     }
      73             : 
      74             :     GIntBig GetFeatureCount(int bForce) override;
      75             : 
      76         136 :     const char *GetFileName() const
      77             :     {
      78         136 :         return m_osFilename.c_str();
      79             :     }
      80             : 
      81          72 :     bool IsDirtyHeader() const
      82             :     {
      83          72 :         return m_bDirtyHeader;
      84             :     }
      85             : 
      86          69 :     int GetRawFieldCount() const
      87             :     {
      88          69 :         return m_poRawFeatureDefn->GetFieldCount();
      89             :     }
      90             : 
      91             :     bool RenameFileTo(const char *pszNewName);
      92             :     virtual char **GetFileList() const;
      93             : 
      94             :     virtual void RefreshFileAreaObservational(CPLXMLNode *psFAO) = 0;
      95             : 
      96             :     GDALDataset *GetDataset() override;
      97             : };
      98             : 
      99             : /************************************************************************/
     100             : /* ==================================================================== */
     101             : /*                        PDS4FixedWidthTable                           */
     102             : /* ==================================================================== */
     103             : /************************************************************************/
     104             : 
     105             : template <class T> class PDS4EditableSynchronizer;
     106             : 
     107             : class PDS4FixedWidthTable CPL_NON_FINAL : public PDS4TableBaseLayer
     108             : {
     109             :     friend class PDS4EditableSynchronizer<PDS4FixedWidthTable>;
     110             : 
     111             :   protected:
     112             :     int m_nRecordSize = 0;
     113             :     CPLString m_osBuffer{};
     114             : 
     115             :     struct Field
     116             :     {
     117             :         int m_nOffset = 0;  // in XML 1-based, here 0-based
     118             :         int m_nLength = 0;
     119             :         CPLString m_osDataType{};
     120             :         CPLString m_osUnit{};
     121             :         CPLString m_osDescription{};
     122             :         CPLString m_osSpecialConstantsXML{};
     123             :     };
     124             : 
     125             :     std::vector<Field> m_aoFields{};
     126             : 
     127             :     virtual CPLString GetSubType() const = 0;
     128             : 
     129             :     virtual bool CreateFieldInternal(OGRFieldType eType,
     130             :                                      OGRFieldSubType eSubType, int nWidth,
     131             :                                      Field &f) = 0;
     132             : 
     133             :     bool ReadFields(const CPLXMLNode *psParent, int nBaseOffset,
     134             :                     const CPLString &osSuffixFieldName);
     135             : 
     136             :   public:
     137             :     PDS4FixedWidthTable(PDS4Dataset *poDS, const char *pszName,
     138             :                         const char *pszFilename);
     139             : 
     140             :     void ResetReading() override;
     141             :     OGRFeature *GetFeature(GIntBig nFID) override;
     142             :     OGRFeature *GetNextFeature() override;
     143             :     int TestCapability(const char *) override;
     144             :     OGRErr ISetFeature(OGRFeature *poFeature) override;
     145             :     OGRErr ICreateFeature(OGRFeature *poFeature) override;
     146             :     OGRErr CreateField(const OGRFieldDefn *poFieldIn, int) override;
     147             : 
     148             :     bool ReadTableDef(const CPLXMLNode *psTable);
     149             : 
     150             :     bool InitializeNewLayer(const OGRSpatialReference *poSRS,
     151             :                             bool bForceGeographic, OGRwkbGeometryType eGType,
     152             :                             const char *const *papszOptions);
     153             : 
     154             :     virtual PDS4FixedWidthTable *NewLayer(PDS4Dataset *poDS,
     155             :                                           const char *pszName,
     156             :                                           const char *pszFilename) = 0;
     157             : 
     158             :     void RefreshFileAreaObservational(CPLXMLNode *psFAO) override;
     159             : };
     160             : 
     161             : /************************************************************************/
     162             : /* ==================================================================== */
     163             : /*                        PDS4TableCharacter                            */
     164             : /* ==================================================================== */
     165             : /************************************************************************/
     166             : 
     167             : class PDS4TableCharacter final : public PDS4FixedWidthTable
     168             : {
     169         565 :     CPLString GetSubType() const override
     170             :     {
     171         565 :         return "Character";
     172             :     }
     173             : 
     174             :     bool CreateFieldInternal(OGRFieldType eType, OGRFieldSubType eSubType,
     175             :                              int nWidth, Field &f) override;
     176             : 
     177             :   public:
     178             :     PDS4TableCharacter(PDS4Dataset *poDS, const char *pszName,
     179             :                        const char *pszFilename);
     180             : 
     181           2 :     PDS4FixedWidthTable *NewLayer(PDS4Dataset *poDS, const char *pszName,
     182             :                                   const char *pszFilename) override
     183             :     {
     184           2 :         return new PDS4TableCharacter(poDS, pszName, pszFilename);
     185             :     }
     186             : };
     187             : 
     188             : /************************************************************************/
     189             : /* ==================================================================== */
     190             : /*                        PDS4TableBinary                               */
     191             : /* ==================================================================== */
     192             : /************************************************************************/
     193             : 
     194             : class PDS4TableBinary final : public PDS4FixedWidthTable
     195             : {
     196        3258 :     CPLString GetSubType() const override
     197             :     {
     198        3258 :         return "Binary";
     199             :     }
     200             : 
     201             :     bool CreateFieldInternal(OGRFieldType eType, OGRFieldSubType eSubType,
     202             :                              int nWidth, Field &f) override;
     203             : 
     204             :   public:
     205             :     PDS4TableBinary(PDS4Dataset *poDS, const char *pszName,
     206             :                     const char *pszFilename);
     207             : 
     208           0 :     PDS4FixedWidthTable *NewLayer(PDS4Dataset *poDS, const char *pszName,
     209             :                                   const char *pszFilename) override
     210             :     {
     211           0 :         return new PDS4TableBinary(poDS, pszName, pszFilename);
     212             :     }
     213             : };
     214             : 
     215             : /************************************************************************/
     216             : /* ==================================================================== */
     217             : /*                        PDS4DelimitedTable                            */
     218             : /* ==================================================================== */
     219             : /************************************************************************/
     220             : 
     221             : class PDS4DelimitedTable CPL_NON_FINAL : public PDS4TableBaseLayer
     222             : {
     223             :     friend class PDS4EditableSynchronizer<PDS4DelimitedTable>;
     224             : 
     225             :   protected:
     226             :     bool m_bCreation = false;
     227             :     char m_chFieldDelimiter = ',';
     228             :     bool m_bAddWKTColumnPending = false;
     229             : 
     230             :     struct Field
     231             :     {
     232             :         CPLString m_osDataType{};
     233             :         CPLString m_osUnit{};
     234             :         CPLString m_osDescription{};
     235             :         CPLString m_osSpecialConstantsXML{};
     236             :         CPLString m_osMissingConstant{};  // included in above potentially
     237             :     };
     238             : 
     239             :     std::vector<Field> m_aoFields{};
     240             : 
     241             :     OGRFeature *GetNextFeatureRaw();
     242             :     CPLString QuoteIfNeeded(const char *pszVal);
     243             :     void GenerateVRT();
     244             : 
     245             :     bool ReadFields(const CPLXMLNode *psParent,
     246             :                     const CPLString &osSuffixFieldName);
     247             : 
     248             :   public:
     249             :     PDS4DelimitedTable(PDS4Dataset *poDS, const char *pszName,
     250             :                        const char *pszFilename);
     251             :     ~PDS4DelimitedTable() override;
     252             : 
     253             :     void ResetReading() override;
     254             :     OGRFeature *GetNextFeature() override;
     255             :     int TestCapability(const char *) override;
     256             :     OGRErr ICreateFeature(OGRFeature *poFeature) override;
     257             :     OGRErr CreateField(const OGRFieldDefn *poFieldIn, int) override;
     258             : 
     259             :     bool ReadTableDef(const CPLXMLNode *psTable);
     260             : 
     261             :     bool InitializeNewLayer(const OGRSpatialReference *poSRS,
     262             :                             bool bForceGeographic, OGRwkbGeometryType eGType,
     263             :                             const char *const *papszOptions);
     264             : 
     265             :     void RefreshFileAreaObservational(CPLXMLNode *psFAO) override;
     266             :     char **GetFileList() const override;
     267             : 
     268           1 :     PDS4DelimitedTable *NewLayer(PDS4Dataset *poDS, const char *pszName,
     269             :                                  const char *pszFilename)
     270             :     {
     271           1 :         return new PDS4DelimitedTable(poDS, pszName, pszFilename);
     272             :     }
     273             : };
     274             : 
     275             : /************************************************************************/
     276             : /* ==================================================================== */
     277             : /*                         PDS4EditableLayer                            */
     278             : /* ==================================================================== */
     279             : /************************************************************************/
     280             : 
     281         324 : class PDS4EditableLayer final : public OGREditableLayer
     282             : {
     283             :     PDS4TableBaseLayer *GetBaseLayer() const;
     284             : 
     285             :   public:
     286             :     explicit PDS4EditableLayer(PDS4FixedWidthTable *poBaseLayer);
     287             :     explicit PDS4EditableLayer(PDS4DelimitedTable *poBaseLayer);
     288             :     ~PDS4EditableLayer() override;
     289             : 
     290          69 :     void RefreshFileAreaObservational(CPLXMLNode *psFAO)
     291             :     {
     292          69 :         GetBaseLayer()->RefreshFileAreaObservational(psFAO);
     293          69 :     }
     294             : 
     295          69 :     const char *GetFileName() const
     296             :     {
     297          69 :         return GetBaseLayer()->GetFileName();
     298             :     }
     299             : 
     300          72 :     bool IsDirtyHeader() const
     301             :     {
     302          72 :         return GetBaseLayer()->IsDirtyHeader();
     303             :     }
     304             : 
     305          69 :     int GetRawFieldCount() const
     306             :     {
     307          69 :         return GetBaseLayer()->GetRawFieldCount();
     308             :     }
     309             : 
     310             :     void SetSpatialRef(OGRSpatialReference *poSRS);
     311             : 
     312          64 :     char **GetFileList() const
     313             :     {
     314          64 :         return GetBaseLayer()->GetFileList();
     315             :     }
     316             : };
     317             : 
     318             : /************************************************************************/
     319             : /*                            PDS4Dataset                               */
     320             : /************************************************************************/
     321             : 
     322             : class PDS4Dataset final : public RawDataset
     323             : {
     324             :     friend class PDS4RawRasterBand;
     325             :     friend class PDS4WrapperRasterBand;
     326             : 
     327             :     VSILFILE *m_fpImage = nullptr;
     328             :     vsi_l_offset m_nBaseOffset = 0;
     329             :     GDALDataset *m_poExternalDS = nullptr;  // external dataset (GeoTIFF)
     330             :     OGRSpatialReference m_oSRS{};
     331             :     bool m_bGotTransform = false;
     332             :     GDALGeoTransform m_gt{};
     333             :     CPLString m_osXMLFilename{};
     334             :     CPLString m_osImageFilename{};
     335             :     CPLString m_osUnits{};
     336             :     bool m_bCreatedFromExistingBinaryFile = false;
     337             : 
     338             :     std::vector<std::unique_ptr<PDS4EditableLayer>> m_apoLayers{};
     339             : 
     340             :     // Write dedicated parameters
     341             :     bool m_bMustInitImageFile = false;
     342             :     bool m_bUseSrcLabel = true;
     343             :     bool m_bDirtyHeader = false;
     344             :     bool m_bCreateHeader = false;
     345             :     bool m_bStripFileAreaObservationalFromTemplate = false;
     346             :     bool m_bIsLSB = true;
     347             :     CPLString m_osHeaderParsingStandard{};
     348             :     CPLString m_osInterleave{};
     349             :     char **m_papszCreationOptions = nullptr;
     350             :     CPLString m_osXMLPDS4{};
     351             : 
     352             :     void CreateHeader(CPLXMLNode *psProduct, const char *pszCARTVersion);
     353             :     void WriteHeader();
     354             :     void WriteHeaderAppendCase();
     355             :     void WriteVectorLayers(CPLXMLNode *psProduct);
     356             :     void WriteArray(const CPLString &osPrefix, CPLXMLNode *psFAO,
     357             :                     const char *pszLocalIdentifier,
     358             :                     CPLXMLNode *psTemplateSpecialConstants);
     359             :     void WriteGeoreferencing(CPLXMLNode *psCart, const char *pszCARTVersion);
     360             :     void ReadGeoreferencing(CPLXMLNode *psProduct);
     361             :     bool InitImageFile();
     362             : 
     363             :     void SubstituteVariables(CPLXMLNode *psNode, char **papszDict);
     364             : 
     365             :     bool OpenTableCharacter(const char *pszFilename, const CPLXMLNode *psTable);
     366             : 
     367             :     bool OpenTableBinary(const char *pszFilename, const CPLXMLNode *psTable);
     368             : 
     369             :     bool OpenTableDelimited(const char *pszFilename, const CPLXMLNode *psTable);
     370             : 
     371             :     static PDS4Dataset *CreateInternal(const char *pszFilename,
     372             :                                        GDALDataset *poSrcDS, int nXSize,
     373             :                                        int nYSize, int nBands,
     374             :                                        GDALDataType eType,
     375             :                                        const char *const *papszOptions);
     376             : 
     377             :     CPLErr Close() override;
     378             : 
     379             :     CPL_DISALLOW_COPY_ASSIGN(PDS4Dataset)
     380             : 
     381             :   public:
     382             :     PDS4Dataset();
     383             :     virtual ~PDS4Dataset();
     384             : 
     385             :     virtual int CloseDependentDatasets() override;
     386             : 
     387             :     const OGRSpatialReference *GetSpatialRef() const override;
     388             :     CPLErr SetSpatialRef(const OGRSpatialReference *poSRS) override;
     389             :     virtual CPLErr GetGeoTransform(GDALGeoTransform &gt) const override;
     390             :     virtual CPLErr SetGeoTransform(const GDALGeoTransform &gt) override;
     391             :     virtual char **GetFileList() override;
     392             :     virtual CPLErr SetMetadata(char **papszMD,
     393             :                                const char *pszDomain = "") override;
     394             : 
     395        1013 :     int GetLayerCount() override
     396             :     {
     397        1013 :         return static_cast<int>(m_apoLayers.size());
     398             :     }
     399             : 
     400             :     OGRLayer *GetLayer(int) override;
     401             : 
     402             :     OGRLayer *ICreateLayer(const char *pszName,
     403             :                            const OGRGeomFieldDefn *poGeomFieldDefn,
     404             :                            CSLConstList papszOptions) override;
     405             : 
     406             :     int TestCapability(const char *pszCap) override;
     407             : 
     408             :     bool GetRawBinaryLayout(GDALDataset::RawBinaryLayout &) override;
     409             : 
     410             :     static PDS4Dataset *OpenInternal(GDALOpenInfo *);
     411             : 
     412         179 :     static GDALDataset *Open(GDALOpenInfo *poOpenInfo)
     413             :     {
     414         179 :         return OpenInternal(poOpenInfo);
     415             :     }
     416             : 
     417             :     static GDALDataset *Create(const char *pszFilename, int nXSize, int nYSize,
     418             :                                int nBands, GDALDataType eType,
     419             :                                char **papszOptions);
     420             :     static GDALDataset *CreateCopy(const char *pszFilename,
     421             :                                    GDALDataset *poSrcDS, int bStrict,
     422             :                                    char **papszOptions,
     423             :                                    GDALProgressFunc pfnProgress,
     424             :                                    void *pProgressData);
     425             :     static CPLErr Delete(const char *pszName);
     426             : 
     427         262 :     const char *const *GetOpenOptions() const
     428             :     {
     429         262 :         return papszOpenOptions;
     430             :     }
     431             : 
     432         338 :     void MarkHeaderDirty()
     433             :     {
     434         338 :         m_bDirtyHeader = true;
     435         338 :     }
     436             : };
     437             : 
     438             : /************************************************************************/
     439             : /* ==================================================================== */
     440             : /*                        PDS4RawRasterBand                            */
     441             : /* ==================================================================== */
     442             : /************************************************************************/
     443             : 
     444             : class PDS4RawRasterBand final : public RawRasterBand
     445             : {
     446             :     friend class PDS4Dataset;
     447             : 
     448             :     bool m_bHasOffset{};
     449             :     bool m_bHasScale{};
     450             :     bool m_bHasNoData{};
     451             :     double m_dfOffset{};
     452             :     double m_dfScale{};
     453             :     double m_dfNoData{};
     454             : 
     455             :   public:
     456             :     PDS4RawRasterBand(GDALDataset *l_poDS, int l_nBand, VSILFILE *l_fpRaw,
     457             :                       vsi_l_offset l_nImgOffset, int l_nPixelOffset,
     458             :                       int l_nLineOffset, GDALDataType l_eDataType,
     459             :                       RawRasterBand::ByteOrder eByteOrderIn);
     460             : 
     461         844 :     virtual ~PDS4RawRasterBand()
     462         422 :     {
     463         844 :     }
     464             : 
     465             :     virtual CPLErr IWriteBlock(int, int, void *) override;
     466             : 
     467             :     virtual CPLErr IRasterIO(GDALRWFlag, int, int, int, int, void *, int, int,
     468             :                              GDALDataType, GSpacing nPixelSpace,
     469             :                              GSpacing nLineSpace,
     470             :                              GDALRasterIOExtraArg *psExtraArg) override;
     471             : 
     472             :     virtual double GetOffset(int *pbSuccess = nullptr) override;
     473             :     virtual double GetScale(int *pbSuccess = nullptr) override;
     474             :     virtual CPLErr SetOffset(double dfNewOffset) override;
     475             :     virtual CPLErr SetScale(double dfNewScale) override;
     476             :     virtual double GetNoDataValue(int *pbSuccess = nullptr) override;
     477             :     virtual CPLErr SetNoDataValue(double dfNewNoData) override;
     478             : 
     479         116 :     virtual const char *GetUnitType() override
     480             :     {
     481         116 :         return static_cast<PDS4Dataset *>(poDS)->m_osUnits.c_str();
     482             :     }
     483             : 
     484          67 :     virtual CPLErr SetUnitType(const char *pszUnits) override
     485             :     {
     486          67 :         static_cast<PDS4Dataset *>(poDS)->m_osUnits = pszUnits;
     487          67 :         return CE_None;
     488             :     }
     489             : 
     490             :     void SetMaskBand(std::unique_ptr<GDALRasterBand> poMaskBand);
     491             : };
     492             : 
     493             : /************************************************************************/
     494             : /* ==================================================================== */
     495             : /*                         PDS4WrapperRasterBand                       */
     496             : /*                                                                      */
     497             : /*      proxy for bands stored in other formats.                        */
     498             : /* ==================================================================== */
     499             : /************************************************************************/
     500             : class PDS4WrapperRasterBand final : public GDALProxyRasterBand
     501             : {
     502             :     friend class PDS4Dataset;
     503             : 
     504             :     GDALRasterBand *m_poBaseBand{};
     505             :     bool m_bHasOffset{};
     506             :     bool m_bHasScale{};
     507             :     bool m_bHasNoData{};
     508             :     double m_dfOffset{};
     509             :     double m_dfScale{};
     510             :     double m_dfNoData{};
     511             : 
     512             :     CPL_DISALLOW_COPY_ASSIGN(PDS4WrapperRasterBand)
     513             : 
     514             :   protected:
     515             :     virtual GDALRasterBand *
     516         150 :     RefUnderlyingRasterBand(bool /*bForceOpen*/) const override
     517             :     {
     518         150 :         return m_poBaseBand;
     519             :     }
     520             : 
     521             :   public:
     522             :     explicit PDS4WrapperRasterBand(GDALRasterBand *poBaseBandIn);
     523             : 
     524          34 :     ~PDS4WrapperRasterBand()
     525          17 :     {
     526          34 :     }
     527             : 
     528             :     virtual CPLErr Fill(double dfRealValue,
     529             :                         double dfImaginaryValue = 0) override;
     530             :     virtual CPLErr IWriteBlock(int, int, void *) override;
     531             : 
     532             :     virtual CPLErr IRasterIO(GDALRWFlag, int, int, int, int, void *, int, int,
     533             :                              GDALDataType, GSpacing nPixelSpace,
     534             :                              GSpacing nLineSpace,
     535             :                              GDALRasterIOExtraArg *psExtraArg) override;
     536             : 
     537             :     virtual double GetOffset(int *pbSuccess = nullptr) override;
     538             :     virtual double GetScale(int *pbSuccess = nullptr) override;
     539             :     virtual CPLErr SetOffset(double dfNewOffset) override;
     540             :     virtual CPLErr SetScale(double dfNewScale) override;
     541             :     virtual double GetNoDataValue(int *pbSuccess = nullptr) override;
     542             :     virtual CPLErr SetNoDataValue(double dfNewNoData) override;
     543             : 
     544          11 :     virtual const char *GetUnitType() override
     545             :     {
     546          11 :         return static_cast<PDS4Dataset *>(poDS)->m_osUnits.c_str();
     547             :     }
     548             : 
     549          13 :     virtual CPLErr SetUnitType(const char *pszUnits) override
     550             :     {
     551          13 :         static_cast<PDS4Dataset *>(poDS)->m_osUnits = pszUnits;
     552          13 :         return CE_None;
     553             :     }
     554             : 
     555           0 :     int GetMaskFlags() override
     556             :     {
     557           0 :         return nMaskFlags;
     558             :     }
     559             : 
     560           0 :     GDALRasterBand *GetMaskBand() override
     561             :     {
     562           0 :         return poMask;
     563             :     }
     564             : 
     565             :     void SetMaskBand(std::unique_ptr<GDALRasterBand> poMaskBand);
     566             : };
     567             : 
     568             : /************************************************************************/
     569             : /* ==================================================================== */
     570             : /*                             PDS4MaskBand                             */
     571             : /* ==================================================================== */
     572             : 
     573             : class PDS4MaskBand final : public GDALRasterBand
     574             : {
     575             :     GDALRasterBand *m_poBaseBand{};
     576             :     void *m_pBuffer{};
     577             :     std::vector<double> m_adfConstants{};
     578             : 
     579             :     CPL_DISALLOW_COPY_ASSIGN(PDS4MaskBand)
     580             : 
     581             :   public:
     582             :     PDS4MaskBand(GDALRasterBand *poBaseBand,
     583             :                  const std::vector<double> &adfConstants);
     584             :     ~PDS4MaskBand();
     585             : 
     586             :     virtual CPLErr IReadBlock(int, int, void *) override;
     587             : };

Generated by: LCOV version 1.14