LCOV - code coverage report
Current view: top level - frmts/hdf5 - hdf5drivercore.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 246 256 96.1 %
Date: 2025-10-01 17:07:58 Functions: 30 31 96.8 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  GDAL
       4             :  * Purpose:  HDF5 driver
       5             :  * Author:   Even Rouault, <even.rouault at spatialys.com>
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2023, Even Rouault, <even.rouault at spatialys.com>
       9             :  *
      10             :  * SPDX-License-Identifier: MIT
      11             :  ****************************************************************************/
      12             : 
      13             : #include "hdf5drivercore.h"
      14             : 
      15             : #include "gdal_frmts.h"
      16             : #include "gdalplugindriverproxy.h"
      17             : #include "gdalsubdatasetinfo.h"
      18             : 
      19             : #include <algorithm>
      20             : #include <cctype>
      21             : 
      22             : /************************************************************************/
      23             : /*                          HDF5DatasetIdentify()                       */
      24             : /************************************************************************/
      25             : 
      26       58814 : int HDF5DatasetIdentify(GDALOpenInfo *poOpenInfo)
      27             : 
      28             : {
      29       58814 :     if ((poOpenInfo->nOpenFlags & GDAL_OF_MULTIDIM_RASTER) &&
      30         688 :         STARTS_WITH(poOpenInfo->pszFilename, "HDF5:"))
      31             :     {
      32          16 :         return TRUE;
      33             :     }
      34             : 
      35             :     // Is it an HDF5 file?
      36       58798 :     constexpr char achSignature[] = "\211HDF\r\n\032\n";
      37             : 
      38       58798 :     if (!poOpenInfo->pabyHeader)
      39       55080 :         return FALSE;
      40             : 
      41        7436 :     const CPLString osExt(poOpenInfo->osExtension);
      42             : 
      43         574 :     const auto IsRecognizedByNetCDFDriver = [&osExt, poOpenInfo]()
      44             :     {
      45         287 :         if ((EQUAL(osExt, "NC") || EQUAL(osExt, "CDF") || EQUAL(osExt, "NC4") ||
      46         292 :              EQUAL(osExt, "gmac")) &&
      47           5 :             GDALGetDriverByName("netCDF") != nullptr)
      48             :         {
      49           5 :             const char *const apszAllowedDriver[] = {"netCDF", nullptr};
      50           5 :             CPLErrorStateBackuper oErrorStateBackuper(CPLQuietErrorHandler);
      51          10 :             return std::unique_ptr<GDALDataset>(GDALDataset::Open(
      52           5 :                        poOpenInfo->pszFilename,
      53             :                        GDAL_OF_RASTER | GDAL_OF_MULTIDIM_RASTER |
      54             :                            GDAL_OF_VECTOR,
      55           5 :                        apszAllowedDriver, nullptr, nullptr)) != nullptr;
      56             :         }
      57         141 :         return false;
      58        3718 :     };
      59             : 
      60        3718 :     if (memcmp(poOpenInfo->pabyHeader, achSignature, 8) == 0 ||
      61        3569 :         (poOpenInfo->nHeaderBytes > 512 + 8 &&
      62        2269 :          memcmp(poOpenInfo->pabyHeader + 512, achSignature, 8) == 0))
      63             :     {
      64         149 :         if (poOpenInfo->IsSingleAllowedDriver("HDF5"))
      65             :         {
      66           4 :             return TRUE;
      67             :         }
      68             : 
      69             :         // The tests to avoid opening KEA and BAG drivers are not
      70             :         // necessary when drivers are built in the core lib, as they
      71             :         // are registered after HDF5, but in the case of plugins, we
      72             :         // cannot do assumptions about the registration order.
      73             : 
      74             :         // Avoid opening kea files if the kea driver is available.
      75         145 :         if (EQUAL(osExt, "KEA") && GDALGetDriverByName("KEA") != nullptr)
      76             :         {
      77           0 :             return FALSE;
      78             :         }
      79             : 
      80             :         // Avoid opening BAG files if the bag driver is available.
      81         145 :         if (EQUAL(osExt, "BAG") && GDALGetDriverByName("BAG") != nullptr)
      82             :         {
      83           1 :             return FALSE;
      84             :         }
      85             : 
      86             :         // Avoid opening NC files if the netCDF driver is available and
      87             :         // they are recognized by it.
      88         144 :         if (IsRecognizedByNetCDFDriver())
      89             :         {
      90           3 :             return FALSE;
      91             :         }
      92             : 
      93         141 :         return TRUE;
      94             :     }
      95             : 
      96        3569 :     if (memcmp(poOpenInfo->pabyHeader, "<HDF_UserBlock>", 15) == 0)
      97             :     {
      98           0 :         return TRUE;
      99             :     }
     100             : 
     101             :     // The HDF5 signature can be at offsets 512, 1024, 2048, etc.
     102        7084 :     if (poOpenInfo->fpL != nullptr &&
     103        3515 :         (EQUAL(osExt, "h5") || EQUAL(osExt, "hdf5") || EQUAL(osExt, "nc") ||
     104        3503 :          EQUAL(osExt, "cdf") || EQUAL(osExt, "nc4") ||
     105        3503 :          poOpenInfo->IsSingleAllowedDriver("HDF5")))
     106             :     {
     107          14 :         vsi_l_offset nOffset = 512;
     108          38 :         for (int i = 0; i < 64; i++)
     109             :         {
     110             :             GByte abyBuf[8];
     111          76 :             if (VSIFSeekL(poOpenInfo->fpL, nOffset, SEEK_SET) != 0 ||
     112          38 :                 VSIFReadL(abyBuf, 1, 8, poOpenInfo->fpL) != 8)
     113             :             {
     114           8 :                 break;
     115             :             }
     116          30 :             if (memcmp(abyBuf, achSignature, 8) == 0)
     117             :             {
     118           6 :                 if (poOpenInfo->IsSingleAllowedDriver("HDF5"))
     119             :                 {
     120           6 :                     return TRUE;
     121             :                 }
     122             :                 // Avoid opening NC files if the netCDF driver is available and
     123             :                 // they are recognized by it.
     124           2 :                 if (IsRecognizedByNetCDFDriver())
     125             :                 {
     126           0 :                     return FALSE;
     127             :                 }
     128             : 
     129           2 :                 return TRUE;
     130             :             }
     131          24 :             nOffset *= 2;
     132             :         }
     133             :     }
     134             : 
     135        3563 :     return FALSE;
     136             : }
     137             : 
     138             : /************************************************************************/
     139             : /*                     HDF5ImageDatasetIdentify()                       */
     140             : /************************************************************************/
     141             : 
     142       58019 : int HDF5ImageDatasetIdentify(GDALOpenInfo *poOpenInfo)
     143             : 
     144             : {
     145       58019 :     if (!STARTS_WITH_CI(poOpenInfo->pszFilename, "HDF5:"))
     146       57959 :         return FALSE;
     147             : 
     148          60 :     return TRUE;
     149             : }
     150             : 
     151             : /************************************************************************/
     152             : /*                    HDF5DriverGetSubdatasetInfo()                     */
     153             : /************************************************************************/
     154             : 
     155             : struct HDF5DriverSubdatasetInfo final : public GDALSubdatasetInfo
     156             : {
     157             :   public:
     158          26 :     explicit HDF5DriverSubdatasetInfo(const std::string &fileName)
     159          26 :         : GDALSubdatasetInfo(fileName)
     160             :     {
     161          26 :     }
     162             : 
     163             :     // GDALSubdatasetInfo interface
     164             :   private:
     165             :     void parseFileName() override;
     166             : };
     167             : 
     168          26 : void HDF5DriverSubdatasetInfo::parseFileName()
     169             : {
     170             : 
     171          26 :     if (!STARTS_WITH_CI(m_fileName.c_str(), "HDF5:"))
     172             :     {
     173           0 :         return;
     174             :     }
     175             : 
     176          52 :     CPLStringList aosParts{CSLTokenizeString2(m_fileName.c_str(), ":", 0)};
     177          26 :     const int iPartsCount{CSLCount(aosParts)};
     178             : 
     179          26 :     if (iPartsCount >= 3)
     180             :     {
     181             : 
     182          24 :         m_driverPrefixComponent = aosParts[0];
     183             : 
     184          48 :         std::string part1{aosParts[1]};
     185          24 :         if (!part1.empty() && part1[0] == '"')
     186             :         {
     187          20 :             part1 = part1.substr(1);
     188             :         }
     189             : 
     190          24 :         int subdatasetIndex{2};
     191             :         const bool hasDriveLetter{
     192          24 :             part1.length() == 1 &&
     193          30 :             std::isalpha(static_cast<unsigned char>(part1.at(0))) &&
     194           6 :             (strlen(aosParts[2]) > 1 &&
     195           5 :              (aosParts[2][0] == '\\' ||
     196           3 :               (aosParts[2][0] == '/' && aosParts[2][1] != '/')))};
     197             : 
     198          47 :         const bool hasProtocol{part1 == "/vsicurl/http" ||
     199          46 :                                part1 == "/vsicurl/https" ||
     200          70 :                                part1 == "/vsicurl_streaming/http" ||
     201          23 :                                part1 == "/vsicurl_streaming/https"};
     202             : 
     203          24 :         m_pathComponent = aosParts[1];
     204             : 
     205          24 :         if (hasDriveLetter || hasProtocol)
     206             :         {
     207           5 :             m_pathComponent.append(":");
     208           5 :             m_pathComponent.append(aosParts[2]);
     209           5 :             subdatasetIndex++;
     210             :         }
     211             : 
     212          24 :         if (iPartsCount > subdatasetIndex)
     213             :         {
     214          24 :             m_subdatasetComponent = aosParts[subdatasetIndex];
     215             : 
     216             :             // Append any remaining part
     217          24 :             for (int i = subdatasetIndex + 1; i < iPartsCount; ++i)
     218             :             {
     219           0 :                 m_subdatasetComponent.append(":");
     220           0 :                 m_subdatasetComponent.append(aosParts[i]);
     221             :             }
     222             :         }
     223             :     }
     224             : }
     225             : 
     226        2711 : static GDALSubdatasetInfo *HDF5DriverGetSubdatasetInfo(const char *pszFileName)
     227             : {
     228        2711 :     if (STARTS_WITH_CI(pszFileName, "HDF5:"))
     229             :     {
     230             :         std::unique_ptr<GDALSubdatasetInfo> info =
     231          26 :             std::make_unique<HDF5DriverSubdatasetInfo>(pszFileName);
     232          76 :         if (!info->GetSubdatasetComponent().empty() &&
     233          50 :             !info->GetPathComponent().empty())
     234             :         {
     235          24 :             return info.release();
     236             :         }
     237             :     }
     238        2687 :     return nullptr;
     239             : }
     240             : 
     241             : /************************************************************************/
     242             : /*                         IdentifySxx()                                */
     243             : /************************************************************************/
     244             : 
     245      176259 : static bool IdentifySxx(GDALOpenInfo *poOpenInfo, const char *pszDriverName,
     246             :                         const char *pszConfigOption,
     247             :                         const char *pszMainGroupName)
     248             : {
     249      176259 :     if (STARTS_WITH(poOpenInfo->pszFilename, pszDriverName) &&
     250          34 :         poOpenInfo->pszFilename[strlen(pszDriverName)] == ':')
     251          34 :         return TRUE;
     252             : 
     253             :     // Is it an HDF5 file?
     254             :     static const char achSignature[] = "\211HDF\r\n\032\n";
     255             : 
     256      176225 :     if (poOpenInfo->pabyHeader == nullptr ||
     257       10958 :         memcmp(poOpenInfo->pabyHeader, achSignature, 8) != 0)
     258      175955 :         return FALSE;
     259             : 
     260         270 :     if (poOpenInfo->IsSingleAllowedDriver(pszDriverName))
     261             :     {
     262           1 :         return TRUE;
     263             :     }
     264             : 
     265             :     // GDAL_Sxxx_IDENTIFY can be set to NO only for tests, to test that
     266             :     // HDF5Dataset::Open() can redirect to Sxxx if the below logic fails
     267         269 :     if (CPLTestBool(CPLGetConfigOption(pszConfigOption, "YES")))
     268             :     {
     269             :         // The below identification logic may be a bit fragile...
     270             :         // Works at least on:
     271             :         // - /vsis3/noaa-s102-pds/ed2.1.0/national_bathymetric_source/boston/dcf2/tiles/102US00_US4MA1GC.h5
     272             :         // - https://datahub.admiralty.co.uk/portal/sharing/rest/content/items/6fd07bde26124d48820b6dee60695389/data (S-102_Liverpool_Trial_Cells.zip)
     273         268 :         const int nLenMainGroup = static_cast<int>(strlen(pszMainGroupName));
     274         268 :         const int nLenGroupF = static_cast<int>(strlen("Group_F"));
     275         268 :         const int nLenProductSpecification =
     276             :             static_cast<int>(strlen("productSpecification"));
     277         268 :         bool bFoundMainGroup = false;
     278         268 :         bool bFoundGroupF = false;
     279         268 :         bool bFoundProductSpecification = false;
     280         268 :         for (int iTry = 0; iTry < 2; ++iTry)
     281             :         {
     282      262472 :             for (int i = 0; i <= poOpenInfo->nHeaderBytes - nLenGroupF; ++i)
     283             :             {
     284      262242 :                 if (i <= poOpenInfo->nHeaderBytes - nLenMainGroup &&
     285      260628 :                     poOpenInfo->pabyHeader[i] == pszMainGroupName[0] &&
     286         164 :                     memcmp(poOpenInfo->pabyHeader + i, pszMainGroupName,
     287             :                            nLenMainGroup) == 0)
     288             :                 {
     289          38 :                     bFoundMainGroup = true;
     290          38 :                     if (bFoundGroupF)
     291           0 :                         return true;
     292             :                 }
     293      262242 :                 if (poOpenInfo->pabyHeader[i] == 'G' &&
     294         225 :                     memcmp(poOpenInfo->pabyHeader + i, "Group_F", nLenGroupF) ==
     295             :                         0)
     296             :                 {
     297          46 :                     bFoundGroupF = true;
     298          46 :                     if (bFoundMainGroup)
     299          38 :                         return true;
     300             :                 }
     301      262204 :                 if (i <= poOpenInfo->nHeaderBytes - nLenProductSpecification &&
     302      259214 :                     poOpenInfo->pabyHeader[i] == 'p' &&
     303         221 :                     memcmp(poOpenInfo->pabyHeader + i, "productSpecification",
     304             :                            nLenProductSpecification) == 0)
     305             :                 {
     306             :                     // For 102DE00OS08J.H5
     307           0 :                     bFoundProductSpecification = true;
     308             :                 }
     309             :             }
     310         230 :             if (!(iTry == 0 && bFoundProductSpecification &&
     311           0 :                   poOpenInfo->nHeaderBytes == 1024 &&
     312           0 :                   poOpenInfo->TryToIngest(4096)))
     313             :             {
     314         230 :                 break;
     315             :             }
     316             :         }
     317             :     }
     318             : 
     319         231 :     return false;
     320             : }
     321             : 
     322             : /************************************************************************/
     323             : /*                        S102DatasetIdentify()                         */
     324             : /************************************************************************/
     325             : 
     326       58789 : int S102DatasetIdentify(GDALOpenInfo *poOpenInfo)
     327             : 
     328             : {
     329       58789 :     return IdentifySxx(poOpenInfo, "S102", "GDAL_S102_IDENTIFY",
     330       58788 :                        "BathymetryCoverage");
     331             : }
     332             : 
     333             : /************************************************************************/
     334             : /*                        S104DatasetIdentify()                         */
     335             : /************************************************************************/
     336             : 
     337       58740 : int S104DatasetIdentify(GDALOpenInfo *poOpenInfo)
     338             : 
     339             : {
     340       58740 :     return IdentifySxx(poOpenInfo, "S104", "GDAL_S104_IDENTIFY", "WaterLevel");
     341             : }
     342             : 
     343             : /************************************************************************/
     344             : /*                        S111DatasetIdentify()                         */
     345             : /************************************************************************/
     346             : 
     347       58735 : int S111DatasetIdentify(GDALOpenInfo *poOpenInfo)
     348             : 
     349             : {
     350       58735 :     return IdentifySxx(poOpenInfo, "S111", "GDAL_S111_IDENTIFY",
     351       58735 :                        "SurfaceCurrent");
     352             : }
     353             : 
     354             : /************************************************************************/
     355             : /*                        BAGDatasetIdentify()                          */
     356             : /************************************************************************/
     357             : 
     358       69472 : int BAGDatasetIdentify(GDALOpenInfo *poOpenInfo)
     359             : 
     360             : {
     361       69472 :     if (STARTS_WITH(poOpenInfo->pszFilename, "BAG:"))
     362          30 :         return TRUE;
     363             : 
     364             :     // Is it an HDF5 file?
     365             :     static const char achSignature[] = "\211HDF\r\n\032\n";
     366             : 
     367       69442 :     if (poOpenInfo->pabyHeader == nullptr ||
     368       11845 :         memcmp(poOpenInfo->pabyHeader, achSignature, 8) != 0)
     369       69200 :         return FALSE;
     370             : 
     371             :     // Does it have the extension .bag?
     372         242 :     if (!poOpenInfo->IsExtensionEqualToCI("bag"))
     373             :     {
     374         106 :         if (poOpenInfo->IsSingleAllowedDriver("BAG"))
     375             :         {
     376           1 :             return TRUE;
     377             :         }
     378         105 :         return FALSE;
     379             :     }
     380             : 
     381         136 :     return TRUE;
     382             : }
     383             : 
     384             : /************************************************************************/
     385             : /*                   HDF5DriverSetCommonMetadata()                      */
     386             : /************************************************************************/
     387             : 
     388        2105 : void HDF5DriverSetCommonMetadata(GDALDriver *poDriver)
     389             : {
     390        2105 :     poDriver->SetDescription(HDF5_DRIVER_NAME);
     391        2105 :     poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
     392        2105 :     poDriver->SetMetadataItem(GDAL_DMD_LONGNAME,
     393        2105 :                               "Hierarchical Data Format Release 5");
     394        2105 :     poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/hdf5.html");
     395        2105 :     poDriver->SetMetadataItem(GDAL_DMD_EXTENSIONS, "h5 hdf5");
     396        2105 :     poDriver->SetMetadataItem(GDAL_DMD_SUBDATASETS, "YES");
     397        2105 :     poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
     398             : 
     399        2105 :     poDriver->SetMetadataItem(GDAL_DCAP_MULTIDIM_RASTER, "YES");
     400             : 
     401        2105 :     poDriver->pfnIdentify = HDF5DatasetIdentify;
     402        2105 :     poDriver->pfnGetSubdatasetInfoFunc = HDF5DriverGetSubdatasetInfo;
     403        2105 :     poDriver->SetMetadataItem(GDAL_DCAP_OPEN, "YES");
     404        2105 : }
     405             : 
     406             : /************************************************************************/
     407             : /*                 HDF5ImageDriverSetCommonMetadata()                   */
     408             : /************************************************************************/
     409             : 
     410        2105 : void HDF5ImageDriverSetCommonMetadata(GDALDriver *poDriver)
     411             : {
     412        2105 :     poDriver->SetDescription(HDF5_IMAGE_DRIVER_NAME);
     413        2105 :     poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
     414        2105 :     poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "HDF5 Dataset");
     415        2105 :     poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/hdf5.html");
     416        2105 :     poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
     417             : 
     418        2105 :     poDriver->pfnIdentify = HDF5ImageDatasetIdentify;
     419        2105 :     poDriver->SetMetadataItem(GDAL_DCAP_OPEN, "YES");
     420        2105 : }
     421             : 
     422             : /************************************************************************/
     423             : /*                     BAGDriverSetCommonMetadata()                     */
     424             : /************************************************************************/
     425             : 
     426        2105 : void BAGDriverSetCommonMetadata(GDALDriver *poDriver)
     427             : {
     428        2105 :     poDriver->SetDescription(BAG_DRIVER_NAME);
     429        2105 :     poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
     430        2105 :     poDriver->SetMetadataItem(GDAL_DCAP_VECTOR, "YES");
     431        2105 :     poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "Bathymetry Attributed Grid");
     432        2105 :     poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/bag.html");
     433        2105 :     poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
     434        2105 :     poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "bag");
     435             : 
     436        2105 :     poDriver->SetMetadataItem(GDAL_DMD_CREATIONDATATYPES, "Float32");
     437             : 
     438        2105 :     poDriver->SetMetadataItem(
     439             :         GDAL_DMD_OPENOPTIONLIST,
     440             :         "<OpenOptionList>"
     441             :         "   <Option name='MODE' type='string-select' default='AUTO'>"
     442             :         "       <Value>AUTO</Value>"
     443             :         "       <Value>LOW_RES_GRID</Value>"
     444             :         "       <Value>LIST_SUPERGRIDS</Value>"
     445             :         "       <Value>RESAMPLED_GRID</Value>"
     446             :         "       <Value>INTERPOLATED</Value>"
     447             :         "   </Option>"
     448             :         "   <Option name='SUPERGRIDS_INDICES' type='string' description="
     449             :         "'Tuple(s) (y1,x1),(y2,x2),...  of supergrids, by indices, to expose "
     450             :         "as subdatasets'/>"
     451             :         "   <Option name='MINX' type='float' description='Minimum X value of "
     452             :         "area of interest'/>"
     453             :         "   <Option name='MINY' type='float' description='Minimum Y value of "
     454             :         "area of interest'/>"
     455             :         "   <Option name='MAXX' type='float' description='Maximum X value of "
     456             :         "area of interest'/>"
     457             :         "   <Option name='MAXY' type='float' description='Maximum Y value of "
     458             :         "area of interest'/>"
     459             :         "   <Option name='RESX' type='float' description="
     460             :         "'Horizontal resolution. Only used for "
     461             :         "MODE=RESAMPLED_GRID/INTERPOLATED'/>"
     462             :         "   <Option name='RESY' type='float' description="
     463             :         "'Vertical resolution (positive value). Only used for "
     464             :         "MODE=RESAMPLED_GRID/INTERPOLATED'/>"
     465             :         "   <Option name='RES_STRATEGY' type='string-select' description="
     466             :         "'Which strategy to apply to select the resampled grid resolution. "
     467             :         "Only used for MODE=RESAMPLED_GRID/INTERPOLATED' default='AUTO'>"
     468             :         "       <Value>AUTO</Value>"
     469             :         "       <Value>MIN</Value>"
     470             :         "       <Value>MAX</Value>"
     471             :         "       <Value>MEAN</Value>"
     472             :         "   </Option>"
     473             :         "   <Option name='RES_FILTER_MIN' type='float' description="
     474             :         "'Minimum resolution of supergrids to take into account (excluded "
     475             :         "bound). "
     476             :         "Only used for MODE=RESAMPLED_GRID, INTERPOLATED or LIST_SUPERGRIDS' "
     477             :         "default='0'/>"
     478             :         "   <Option name='RES_FILTER_MAX' type='float' description="
     479             :         "'Maximum resolution of supergrids to take into account (included "
     480             :         "bound). "
     481             :         "Only used for MODE=RESAMPLED_GRID, INTERPOLATED or LIST_SUPERGRIDS' "
     482             :         "default='inf'/>"
     483             :         "   <Option name='VALUE_POPULATION' type='string-select' description="
     484             :         "'Which value population strategy to apply to compute the resampled "
     485             :         "cell "
     486             :         "values. Only used for MODE=RESAMPLED_GRID' default='MAX'>"
     487             :         "       <Value>MIN</Value>"
     488             :         "       <Value>MAX</Value>"
     489             :         "       <Value>MEAN</Value>"
     490             :         "       <Value>COUNT</Value>"
     491             :         "   </Option>"
     492             :         "   <Option name='SUPERGRIDS_MASK' type='boolean' description="
     493             :         "'Whether the dataset should consist of a mask band indicating if a "
     494             :         "supergrid node matches each target pixel. Only used for "
     495             :         "MODE=RESAMPLED_GRID' default='NO'/>"
     496             :         "   <Option name='NODATA_VALUE' type='float' default='1000000'/>"
     497             :         "   <Option name='REPORT_VERTCRS' type='boolean' default='YES'/>"
     498        2105 :         "</OpenOptionList>");
     499             : 
     500        2105 :     poDriver->SetMetadataItem(
     501             :         GDAL_DMD_CREATIONOPTIONLIST,
     502             :         "<CreationOptionList>"
     503             :         "  <Option name='VAR_*' type='string' description="
     504             :         "'Value to substitute to a variable in the template'/>"
     505             :         "  <Option name='TEMPLATE' type='string' description="
     506             :         "'.xml template to use'/>"
     507             :         "  <Option name='BAG_VERSION' type='string' description="
     508             :         "'Version to write in the Bag Version attribute' default='1.6.2'/>"
     509             :         "  <Option name='COMPRESS' type='string-select' default='DEFLATE'>"
     510             :         "    <Value>NONE</Value>"
     511             :         "    <Value>DEFLATE</Value>"
     512             :         "  </Option>"
     513             :         "  <Option name='ZLEVEL' type='int' "
     514             :         "description='DEFLATE compression level 1-9' default='6' />"
     515             :         "  <Option name='BLOCK_SIZE' type='int' description='Chunk size' />"
     516        2105 :         "</CreationOptionList>");
     517             : 
     518        2105 :     poDriver->SetMetadataItem(GDAL_DCAP_MULTIDIM_RASTER, "YES");
     519             : 
     520        2105 :     poDriver->pfnIdentify = BAGDatasetIdentify;
     521        2105 :     poDriver->SetMetadataItem(GDAL_DCAP_OPEN, "YES");
     522        2105 :     poDriver->SetMetadataItem(GDAL_DCAP_CREATE, "YES");
     523        2105 :     poDriver->SetMetadataItem(GDAL_DCAP_CREATECOPY, "YES");
     524        2105 : }
     525             : 
     526             : /************************************************************************/
     527             : /*                    S102DriverSetCommonMetadata()                     */
     528             : /************************************************************************/
     529             : 
     530        2105 : void S102DriverSetCommonMetadata(GDALDriver *poDriver)
     531             : {
     532        2105 :     poDriver->SetDescription(S102_DRIVER_NAME);
     533        2105 :     poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
     534        2105 :     poDriver->SetMetadataItem(GDAL_DCAP_MULTIDIM_RASTER, "YES");
     535        2105 :     poDriver->SetMetadataItem(GDAL_DMD_LONGNAME,
     536        2105 :                               "S-102 Bathymetric Surface Product");
     537        2105 :     poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/s102.html");
     538        2105 :     poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
     539        2105 :     poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "h5");
     540        2105 :     poDriver->SetMetadataItem(GDAL_DMD_SUBDATASETS, "YES");
     541             : 
     542        2105 :     poDriver->SetMetadataItem(
     543             :         GDAL_DMD_OPENOPTIONLIST,
     544             :         "<OpenOptionList>"
     545             :         "   <Option name='DEPTH_OR_ELEVATION' type='string-select' "
     546             :         "default='DEPTH'>"
     547             :         "       <Value>DEPTH</Value>"
     548             :         "       <Value>ELEVATION</Value>"
     549             :         "   </Option>"
     550             :         "   <Option name='NORTH_UP' type='boolean' default='YES' "
     551             :         "description='Whether the top line of the dataset should be the "
     552             :         "northern-most one'/>"
     553        2105 :         "</OpenOptionList>");
     554        2105 :     poDriver->pfnIdentify = S102DatasetIdentify;
     555        2105 :     poDriver->SetMetadataItem(GDAL_DCAP_OPEN, "YES");
     556        2105 : }
     557             : 
     558             : /************************************************************************/
     559             : /*                    S104DriverSetCommonMetadata()                     */
     560             : /************************************************************************/
     561             : 
     562        2105 : void S104DriverSetCommonMetadata(GDALDriver *poDriver)
     563             : {
     564        2105 :     poDriver->SetDescription(S104_DRIVER_NAME);
     565        2105 :     poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
     566        2105 :     poDriver->SetMetadataItem(GDAL_DCAP_MULTIDIM_RASTER, "YES");
     567        2105 :     poDriver->SetMetadataItem(
     568             :         GDAL_DMD_LONGNAME,
     569        2105 :         "S-104 Water Level Information for Surface Navigation Product");
     570        2105 :     poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/s104.html");
     571        2105 :     poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
     572        2105 :     poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "h5");
     573             : 
     574        2105 :     poDriver->SetMetadataItem(
     575             :         GDAL_DMD_OPENOPTIONLIST,
     576             :         "<OpenOptionList>"
     577             :         "   <Option name='NORTH_UP' type='boolean' default='YES' "
     578             :         "description='Whether the top line of the dataset should be the "
     579             :         "northern-most one'/>"
     580        2105 :         "</OpenOptionList>");
     581        2105 :     poDriver->pfnIdentify = S104DatasetIdentify;
     582        2105 :     poDriver->SetMetadataItem(GDAL_DCAP_OPEN, "YES");
     583        2105 : }
     584             : 
     585             : /************************************************************************/
     586             : /*                    S111DriverSetCommonMetadata()                     */
     587             : /************************************************************************/
     588             : 
     589        2105 : void S111DriverSetCommonMetadata(GDALDriver *poDriver)
     590             : {
     591        2105 :     poDriver->SetDescription(S111_DRIVER_NAME);
     592        2105 :     poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
     593        2105 :     poDriver->SetMetadataItem(GDAL_DCAP_MULTIDIM_RASTER, "YES");
     594        2105 :     poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "Surface Currents Product");
     595        2105 :     poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/s111.html");
     596        2105 :     poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
     597        2105 :     poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "h5");
     598             : 
     599        2105 :     poDriver->SetMetadataItem(
     600             :         GDAL_DMD_OPENOPTIONLIST,
     601             :         "<OpenOptionList>"
     602             :         "   <Option name='NORTH_UP' type='boolean' default='YES' "
     603             :         "description='Whether the top line of the dataset should be the "
     604             :         "northern-most one'/>"
     605        2105 :         "</OpenOptionList>");
     606        2105 :     poDriver->pfnIdentify = S111DatasetIdentify;
     607        2105 :     poDriver->SetMetadataItem(GDAL_DCAP_OPEN, "YES");
     608        2105 : }
     609             : 
     610             : /************************************************************************/
     611             : /*                    DeclareDeferredHDF5Plugin()                       */
     612             : /************************************************************************/
     613             : 
     614             : #ifdef PLUGIN_FILENAME
     615        2033 : void DeclareDeferredHDF5Plugin()
     616             : {
     617        2033 :     if (GDALGetDriverByName(HDF5_DRIVER_NAME) != nullptr)
     618             :     {
     619         283 :         return;
     620             :     }
     621             :     {
     622        1750 :         auto poDriver = new GDALPluginDriverProxy(PLUGIN_FILENAME);
     623             : #ifdef PLUGIN_INSTALLATION_MESSAGE
     624             :         poDriver->SetMetadataItem(GDAL_DMD_PLUGIN_INSTALLATION_MESSAGE,
     625             :                                   PLUGIN_INSTALLATION_MESSAGE);
     626             : #endif
     627        1750 :         HDF5DriverSetCommonMetadata(poDriver);
     628        1750 :         GetGDALDriverManager()->DeclareDeferredPluginDriver(poDriver);
     629             :     }
     630             :     {
     631        1750 :         auto poDriver = new GDALPluginDriverProxy(PLUGIN_FILENAME);
     632             : #ifdef PLUGIN_INSTALLATION_MESSAGE
     633             :         poDriver->SetMetadataItem(GDAL_DMD_PLUGIN_INSTALLATION_MESSAGE,
     634             :                                   PLUGIN_INSTALLATION_MESSAGE);
     635             : #endif
     636        1750 :         HDF5ImageDriverSetCommonMetadata(poDriver);
     637        1750 :         GetGDALDriverManager()->DeclareDeferredPluginDriver(poDriver);
     638             :     }
     639             :     {
     640        1750 :         auto poDriver = new GDALPluginDriverProxy(PLUGIN_FILENAME);
     641             : #ifdef PLUGIN_INSTALLATION_MESSAGE
     642             :         poDriver->SetMetadataItem(GDAL_DMD_PLUGIN_INSTALLATION_MESSAGE,
     643             :                                   PLUGIN_INSTALLATION_MESSAGE);
     644             : #endif
     645        1750 :         BAGDriverSetCommonMetadata(poDriver);
     646        1750 :         GetGDALDriverManager()->DeclareDeferredPluginDriver(poDriver);
     647             :     }
     648             :     {
     649        1750 :         auto poDriver = new GDALPluginDriverProxy(PLUGIN_FILENAME);
     650             : #ifdef PLUGIN_INSTALLATION_MESSAGE
     651             :         poDriver->SetMetadataItem(GDAL_DMD_PLUGIN_INSTALLATION_MESSAGE,
     652             :                                   PLUGIN_INSTALLATION_MESSAGE);
     653             : #endif
     654        1750 :         S102DriverSetCommonMetadata(poDriver);
     655        1750 :         GetGDALDriverManager()->DeclareDeferredPluginDriver(poDriver);
     656             :     }
     657             :     {
     658        1750 :         auto poDriver = new GDALPluginDriverProxy(PLUGIN_FILENAME);
     659             : #ifdef PLUGIN_INSTALLATION_MESSAGE
     660             :         poDriver->SetMetadataItem(GDAL_DMD_PLUGIN_INSTALLATION_MESSAGE,
     661             :                                   PLUGIN_INSTALLATION_MESSAGE);
     662             : #endif
     663        1750 :         S104DriverSetCommonMetadata(poDriver);
     664        1750 :         GetGDALDriverManager()->DeclareDeferredPluginDriver(poDriver);
     665             :     }
     666             :     {
     667        1750 :         auto poDriver = new GDALPluginDriverProxy(PLUGIN_FILENAME);
     668             : #ifdef PLUGIN_INSTALLATION_MESSAGE
     669             :         poDriver->SetMetadataItem(GDAL_DMD_PLUGIN_INSTALLATION_MESSAGE,
     670             :                                   PLUGIN_INSTALLATION_MESSAGE);
     671             : #endif
     672        1750 :         S111DriverSetCommonMetadata(poDriver);
     673        1750 :         GetGDALDriverManager()->DeclareDeferredPluginDriver(poDriver);
     674             :     }
     675             : }
     676             : #endif

Generated by: LCOV version 1.14