LCOV - code coverage report
Current view: top level - frmts/pds - pds4dataset.h (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 54 60 90.0 %
Date: 2024-05-03 15:49:35 Functions: 26 29 89.7 %

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

Generated by: LCOV version 1.14