LCOV - code coverage report
Current view: top level - frmts/raw - snodasdataset.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 227 245 92.7 %
Date: 2024-05-03 15:49:35 Functions: 16 16 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  SNODAS driver
       4             :  * Purpose:  Implementation of SNODASDataset
       5             :  * Author:   Even Rouault, <even dot rouault at spatialys.com>
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2011, Even Rouault <even dot rouault at spatialys.com>
       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             : #include "cpl_string.h"
      30             : #include "gdal_frmts.h"
      31             : #include "ogr_srs_api.h"
      32             : #include "rawdataset.h"
      33             : 
      34             : /************************************************************************/
      35             : /* ==================================================================== */
      36             : /*                            SNODASDataset                             */
      37             : /* ==================================================================== */
      38             : /************************************************************************/
      39             : 
      40             : class SNODASRasterBand;
      41             : 
      42             : class SNODASDataset final : public RawDataset
      43             : {
      44             :     CPLString osDataFilename{};
      45             :     bool bGotTransform;
      46             :     double adfGeoTransform[6];
      47             :     bool bHasNoData;
      48             :     double dfNoData;
      49             :     bool bHasMin;
      50             :     double dfMin;
      51             :     int bHasMax;
      52             :     double dfMax;
      53             :     OGRSpatialReference m_oSRS{};
      54             : 
      55             :     friend class SNODASRasterBand;
      56             : 
      57             :     CPL_DISALLOW_COPY_ASSIGN(SNODASDataset)
      58             : 
      59             :     CPLErr Close() override;
      60             : 
      61             :   public:
      62             :     SNODASDataset();
      63             :     ~SNODASDataset() override;
      64             : 
      65             :     CPLErr GetGeoTransform(double *padfTransform) override;
      66             : 
      67           1 :     const OGRSpatialReference *GetSpatialRef() const override
      68             :     {
      69           1 :         return &m_oSRS;
      70             :     }
      71             : 
      72             :     char **GetFileList() override;
      73             : 
      74             :     static GDALDataset *Open(GDALOpenInfo *);
      75             :     static int Identify(GDALOpenInfo *);
      76             : };
      77             : 
      78             : /************************************************************************/
      79             : /* ==================================================================== */
      80             : /*                            SNODASRasterBand                          */
      81             : /* ==================================================================== */
      82             : /************************************************************************/
      83             : 
      84             : class SNODASRasterBand final : public RawRasterBand
      85             : {
      86             :     CPL_DISALLOW_COPY_ASSIGN(SNODASRasterBand)
      87             : 
      88             :   public:
      89             :     SNODASRasterBand(VSILFILE *fpRaw, int nXSize, int nYSize);
      90             : 
      91           6 :     ~SNODASRasterBand() override
      92           3 :     {
      93           6 :     }
      94             : 
      95             :     double GetNoDataValue(int *pbSuccess = nullptr) override;
      96             :     double GetMinimum(int *pbSuccess = nullptr) override;
      97             :     double GetMaximum(int *pbSuccess = nullptr) override;
      98             : };
      99             : 
     100             : /************************************************************************/
     101             : /*                         SNODASRasterBand()                           */
     102             : /************************************************************************/
     103             : 
     104           3 : SNODASRasterBand::SNODASRasterBand(VSILFILE *fpRawIn, int nXSize, int nYSize)
     105             :     : RawRasterBand(fpRawIn, 0, 2, nXSize * 2, GDT_Int16, !CPL_IS_LSB, nXSize,
     106           3 :                     nYSize, RawRasterBand::OwnFP::YES)
     107             : {
     108           3 : }
     109             : 
     110             : /************************************************************************/
     111             : /*                          GetNoDataValue()                            */
     112             : /************************************************************************/
     113             : 
     114           1 : double SNODASRasterBand::GetNoDataValue(int *pbSuccess)
     115             : {
     116           1 :     SNODASDataset *poGDS = reinterpret_cast<SNODASDataset *>(poDS);
     117           1 :     if (pbSuccess)
     118           1 :         *pbSuccess = poGDS->bHasNoData;
     119             : 
     120           1 :     if (poGDS->bHasNoData)
     121           1 :         return poGDS->dfNoData;
     122             : 
     123           0 :     return RawRasterBand::GetNoDataValue(pbSuccess);
     124             : }
     125             : 
     126             : /************************************************************************/
     127             : /*                            GetMinimum()                              */
     128             : /************************************************************************/
     129             : 
     130           1 : double SNODASRasterBand::GetMinimum(int *pbSuccess)
     131             : {
     132           1 :     SNODASDataset *poGDS = reinterpret_cast<SNODASDataset *>(poDS);
     133           1 :     if (pbSuccess)
     134           1 :         *pbSuccess = poGDS->bHasMin;
     135             : 
     136           1 :     if (poGDS->bHasMin)
     137           1 :         return poGDS->dfMin;
     138             : 
     139           0 :     return RawRasterBand::GetMinimum(pbSuccess);
     140             : }
     141             : 
     142             : /************************************************************************/
     143             : /*                            GetMaximum()                             */
     144             : /************************************************************************/
     145             : 
     146           1 : double SNODASRasterBand::GetMaximum(int *pbSuccess)
     147             : {
     148           1 :     SNODASDataset *poGDS = reinterpret_cast<SNODASDataset *>(poDS);
     149           1 :     if (pbSuccess)
     150           1 :         *pbSuccess = poGDS->bHasMax;
     151             : 
     152           1 :     if (poGDS->bHasMax)
     153           1 :         return poGDS->dfMax;
     154             : 
     155           0 :     return RawRasterBand::GetMaximum(pbSuccess);
     156             : }
     157             : 
     158             : /************************************************************************/
     159             : /* ==================================================================== */
     160             : /*                            SNODASDataset                             */
     161             : /* ==================================================================== */
     162             : /************************************************************************/
     163             : 
     164             : /************************************************************************/
     165             : /*                           SNODASDataset()                            */
     166             : /************************************************************************/
     167             : 
     168           3 : SNODASDataset::SNODASDataset()
     169             :     : bGotTransform(false), bHasNoData(false), dfNoData(0.0), bHasMin(false),
     170           3 :       dfMin(0.0), bHasMax(false), dfMax(0.0)
     171             : {
     172           3 :     m_oSRS.SetFromUserInput(SRS_WKT_WGS84_LAT_LONG);
     173           3 :     m_oSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
     174             : 
     175           3 :     adfGeoTransform[0] = 0.0;
     176           3 :     adfGeoTransform[1] = 1.0;
     177           3 :     adfGeoTransform[2] = 0.0;
     178           3 :     adfGeoTransform[3] = 0.0;
     179           3 :     adfGeoTransform[4] = 0.0;
     180           3 :     adfGeoTransform[5] = 1.0;
     181           3 : }
     182             : 
     183             : /************************************************************************/
     184             : /*                           ~SNODASDataset()                           */
     185             : /************************************************************************/
     186             : 
     187           6 : SNODASDataset::~SNODASDataset()
     188             : 
     189             : {
     190           3 :     SNODASDataset::Close();
     191           6 : }
     192             : 
     193             : /************************************************************************/
     194             : /*                              Close()                                 */
     195             : /************************************************************************/
     196             : 
     197           6 : CPLErr SNODASDataset::Close()
     198             : {
     199           6 :     CPLErr eErr = CE_None;
     200           6 :     if (nOpenFlags != OPEN_FLAGS_CLOSED)
     201             :     {
     202           3 :         if (SNODASDataset::FlushCache(true) != CE_None)
     203           0 :             eErr = CE_Failure;
     204             : 
     205           3 :         if (GDALPamDataset::Close() != CE_None)
     206           0 :             eErr = CE_Failure;
     207             :     }
     208           6 :     return eErr;
     209             : }
     210             : 
     211             : /************************************************************************/
     212             : /*                          GetGeoTransform()                           */
     213             : /************************************************************************/
     214             : 
     215           1 : CPLErr SNODASDataset::GetGeoTransform(double *padfTransform)
     216             : 
     217             : {
     218           1 :     if (bGotTransform)
     219             :     {
     220           1 :         memcpy(padfTransform, adfGeoTransform, sizeof(double) * 6);
     221           1 :         return CE_None;
     222             :     }
     223             : 
     224           0 :     return GDALPamDataset::GetGeoTransform(padfTransform);
     225             : }
     226             : 
     227             : /************************************************************************/
     228             : /*                            GetFileList()                             */
     229             : /************************************************************************/
     230             : 
     231           2 : char **SNODASDataset::GetFileList()
     232             : 
     233             : {
     234           2 :     char **papszFileList = GDALPamDataset::GetFileList();
     235             : 
     236           2 :     papszFileList = CSLAddString(papszFileList, osDataFilename);
     237             : 
     238           2 :     return papszFileList;
     239             : }
     240             : 
     241             : /************************************************************************/
     242             : /*                            Identify()                                */
     243             : /************************************************************************/
     244             : 
     245       48725 : int SNODASDataset::Identify(GDALOpenInfo *poOpenInfo)
     246             : {
     247       48725 :     if (poOpenInfo->nHeaderBytes == 0)
     248       45321 :         return FALSE;
     249             : 
     250        3404 :     return STARTS_WITH_CI(reinterpret_cast<char *>(poOpenInfo->pabyHeader),
     251             :                           "Format version: NOHRSC GIS/RS raster file v1.1");
     252             : }
     253             : 
     254             : /************************************************************************/
     255             : /*                                Open()                                */
     256             : /************************************************************************/
     257             : 
     258           3 : GDALDataset *SNODASDataset::Open(GDALOpenInfo *poOpenInfo)
     259             : 
     260             : {
     261           3 :     if (!Identify(poOpenInfo) || poOpenInfo->fpL == nullptr)
     262           0 :         return nullptr;
     263             : 
     264             :     /* -------------------------------------------------------------------- */
     265             :     /*      Confirm the requested access is supported.                      */
     266             :     /* -------------------------------------------------------------------- */
     267           3 :     if (poOpenInfo->eAccess == GA_Update)
     268             :     {
     269           0 :         CPLError(CE_Failure, CPLE_NotSupported,
     270             :                  "The SNODAS driver does not support update access to existing"
     271             :                  " datasets.");
     272           0 :         return nullptr;
     273             :     }
     274             : 
     275           3 :     int nRows = -1;
     276           3 :     int nCols = -1;
     277           6 :     CPLString osDataFilename;
     278           3 :     bool bIsInteger = false;
     279           3 :     bool bIs2Bytes = false;
     280           3 :     double dfNoData = 0;
     281           3 :     bool bHasNoData = false;
     282           3 :     double dfMin = 0;
     283           3 :     bool bHasMin = false;
     284           3 :     double dfMax = 0;
     285           3 :     bool bHasMax = false;
     286           3 :     double dfMinX = 0.0;
     287           3 :     double dfMinY = 0.0;
     288           3 :     double dfMaxX = 0.0;
     289           3 :     double dfMaxY = 0.0;
     290           3 :     bool bHasMinX = false;
     291           3 :     bool bHasMinY = false;
     292           3 :     bool bHasMaxX = false;
     293           3 :     bool bHasMaxY = false;
     294           3 :     bool bNotProjected = false;
     295           3 :     bool bIsWGS84 = false;
     296           6 :     CPLString osDataUnits;
     297           6 :     CPLString osDescription;
     298           3 :     int nStartYear = -1;
     299           3 :     int nStartMonth = -1;
     300           3 :     int nStartDay = -1;
     301           3 :     int nStartHour = -1;
     302           3 :     int nStartMinute = -1;
     303           3 :     int nStartSecond = -1;
     304           3 :     int nStopYear = -1;
     305           3 :     int nStopMonth = -1;
     306           3 :     int nStopDay = -1;
     307           3 :     int nStopHour = -1;
     308           3 :     int nStopMinute = -1;
     309           3 :     int nStopSecond = -1;
     310             : 
     311           3 :     const char *pszLine = nullptr;
     312         324 :     while ((pszLine = CPLReadLine2L(poOpenInfo->fpL, 1024, nullptr)) != nullptr)
     313             :     {
     314             :         char **papszTokens =
     315         321 :             CSLTokenizeStringComplex(pszLine, ":", TRUE, FALSE);
     316         321 :         if (CSLCount(papszTokens) != 2)
     317             :         {
     318           3 :             CSLDestroy(papszTokens);
     319           3 :             continue;
     320             :         }
     321         318 :         if (papszTokens[1][0] == ' ')
     322         318 :             memmove(papszTokens[1], papszTokens[1] + 1,
     323         318 :                     strlen(papszTokens[1] + 1) + 1);
     324             : 
     325         318 :         if (EQUAL(papszTokens[0], "Data file pathname"))
     326             :         {
     327           3 :             osDataFilename = papszTokens[1];
     328             :         }
     329         315 :         else if (EQUAL(papszTokens[0], "Description"))
     330             :         {
     331           3 :             osDescription = papszTokens[1];
     332             :         }
     333         312 :         else if (EQUAL(papszTokens[0], "Data units"))
     334             :         {
     335           3 :             osDataUnits = papszTokens[1];
     336             :         }
     337             : 
     338         309 :         else if (EQUAL(papszTokens[0], "Start year"))
     339           3 :             nStartYear = atoi(papszTokens[1]);
     340         306 :         else if (EQUAL(papszTokens[0], "Start month"))
     341           3 :             nStartMonth = atoi(papszTokens[1]);
     342         303 :         else if (EQUAL(papszTokens[0], "Start day"))
     343           3 :             nStartDay = atoi(papszTokens[1]);
     344         300 :         else if (EQUAL(papszTokens[0], "Start hour"))
     345           3 :             nStartHour = atoi(papszTokens[1]);
     346         297 :         else if (EQUAL(papszTokens[0], " Start minute"))
     347           0 :             nStartMinute = atoi(papszTokens[1]);
     348         297 :         else if (EQUAL(papszTokens[0], "Start second"))
     349           3 :             nStartSecond = atoi(papszTokens[1]);
     350             : 
     351         294 :         else if (EQUAL(papszTokens[0], "Stop year"))
     352           3 :             nStopYear = atoi(papszTokens[1]);
     353         291 :         else if (EQUAL(papszTokens[0], "Stop month"))
     354           3 :             nStopMonth = atoi(papszTokens[1]);
     355         288 :         else if (EQUAL(papszTokens[0], "Stop day"))
     356           3 :             nStopDay = atoi(papszTokens[1]);
     357         285 :         else if (EQUAL(papszTokens[0], "Stop hour"))
     358           3 :             nStopHour = atoi(papszTokens[1]);
     359         282 :         else if (EQUAL(papszTokens[0], "Stop minute"))
     360           3 :             nStopMinute = atoi(papszTokens[1]);
     361         279 :         else if (EQUAL(papszTokens[0], "Stop second"))
     362           3 :             nStopSecond = atoi(papszTokens[1]);
     363             : 
     364         276 :         else if (EQUAL(papszTokens[0], "Number of columns"))
     365             :         {
     366           3 :             nCols = atoi(papszTokens[1]);
     367             :         }
     368         273 :         else if (EQUAL(papszTokens[0], "Number of rows"))
     369             :         {
     370           3 :             nRows = atoi(papszTokens[1]);
     371             :         }
     372         270 :         else if (EQUAL(papszTokens[0], "Data type"))
     373             :         {
     374           3 :             bIsInteger = EQUAL(papszTokens[1], "integer");
     375             :         }
     376         267 :         else if (EQUAL(papszTokens[0], "Data bytes per pixel"))
     377             :         {
     378           3 :             bIs2Bytes = EQUAL(papszTokens[1], "2");
     379             :         }
     380         264 :         else if (EQUAL(papszTokens[0], "Projected"))
     381             :         {
     382           3 :             bNotProjected = EQUAL(papszTokens[1], "no");
     383             :         }
     384         261 :         else if (EQUAL(papszTokens[0], "Horizontal datum"))
     385             :         {
     386           3 :             bIsWGS84 = EQUAL(papszTokens[1], "WGS84");
     387             :         }
     388         258 :         else if (EQUAL(papszTokens[0], "No data value"))
     389             :         {
     390           3 :             bHasNoData = true;
     391           3 :             dfNoData = CPLAtofM(papszTokens[1]);
     392             :         }
     393         255 :         else if (EQUAL(papszTokens[0], "Minimum data value"))
     394             :         {
     395           3 :             bHasMin = true;
     396           3 :             dfMin = CPLAtofM(papszTokens[1]);
     397             :         }
     398         252 :         else if (EQUAL(papszTokens[0], "Maximum data value"))
     399             :         {
     400           3 :             bHasMax = true;
     401           3 :             dfMax = CPLAtofM(papszTokens[1]);
     402             :         }
     403         249 :         else if (EQUAL(papszTokens[0], "Minimum x-axis coordinate"))
     404             :         {
     405           3 :             bHasMinX = true;
     406           3 :             dfMinX = CPLAtofM(papszTokens[1]);
     407             :         }
     408         246 :         else if (EQUAL(papszTokens[0], "Minimum y-axis coordinate"))
     409             :         {
     410           3 :             bHasMinY = true;
     411           3 :             dfMinY = CPLAtofM(papszTokens[1]);
     412             :         }
     413         243 :         else if (EQUAL(papszTokens[0], "Maximum x-axis coordinate"))
     414             :         {
     415           3 :             bHasMaxX = true;
     416           3 :             dfMaxX = CPLAtofM(papszTokens[1]);
     417             :         }
     418         240 :         else if (EQUAL(papszTokens[0], "Maximum y-axis coordinate"))
     419             :         {
     420           3 :             bHasMaxY = true;
     421           3 :             dfMaxY = CPLAtofM(papszTokens[1]);
     422             :         }
     423             : 
     424         318 :         CSLDestroy(papszTokens);
     425             :     }
     426             : 
     427           3 :     CPL_IGNORE_RET_VAL(VSIFCloseL(poOpenInfo->fpL));
     428           3 :     poOpenInfo->fpL = nullptr;
     429             : 
     430             :     /* -------------------------------------------------------------------- */
     431             :     /*      Did we get the required keywords?  If not we return with        */
     432             :     /*      this never having been considered to be a match. This isn't     */
     433             :     /*      an error!                                                       */
     434             :     /* -------------------------------------------------------------------- */
     435           3 :     if (nRows == -1 || nCols == -1 || !bIsInteger || !bIs2Bytes)
     436           0 :         return nullptr;
     437             : 
     438           3 :     if (!bNotProjected || !bIsWGS84)
     439           0 :         return nullptr;
     440             : 
     441           3 :     if (osDataFilename.empty())
     442           0 :         return nullptr;
     443             : 
     444           3 :     if (!GDALCheckDatasetDimensions(nCols, nRows))
     445           0 :         return nullptr;
     446             : 
     447             :     /* -------------------------------------------------------------------- */
     448             :     /*      Open target binary file.                                        */
     449             :     /* -------------------------------------------------------------------- */
     450           3 :     const char *pszPath = CPLGetPath(poOpenInfo->pszFilename);
     451           3 :     osDataFilename = CPLFormFilename(pszPath, osDataFilename, nullptr);
     452             : 
     453           3 :     VSILFILE *fpRaw = VSIFOpenL(osDataFilename, "rb");
     454             : 
     455           3 :     if (fpRaw == nullptr)
     456           0 :         return nullptr;
     457             : 
     458             :     /* -------------------------------------------------------------------- */
     459             :     /*      Create a corresponding GDALDataset.                             */
     460             :     /* -------------------------------------------------------------------- */
     461           6 :     auto poDS = std::make_unique<SNODASDataset>();
     462             : 
     463           3 :     poDS->nRasterXSize = nCols;
     464           3 :     poDS->nRasterYSize = nRows;
     465           3 :     poDS->osDataFilename = std::move(osDataFilename);
     466           3 :     poDS->bHasNoData = bHasNoData;
     467           3 :     poDS->dfNoData = dfNoData;
     468           3 :     poDS->bHasMin = bHasMin;
     469           3 :     poDS->dfMin = dfMin;
     470           3 :     poDS->bHasMax = bHasMax;
     471           3 :     poDS->dfMax = dfMax;
     472           3 :     if (bHasMinX && bHasMinY && bHasMaxX && bHasMaxY)
     473             :     {
     474           3 :         poDS->bGotTransform = true;
     475           3 :         poDS->adfGeoTransform[0] = dfMinX;
     476           3 :         poDS->adfGeoTransform[1] = (dfMaxX - dfMinX) / nCols;
     477           3 :         poDS->adfGeoTransform[2] = 0.0;
     478           3 :         poDS->adfGeoTransform[3] = dfMaxY;
     479           3 :         poDS->adfGeoTransform[4] = 0.0;
     480           3 :         poDS->adfGeoTransform[5] = -(dfMaxY - dfMinY) / nRows;
     481             :     }
     482             : 
     483           3 :     if (!osDescription.empty())
     484           3 :         poDS->SetMetadataItem("Description", osDescription);
     485           3 :     if (!osDataUnits.empty())
     486           3 :         poDS->SetMetadataItem("Data_Units", osDataUnits);
     487           3 :     if (nStartYear != -1 && nStartMonth != -1 && nStartDay != -1 &&
     488           3 :         nStartHour != -1 && nStartMinute != -1 && nStartSecond != -1)
     489           0 :         poDS->SetMetadataItem(
     490             :             "Start_Date",
     491             :             CPLSPrintf("%04d/%02d/%02d %02d:%02d:%02d", nStartYear, nStartMonth,
     492           0 :                        nStartDay, nStartHour, nStartMinute, nStartSecond));
     493           3 :     if (nStopYear != -1 && nStopMonth != -1 && nStopDay != -1 &&
     494           3 :         nStopHour != -1 && nStopMinute != -1 && nStopSecond != -1)
     495           6 :         poDS->SetMetadataItem("Stop_Date",
     496             :                               CPLSPrintf("%04d/%02d/%02d %02d:%02d:%02d",
     497             :                                          nStopYear, nStopMonth, nStopDay,
     498           3 :                                          nStopHour, nStopMinute, nStopSecond));
     499             : 
     500             :     /* -------------------------------------------------------------------- */
     501             :     /*      Create band information objects.                                */
     502             :     /* -------------------------------------------------------------------- */
     503           6 :     auto poBand = std::make_unique<SNODASRasterBand>(fpRaw, nCols, nRows);
     504           3 :     if (!poBand->IsValid())
     505           0 :         return nullptr;
     506           3 :     poDS->SetBand(1, std::move(poBand));
     507             : 
     508             :     /* -------------------------------------------------------------------- */
     509             :     /*      Initialize any PAM information.                                 */
     510             :     /* -------------------------------------------------------------------- */
     511           3 :     poDS->SetDescription(poOpenInfo->pszFilename);
     512           3 :     poDS->TryLoadXML();
     513             : 
     514             :     /* -------------------------------------------------------------------- */
     515             :     /*      Check for overviews.                                            */
     516             :     /* -------------------------------------------------------------------- */
     517           3 :     poDS->oOvManager.Initialize(poDS.get(), poOpenInfo->pszFilename);
     518             : 
     519           3 :     return poDS.release();
     520             : }
     521             : 
     522             : /************************************************************************/
     523             : /*                       GDALRegister_SNODAS()                          */
     524             : /************************************************************************/
     525             : 
     526        1511 : void GDALRegister_SNODAS()
     527             : 
     528             : {
     529        1511 :     if (GDALGetDriverByName("SNODAS") != nullptr)
     530         295 :         return;
     531             : 
     532        1216 :     GDALDriver *poDriver = new GDALDriver();
     533             : 
     534        1216 :     poDriver->SetDescription("SNODAS");
     535        1216 :     poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
     536        1216 :     poDriver->SetMetadataItem(GDAL_DMD_LONGNAME,
     537        1216 :                               "Snow Data Assimilation System");
     538        1216 :     poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/snodas.html");
     539        1216 :     poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "hdr");
     540        1216 :     poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
     541             : 
     542        1216 :     poDriver->pfnOpen = SNODASDataset::Open;
     543        1216 :     poDriver->pfnIdentify = SNODASDataset::Identify;
     544             : 
     545        1216 :     GetGDALDriverManager()->RegisterDriver(poDriver);
     546             : }

Generated by: LCOV version 1.14