LCOV - code coverage report
Current view: top level - frmts/hdf5 - hdf5drivercore.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 264 271 97.4 %
Date: 2026-01-18 23:37:47 Functions: 31 31 100.0 %

          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       61639 : int HDF5DatasetIdentify(GDALOpenInfo *poOpenInfo)
      27             : 
      28             : {
      29       61639 :     if ((poOpenInfo->nOpenFlags & GDAL_OF_MULTIDIM_RASTER) &&
      30         736 :         STARTS_WITH(poOpenInfo->pszFilename, "HDF5:"))
      31             :     {
      32          16 :         return TRUE;
      33             :     }
      34             : 
      35             :     // Is it an HDF5 file?
      36       61623 :     constexpr char achSignature[] = "\211HDF\r\n\032\n";
      37             : 
      38       61623 :     if (!poOpenInfo->pabyHeader)
      39       56767 :         return FALSE;
      40             : 
      41        9712 :     const CPLString osExt(poOpenInfo->osExtension);
      42             : 
      43         802 :     const auto IsRecognizedByNetCDFDriver = [&osExt, poOpenInfo]()
      44             :     {
      45         401 :         if ((EQUAL(osExt, "NC") || EQUAL(osExt, "CDF") || EQUAL(osExt, "NC4") ||
      46         406 :              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         198 :         return false;
      58        4856 :     };
      59             : 
      60        4856 :     if (memcmp(poOpenInfo->pabyHeader, achSignature, 8) == 0 ||
      61        4650 :         (poOpenInfo->nHeaderBytes > 512 + 8 &&
      62        3333 :          memcmp(poOpenInfo->pabyHeader + 512, achSignature, 8) == 0))
      63             :     {
      64         206 :         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         202 :         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         202 :         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         201 :         if (IsRecognizedByNetCDFDriver())
      89             :         {
      90           3 :             return FALSE;
      91             :         }
      92             : 
      93         198 :         return TRUE;
      94             :     }
      95             : 
      96        4650 :     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        9246 :     if (poOpenInfo->fpL != nullptr &&
     103        4596 :         (EQUAL(osExt, "h5") || EQUAL(osExt, "hdf5") || EQUAL(osExt, "nc") ||
     104        4582 :          EQUAL(osExt, "cdf") || EQUAL(osExt, "nc4") ||
     105        4582 :          poOpenInfo->IsSingleAllowedDriver("HDF5")))
     106             :     {
     107          16 :         vsi_l_offset nOffset = 512;
     108          40 :         for (int i = 0; i < 64; i++)
     109             :         {
     110             :             GByte abyBuf[8];
     111          80 :             if (VSIFSeekL(poOpenInfo->fpL, nOffset, SEEK_SET) != 0 ||
     112          40 :                 VSIFReadL(abyBuf, 1, 8, poOpenInfo->fpL) != 8)
     113             :             {
     114          10 :                 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        4644 :     return FALSE;
     136             : }
     137             : 
     138             : /************************************************************************/
     139             : /*                     HDF5ImageDatasetIdentify()                       */
     140             : /************************************************************************/
     141             : 
     142       60776 : int HDF5ImageDatasetIdentify(GDALOpenInfo *poOpenInfo)
     143             : 
     144             : {
     145       60776 :     if (!STARTS_WITH_CI(poOpenInfo->pszFilename, "HDF5:"))
     146       60715 :         return FALSE;
     147             : 
     148          61 :     return TRUE;
     149             : }
     150             : 
     151             : /************************************************************************/
     152             : /*                    HDF5DriverGetSubdatasetInfo()                     */
     153             : /************************************************************************/
     154             : 
     155             : struct HDF5DriverSubdatasetInfo final : public GDALSubdatasetInfo
     156             : {
     157             :   public:
     158          40 :     explicit HDF5DriverSubdatasetInfo(const std::string &fileName)
     159          40 :         : GDALSubdatasetInfo(fileName)
     160             :     {
     161          40 :     }
     162             : 
     163             :     // GDALSubdatasetInfo interface
     164             :   private:
     165             :     void parseFileName() override;
     166             : };
     167             : 
     168          40 : void HDF5DriverSubdatasetInfo::parseFileName()
     169             : {
     170             : 
     171          40 :     if (!STARTS_WITH_CI(m_fileName.c_str(), "HDF5:"))
     172             :     {
     173           0 :         return;
     174             :     }
     175             : 
     176          80 :     CPLStringList aosParts{CSLTokenizeString2(m_fileName.c_str(), ":", 0)};
     177          40 :     const int iPartsCount{CSLCount(aosParts)};
     178             : 
     179          40 :     if (iPartsCount >= 3)
     180             :     {
     181             : 
     182          38 :         m_driverPrefixComponent = aosParts[0];
     183             : 
     184          76 :         std::string part1{aosParts[1]};
     185          38 :         if (!part1.empty() && part1[0] == '"')
     186             :         {
     187          34 :             part1 = part1.substr(1);
     188             :         }
     189             : 
     190          38 :         int subdatasetIndex{2};
     191             :         const bool hasDriveLetter{
     192          38 :             part1.length() == 1 &&
     193          44 :             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          75 :         const bool hasProtocol{part1 == "/vsicurl/http" ||
     199          74 :                                part1 == "/vsicurl/https" ||
     200         112 :                                part1 == "/vsicurl_streaming/http" ||
     201          37 :                                part1 == "/vsicurl_streaming/https"};
     202             : 
     203          38 :         m_pathComponent = aosParts[1];
     204             : 
     205          38 :         if (hasDriveLetter || hasProtocol)
     206             :         {
     207           5 :             m_pathComponent.append(":");
     208           5 :             m_pathComponent.append(aosParts[2]);
     209           5 :             subdatasetIndex++;
     210             :         }
     211             : 
     212          38 :         if (iPartsCount > subdatasetIndex)
     213             :         {
     214          38 :             m_subdatasetComponent = aosParts[subdatasetIndex];
     215             : 
     216             :             // Append any remaining part
     217          38 :             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        2736 : static GDALSubdatasetInfo *HDF5DriverGetSubdatasetInfo(const char *pszFileName)
     227             : {
     228        2736 :     if (STARTS_WITH_CI(pszFileName, "HDF5:"))
     229             :     {
     230             :         std::unique_ptr<GDALSubdatasetInfo> info =
     231          40 :             std::make_unique<HDF5DriverSubdatasetInfo>(pszFileName);
     232         118 :         if (!info->GetSubdatasetComponent().empty() &&
     233          78 :             !info->GetPathComponent().empty())
     234             :         {
     235          38 :             return info.release();
     236             :         }
     237             :     }
     238        2698 :     return nullptr;
     239             : }
     240             : 
     241             : /************************************************************************/
     242             : /*                         IdentifySxx()                                */
     243             : /************************************************************************/
     244             : 
     245      185288 : static bool IdentifySxx(GDALOpenInfo *poOpenInfo, const char *pszDriverName,
     246             :                         const char *pszConfigOption,
     247             :                         const char *pszMainGroupName)
     248             : {
     249      185288 :     if (STARTS_WITH(poOpenInfo->pszFilename, pszDriverName) &&
     250         188 :         poOpenInfo->pszFilename[strlen(pszDriverName)] == ':')
     251         188 :         return TRUE;
     252             : 
     253             :     // Is it an HDF5 file?
     254             :     static const char achSignature[] = "\211HDF\r\n\032\n";
     255             : 
     256      185100 :     if (poOpenInfo->pabyHeader == nullptr ||
     257       14492 :         memcmp(poOpenInfo->pabyHeader, achSignature, 8) != 0)
     258      184541 :         return FALSE;
     259             : 
     260         559 :     if (poOpenInfo->IsSingleAllowedDriver(pszDriverName))
     261             :     {
     262          35 :         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         524 :     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         523 :         const int nLenMainGroup = static_cast<int>(strlen(pszMainGroupName));
     274         523 :         const int nLenGroupF = static_cast<int>(strlen("Group_F"));
     275         523 :         const int nLenProductSpecification =
     276             :             static_cast<int>(strlen("productSpecification"));
     277         523 :         bool bFoundMainGroup = false;
     278         523 :         bool bFoundGroupF = false;
     279         523 :         bool bFoundProductSpecification = false;
     280         563 :         for (int iTry = 0; iTry < 2; ++iTry)
     281             :         {
     282      870267 :             for (int i = 0; i <= poOpenInfo->nHeaderBytes - nLenGroupF; ++i)
     283             :             {
     284      869863 :                 if (i <= poOpenInfo->nHeaderBytes - nLenMainGroup &&
     285      866803 :                     poOpenInfo->pabyHeader[i] == pszMainGroupName[0] &&
     286         714 :                     memcmp(poOpenInfo->pabyHeader + i, pszMainGroupName,
     287             :                            nLenMainGroup) == 0)
     288             :                 {
     289         170 :                     bFoundMainGroup = true;
     290         170 :                     if (bFoundGroupF)
     291           0 :                         return true;
     292             :                 }
     293      869863 :                 if (poOpenInfo->pabyHeader[i] == 'G' &&
     294         548 :                     memcmp(poOpenInfo->pabyHeader + i, "Group_F", nLenGroupF) ==
     295             :                         0)
     296             :                 {
     297         196 :                     bFoundGroupF = true;
     298         196 :                     if (bFoundMainGroup)
     299         159 :                         return true;
     300             :                 }
     301      869704 :                 if (i <= poOpenInfo->nHeaderBytes - nLenProductSpecification &&
     302      864452 :                     poOpenInfo->pabyHeader[i] == 'p' &&
     303         857 :                     memcmp(poOpenInfo->pabyHeader + i, "productSpecification",
     304             :                            nLenProductSpecification) == 0)
     305             :                 {
     306             :                     // For 102DE00OS08J.H5
     307         151 :                     bFoundProductSpecification = true;
     308             :                 }
     309             :             }
     310         515 :             if (!(iTry == 0 && bFoundProductSpecification &&
     311         111 :                   poOpenInfo->nHeaderBytes == 1024 &&
     312          40 :                   poOpenInfo->TryToIngest(4096)))
     313             :             {
     314         364 :                 break;
     315             :             }
     316             :         }
     317             :     }
     318             : 
     319         365 :     return false;
     320             : }
     321             : 
     322             : /************************************************************************/
     323             : /*                        S102DatasetIdentify()                         */
     324             : /************************************************************************/
     325             : 
     326       61774 : int S102DatasetIdentify(GDALOpenInfo *poOpenInfo)
     327             : 
     328             : {
     329       61774 :     return IdentifySxx(poOpenInfo, "S102", "GDAL_S102_IDENTIFY",
     330       61774 :                        "BathymetryCoverage");
     331             : }
     332             : 
     333             : /************************************************************************/
     334             : /*                        S104DatasetIdentify()                         */
     335             : /************************************************************************/
     336             : 
     337       61795 : int S104DatasetIdentify(GDALOpenInfo *poOpenInfo)
     338             : 
     339             : {
     340       61795 :     return IdentifySxx(poOpenInfo, "S104", "GDAL_S104_IDENTIFY", "WaterLevel");
     341             : }
     342             : 
     343             : /************************************************************************/
     344             : /*                        S111DatasetIdentify()                         */
     345             : /************************************************************************/
     346             : 
     347       61719 : int S111DatasetIdentify(GDALOpenInfo *poOpenInfo)
     348             : 
     349             : {
     350       61719 :     return IdentifySxx(poOpenInfo, "S111", "GDAL_S111_IDENTIFY",
     351       61719 :                        "SurfaceCurrent");
     352             : }
     353             : 
     354             : /************************************************************************/
     355             : /*                        BAGDatasetIdentify()                          */
     356             : /************************************************************************/
     357             : 
     358       72675 : int BAGDatasetIdentify(GDALOpenInfo *poOpenInfo)
     359             : 
     360             : {
     361       72675 :     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       72645 :     if (poOpenInfo->pabyHeader == nullptr ||
     368       13189 :         memcmp(poOpenInfo->pabyHeader, achSignature, 8) != 0)
     369       72345 :         return FALSE;
     370             : 
     371             :     // Does it have the extension .bag?
     372         300 :     if (!poOpenInfo->IsExtensionEqualToCI("bag"))
     373             :     {
     374         164 :         if (poOpenInfo->IsSingleAllowedDriver("BAG"))
     375             :         {
     376           1 :             return TRUE;
     377             :         }
     378         163 :         return FALSE;
     379             :     }
     380             : 
     381         136 :     return TRUE;
     382             : }
     383             : 
     384             : /************************************************************************/
     385             : /*                   HDF5DriverSetCommonMetadata()                      */
     386             : /************************************************************************/
     387             : 
     388        1789 : void HDF5DriverSetCommonMetadata(GDALDriver *poDriver)
     389             : {
     390        1789 :     poDriver->SetDescription(HDF5_DRIVER_NAME);
     391        1789 :     poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
     392        1789 :     poDriver->SetMetadataItem(GDAL_DMD_LONGNAME,
     393        1789 :                               "Hierarchical Data Format Release 5");
     394        1789 :     poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/hdf5.html");
     395        1789 :     poDriver->SetMetadataItem(GDAL_DMD_EXTENSIONS, "h5 hdf5");
     396        1789 :     poDriver->SetMetadataItem(GDAL_DMD_SUBDATASETS, "YES");
     397        1789 :     poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
     398             : 
     399        1789 :     poDriver->SetMetadataItem(GDAL_DCAP_MULTIDIM_RASTER, "YES");
     400             : 
     401        1789 :     poDriver->pfnIdentify = HDF5DatasetIdentify;
     402        1789 :     poDriver->pfnGetSubdatasetInfoFunc = HDF5DriverGetSubdatasetInfo;
     403        1789 :     poDriver->SetMetadataItem(GDAL_DCAP_OPEN, "YES");
     404        1789 : }
     405             : 
     406             : /************************************************************************/
     407             : /*                 HDF5ImageDriverSetCommonMetadata()                   */
     408             : /************************************************************************/
     409             : 
     410        1789 : void HDF5ImageDriverSetCommonMetadata(GDALDriver *poDriver)
     411             : {
     412        1789 :     poDriver->SetDescription(HDF5_IMAGE_DRIVER_NAME);
     413        1789 :     poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
     414        1789 :     poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "HDF5 Dataset");
     415        1789 :     poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/hdf5.html");
     416        1789 :     poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
     417             : 
     418        1789 :     poDriver->pfnIdentify = HDF5ImageDatasetIdentify;
     419        1789 :     poDriver->SetMetadataItem(GDAL_DCAP_OPEN, "YES");
     420        1789 : }
     421             : 
     422             : /************************************************************************/
     423             : /*                     BAGDriverSetCommonMetadata()                     */
     424             : /************************************************************************/
     425             : 
     426        1789 : void BAGDriverSetCommonMetadata(GDALDriver *poDriver)
     427             : {
     428        1789 :     poDriver->SetDescription(BAG_DRIVER_NAME);
     429        1789 :     poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
     430        1789 :     poDriver->SetMetadataItem(GDAL_DCAP_VECTOR, "YES");
     431        1789 :     poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "Bathymetry Attributed Grid");
     432        1789 :     poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/bag.html");
     433        1789 :     poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
     434        1789 :     poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "bag");
     435             : 
     436        1789 :     poDriver->SetMetadataItem(GDAL_DMD_CREATIONDATATYPES, "Float32");
     437             : 
     438        1789 :     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        1789 :         "</OpenOptionList>");
     499             : 
     500        1789 :     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        1789 :         "</CreationOptionList>");
     517             : 
     518        1789 :     poDriver->SetMetadataItem(GDAL_DCAP_MULTIDIM_RASTER, "YES");
     519             : 
     520        1789 :     poDriver->pfnIdentify = BAGDatasetIdentify;
     521        1789 :     poDriver->SetMetadataItem(GDAL_DCAP_OPEN, "YES");
     522        1789 :     poDriver->SetMetadataItem(GDAL_DCAP_CREATE, "YES");
     523        1789 :     poDriver->SetMetadataItem(GDAL_DCAP_CREATECOPY, "YES");
     524        1789 : }
     525             : 
     526             : /************************************************************************/
     527             : /*                    S102DriverSetCommonMetadata()                     */
     528             : /************************************************************************/
     529             : 
     530        1789 : void S102DriverSetCommonMetadata(GDALDriver *poDriver)
     531             : {
     532        1789 :     poDriver->SetDescription(S102_DRIVER_NAME);
     533        1789 :     poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
     534        1789 :     poDriver->SetMetadataItem(GDAL_DCAP_MULTIDIM_RASTER, "YES");
     535        1789 :     poDriver->SetMetadataItem(GDAL_DMD_LONGNAME,
     536        1789 :                               "S-102 Bathymetric Surface Product");
     537        1789 :     poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/s102.html");
     538        1789 :     poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
     539        1789 :     poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "h5");
     540        1789 :     poDriver->SetMetadataItem(GDAL_DMD_SUBDATASETS, "YES");
     541        1789 :     poDriver->SetMetadataItem(GDAL_DCAP_CREATE_SUBDATASETS, "YES");
     542             : 
     543        1789 :     poDriver->SetMetadataItem(
     544             :         GDAL_DMD_OPENOPTIONLIST,
     545             :         "<OpenOptionList>"
     546             :         "   <Option name='DEPTH_OR_ELEVATION' type='string-select' "
     547             :         "default='DEPTH'>"
     548             :         "       <Value>DEPTH</Value>"
     549             :         "       <Value>ELEVATION</Value>"
     550             :         "   </Option>"
     551             :         "   <Option name='NORTH_UP' type='boolean' default='YES' "
     552             :         "description='Whether the top line of the dataset should be the "
     553             :         "northern-most one'/>"
     554        1789 :         "</OpenOptionList>");
     555             : 
     556        1789 :     poDriver->SetMetadataItem(
     557             :         GDAL_DMD_CREATIONOPTIONLIST,
     558             :         "<CreationOptionList>"
     559             :         "  <Option name='VERTICAL_DATUM' type='string' description="
     560             :         "'Vertical datum abbreviation or code (required)'/>"
     561             :         "  <Option name='ISSUE_DATE' type='string' description="
     562             :         "'Issue date as YYYYMMDD'/>"
     563             :         "  <Option name='ISSUE_TIME' type='string' description="
     564             :         "'Issue time as hhmmssZ or hhmmss[+-]HHMM'/>"
     565             :         "  <Option name='HORIZONTAL_POSITION_UNCERTAINTY' type='float' "
     566             :         "description='Horizontal position uncertainty in meter'/>"
     567             :         "  <Option name='VERTICAL_UNCERTAINTY' type='float' "
     568             :         "description='Vertical uncertainty in meter'/>"
     569             :         "  <Option name='QUALITY_DATASET' type='string' description="
     570             :         "'Path to a dataset with the quality of bathymetric coverage'/>"
     571             :         "  <Option name='COMPRESS' type='string-select' default='DEFLATE'>"
     572             :         "    <Value>NONE</Value>"
     573             :         "    <Value>DEFLATE</Value>"
     574             :         "  </Option>"
     575             :         "  <Option name='ZLEVEL' type='int' "
     576             :         "description='DEFLATE compression level 1-9' default='6' />"
     577             :         "  <Option name='BLOCK_SIZE' type='int' description='Chunk size' />"
     578        1789 :         "</CreationOptionList>");
     579             : 
     580        1789 :     poDriver->pfnIdentify = S102DatasetIdentify;
     581        1789 :     poDriver->SetMetadataItem(GDAL_DCAP_OPEN, "YES");
     582        1789 :     poDriver->SetMetadataItem(GDAL_DCAP_CREATECOPY, "YES");
     583        1789 : }
     584             : 
     585             : /************************************************************************/
     586             : /*                    S104DriverSetCommonMetadata()                     */
     587             : /************************************************************************/
     588             : 
     589        1789 : void S104DriverSetCommonMetadata(GDALDriver *poDriver)
     590             : {
     591        1789 :     poDriver->SetDescription(S104_DRIVER_NAME);
     592        1789 :     poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
     593        1789 :     poDriver->SetMetadataItem(GDAL_DCAP_MULTIDIM_RASTER, "YES");
     594        1789 :     poDriver->SetMetadataItem(
     595             :         GDAL_DMD_LONGNAME,
     596        1789 :         "S-104 Water Level Information for Surface Navigation Product");
     597        1789 :     poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/s104.html");
     598        1789 :     poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
     599        1789 :     poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "h5");
     600        1789 :     poDriver->SetMetadataItem(GDAL_DMD_SUBDATASETS, "YES");
     601        1789 :     poDriver->SetMetadataItem(GDAL_DCAP_CREATE_SUBDATASETS, "YES");
     602             : 
     603        1789 :     poDriver->SetMetadataItem(
     604             :         GDAL_DMD_OPENOPTIONLIST,
     605             :         "<OpenOptionList>"
     606             :         "   <Option name='NORTH_UP' type='boolean' default='YES' "
     607             :         "description='Whether the top line of the dataset should be the "
     608             :         "northern-most one'/>"
     609        1789 :         "</OpenOptionList>");
     610             : 
     611        1789 :     poDriver->SetMetadataItem(
     612             :         GDAL_DMD_CREATIONOPTIONLIST,
     613             :         "<CreationOptionList>"
     614             :         "  <Option name='TIME_POINT' type='string' description="
     615             :         "'Timestamp as YYYYMMDDTHHMMSSZ format (required)'/>"
     616             :         "  <Option name='VERTICAL_DATUM' type='string' description="
     617             :         "'Vertical datum abbreviation or code (required)'/>"
     618             :         "  <Option name='VERTICAL_CS' type='string-select' description="
     619             :         "'Vertical coordinate system (required).'>"
     620             :         "    <Value alias='6498'>DEPTH</Value>"
     621             :         "    <Value alias='6499'>HEIGHT</Value>"
     622             :         "  </Option>"
     623             :         "  <Option name='WATER_LEVEL_TREND_THRESHOLD' type='float' description="
     624             :         "'Critical value used to determine steady water level trend (required)."
     625             :         "Units are meters/hour (m/hr)'/>"
     626             :         "  <Option name='DATA_DYNAMICITY' type='string-select' description="
     627             :         "'Classification of data according to the relationship between the "
     628             :         "time of its collection, generation, or calculation of generation "
     629             :         "parameters, in relation to the time of publication of the dataset "
     630             :         "(required).'>"
     631             :         "    <Value alias='1'>observation</Value>"
     632             :         "    <Value alias='2'>astronomicalPrediction</Value>"
     633             :         "    <Value alias='3'>analysisOrHybrid</Value>"
     634             :         "    <Value alias='5'>hydrodynamicForecast</Value>"
     635             :         "  </Option>"
     636             :         "  <Option name='DATASETS' type='string' description="
     637             :         "'Comma separated list of datasets at different timestamps.'/>"
     638             :         "  <Option name='DATASETS_TIME_POINT' type='string' description="
     639             :         "'Comma separated list of the time point value of each dataset of "
     640             :         "DATASETS.'/>"
     641             :         "  <Option name='GEOGRAPHIC_IDENTIFIER' type='string' description="
     642             :         "'Description, or location code from list agreed by data producers'/>"
     643             :         "  <Option name='ISSUE_DATE' type='string' description="
     644             :         "'Issue date as YYYYMMDD'/>"
     645             :         "  <Option name='ISSUE_TIME' type='string' description="
     646             :         "'Issue time as hhmmssZ or hhmmss[+-]HHMM'/>"
     647             :         "  <Option name='TREND_INTERVAL' type='integer' "
     648             :         "description='Interval, in minutes, over which trend at a a particular "
     649             :         "time is calculated'/>"
     650             :         "  <Option name='DATASET_DELIVERY_INTERVAL' type='string' description="
     651             :         "'Expected time interval between availability of successive datasets "
     652             :         "for time-varying data. Must be formatted as PnYnMnDTnHnMnS "
     653             :         "(ISO8601 duration)'/>"
     654             :         "  <Option name='TIME_RECORD_INTERVAL' type='integer' description="
     655             :         "'Interval in seconds between time records.'/>"
     656             :         "  <Option name='COMMON_POINT_RULE' type='string-select' description="
     657             :         "'Procedure used for evaluating the coverage at a position that falls "
     658             :         "on the boundary or in an area of overlap between geographic objects' "
     659             :         "default='all'>"
     660             :         "    <Value alias='1'>average</Value>"
     661             :         "    <Value alias='2'>low</Value>"
     662             :         "    <Value alias='3'>high</Value>"
     663             :         "    <Value alias='4'>all</Value>"
     664             :         "  </Option>"
     665             :         "  <Option name='UNCERTAINTY' type='float' "
     666             :         "description='Uncertainty of depth values in meter'/>"
     667             :         "  <Option name='HORIZONTAL_POSITION_UNCERTAINTY' type='float' "
     668             :         "description='Horizontal position uncertainty in meter'/>"
     669             :         "  <Option name='VERTICAL_UNCERTAINTY' type='float' "
     670             :         "description='Vertical uncertainty in meter'/>"
     671             :         "  <Option name='TIME_UNCERTAINTY' type='float' "
     672             :         "description='Time uncertainty in second'/>"
     673             :         "  <Option name='COMPRESS' type='string-select' default='DEFLATE'>"
     674             :         "    <Value>NONE</Value>"
     675             :         "    <Value>DEFLATE</Value>"
     676             :         "  </Option>"
     677             :         "  <Option name='ZLEVEL' type='int' "
     678             :         "description='DEFLATE compression level 1-9' default='6' />"
     679             :         "  <Option name='BLOCK_SIZE' type='int' description='Chunk size' />"
     680        1789 :         "</CreationOptionList>");
     681             : 
     682        1789 :     poDriver->pfnIdentify = S104DatasetIdentify;
     683        1789 :     poDriver->SetMetadataItem(GDAL_DCAP_OPEN, "YES");
     684        1789 :     poDriver->SetMetadataItem(GDAL_DCAP_CREATECOPY, "YES");
     685        1789 : }
     686             : 
     687             : /************************************************************************/
     688             : /*                    S111DriverSetCommonMetadata()                     */
     689             : /************************************************************************/
     690             : 
     691        1789 : void S111DriverSetCommonMetadata(GDALDriver *poDriver)
     692             : {
     693        1789 :     poDriver->SetDescription(S111_DRIVER_NAME);
     694        1789 :     poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
     695        1789 :     poDriver->SetMetadataItem(GDAL_DCAP_MULTIDIM_RASTER, "YES");
     696        1789 :     poDriver->SetMetadataItem(GDAL_DMD_LONGNAME,
     697        1789 :                               "S-111 Surface Currents Product");
     698        1789 :     poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/s111.html");
     699        1789 :     poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
     700        1789 :     poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "h5");
     701        1789 :     poDriver->SetMetadataItem(GDAL_DMD_SUBDATASETS, "YES");
     702        1789 :     poDriver->SetMetadataItem(GDAL_DCAP_CREATE_SUBDATASETS, "YES");
     703             : 
     704        1789 :     poDriver->SetMetadataItem(
     705             :         GDAL_DMD_OPENOPTIONLIST,
     706             :         "<OpenOptionList>"
     707             :         "   <Option name='NORTH_UP' type='boolean' default='YES' "
     708             :         "description='Whether the top line of the dataset should be the "
     709             :         "northern-most one'/>"
     710        1789 :         "</OpenOptionList>");
     711             : 
     712        1789 :     poDriver->SetMetadataItem(
     713             :         GDAL_DMD_CREATIONOPTIONLIST,
     714             :         "<CreationOptionList>"
     715             :         "  <Option name='TIME_POINT' type='string' description="
     716             :         "'Timestamp as YYYYMMDDTHHMMSSZ format (required)'/>"
     717             :         "  <Option name='DEPTH_TYPE' type='string-select' description="
     718             :         "'Type of depth (required). When selecting heightOrDepth, "
     719             :         "the interpretation depends on the VERTICAL_CS value.'>"
     720             :         "    <Value alias='1'>heightOrDepth</Value>"
     721             :         "    <Value alias='2'>layerAverage</Value>"
     722             :         "  </Option>"
     723             :         "  <Option name='VERTICAL_DATUM' type='string' description="
     724             :         "'Vertical datum abbreviation or code (required if "
     725             :         "DEPTH_TYPE=heightOrDepth)'/>"
     726             :         "  <Option name='VERTICAL_CS' type='string-select' description="
     727             :         "'Vertical coordinate system (required if DEPTH_TYPE=heightOrDepth).'>"
     728             :         "    <Value alias='6498'>DEPTH</Value>"
     729             :         "    <Value alias='6499'>HEIGHT</Value>"
     730             :         "  </Option>"
     731             :         "  <Option name='SURFACE_CURRENT_DEPTH' type='float' description="
     732             :         "'Depth/height value or layer thickness (m) (required)'/>"
     733             :         "  <Option name='DATA_DYNAMICITY' type='string-select' description="
     734             :         "'Classification of data according to the relationship between the "
     735             :         "time of its collection, generation, or calculation of generation "
     736             :         "parameters, in relation to the time of publication of the dataset "
     737             :         "(required).'>"
     738             :         "    <Value alias='1'>observation</Value>"
     739             :         "    <Value alias='2'>astronomicalPrediction</Value>"
     740             :         "    <Value alias='3'>analysisOrHybrid</Value>"
     741             :         "    <Value alias='5'>hydrodynamicForecast</Value>"
     742             :         "  </Option>"
     743             :         "  <Option name='DATASETS' type='string' description="
     744             :         "'Comma separated list of datasets at different timestamps.'/>"
     745             :         "  <Option name='DATASETS_TIME_POINT' type='string' description="
     746             :         "'Comma separated list of the time point value of each dataset of "
     747             :         "DATASETS.'/>"
     748             :         "  <Option name='GEOGRAPHIC_IDENTIFIER' type='string' description="
     749             :         "'Description, or location code from list agreed by data producers'/>"
     750             :         "  <Option name='ISSUE_DATE' type='string' description="
     751             :         "'Issue date as YYYYMMDD'/>"
     752             :         "  <Option name='ISSUE_TIME' type='string' description="
     753             :         "'Issue time as hhmmssZ or hhmmss[+-]HHMM'/>"
     754             :         "  <Option name='DATASET_DELIVERY_INTERVAL' type='string' description="
     755             :         "'Expected time interval between availability of successive datasets "
     756             :         "for time-varying data. Must be formatted as PnYnMnDTnHnMnS "
     757             :         "(ISO8601 duration)'/>"
     758             :         "  <Option name='TIME_RECORD_INTERVAL' type='integer' description="
     759             :         "'Interval in seconds between time records.'/>"
     760             :         "  <Option name='COMMON_POINT_RULE' type='string-select' description="
     761             :         "'Procedure used for evaluating the coverage at a position that falls "
     762             :         "on the boundary or in an area of overlap between geographic objects' "
     763             :         "default='high'>"
     764             :         "    <Value alias='1'>average</Value>"
     765             :         "    <Value alias='2'>low</Value>"
     766             :         "    <Value alias='3'>high</Value>"
     767             :         "    <Value alias='4'>all</Value>"
     768             :         "  </Option>"
     769             :         "  <Option name='UNCERTAINTY_SPEED' type='float' "
     770             :         "description='Uncertainty of speeds in knot'/>"
     771             :         "  <Option name='UNCERTAINTY_DIRECTION' type='float' "
     772             :         "description='Uncertainty of direction angles in degree'/>"
     773             :         "  <Option name='HORIZONTAL_POSITION_UNCERTAINTY' type='float' "
     774             :         "description='Horizontal position uncertainty in meter'/>"
     775             :         "  <Option name='VERTICAL_UNCERTAINTY' type='float' "
     776             :         "description='Vertical uncertainty in meter'/>"
     777             :         "  <Option name='TIME_UNCERTAINTY' type='float' "
     778             :         "description='Time uncertainty in second'/>"
     779             :         "  <Option name='COMPRESS' type='string-select' default='DEFLATE'>"
     780             :         "    <Value>NONE</Value>"
     781             :         "    <Value>DEFLATE</Value>"
     782             :         "  </Option>"
     783             :         "  <Option name='ZLEVEL' type='int' "
     784             :         "description='DEFLATE compression level 1-9' default='6' />"
     785             :         "  <Option name='BLOCK_SIZE' type='int' description='Chunk size' />"
     786        1789 :         "</CreationOptionList>");
     787             : 
     788        1789 :     poDriver->pfnIdentify = S111DatasetIdentify;
     789        1789 :     poDriver->SetMetadataItem(GDAL_DCAP_OPEN, "YES");
     790        1789 :     poDriver->SetMetadataItem(GDAL_DCAP_CREATECOPY, "YES");
     791        1789 : }
     792             : 
     793             : /************************************************************************/
     794             : /*                    DeclareDeferredHDF5Plugin()                       */
     795             : /************************************************************************/
     796             : 
     797             : #ifdef PLUGIN_FILENAME
     798        2058 : void DeclareDeferredHDF5Plugin()
     799             : {
     800        2058 :     if (GDALGetDriverByName(HDF5_DRIVER_NAME) != nullptr)
     801             :     {
     802         283 :         return;
     803             :     }
     804             :     {
     805        1775 :         auto poDriver = new GDALPluginDriverProxy(PLUGIN_FILENAME);
     806             : #ifdef PLUGIN_INSTALLATION_MESSAGE
     807             :         poDriver->SetMetadataItem(GDAL_DMD_PLUGIN_INSTALLATION_MESSAGE,
     808             :                                   PLUGIN_INSTALLATION_MESSAGE);
     809             : #endif
     810        1775 :         HDF5DriverSetCommonMetadata(poDriver);
     811        1775 :         GetGDALDriverManager()->DeclareDeferredPluginDriver(poDriver);
     812             :     }
     813             :     {
     814        1775 :         auto poDriver = new GDALPluginDriverProxy(PLUGIN_FILENAME);
     815             : #ifdef PLUGIN_INSTALLATION_MESSAGE
     816             :         poDriver->SetMetadataItem(GDAL_DMD_PLUGIN_INSTALLATION_MESSAGE,
     817             :                                   PLUGIN_INSTALLATION_MESSAGE);
     818             : #endif
     819        1775 :         HDF5ImageDriverSetCommonMetadata(poDriver);
     820        1775 :         GetGDALDriverManager()->DeclareDeferredPluginDriver(poDriver);
     821             :     }
     822             :     {
     823        1775 :         auto poDriver = new GDALPluginDriverProxy(PLUGIN_FILENAME);
     824             : #ifdef PLUGIN_INSTALLATION_MESSAGE
     825             :         poDriver->SetMetadataItem(GDAL_DMD_PLUGIN_INSTALLATION_MESSAGE,
     826             :                                   PLUGIN_INSTALLATION_MESSAGE);
     827             : #endif
     828        1775 :         BAGDriverSetCommonMetadata(poDriver);
     829        1775 :         GetGDALDriverManager()->DeclareDeferredPluginDriver(poDriver);
     830             :     }
     831             :     {
     832        1775 :         auto poDriver = new GDALPluginDriverProxy(PLUGIN_FILENAME);
     833             : #ifdef PLUGIN_INSTALLATION_MESSAGE
     834             :         poDriver->SetMetadataItem(GDAL_DMD_PLUGIN_INSTALLATION_MESSAGE,
     835             :                                   PLUGIN_INSTALLATION_MESSAGE);
     836             : #endif
     837        1775 :         S102DriverSetCommonMetadata(poDriver);
     838        1775 :         GetGDALDriverManager()->DeclareDeferredPluginDriver(poDriver);
     839             :     }
     840             :     {
     841        1775 :         auto poDriver = new GDALPluginDriverProxy(PLUGIN_FILENAME);
     842             : #ifdef PLUGIN_INSTALLATION_MESSAGE
     843             :         poDriver->SetMetadataItem(GDAL_DMD_PLUGIN_INSTALLATION_MESSAGE,
     844             :                                   PLUGIN_INSTALLATION_MESSAGE);
     845             : #endif
     846        1775 :         S104DriverSetCommonMetadata(poDriver);
     847        1775 :         GetGDALDriverManager()->DeclareDeferredPluginDriver(poDriver);
     848             :     }
     849             :     {
     850        1775 :         auto poDriver = new GDALPluginDriverProxy(PLUGIN_FILENAME);
     851             : #ifdef PLUGIN_INSTALLATION_MESSAGE
     852             :         poDriver->SetMetadataItem(GDAL_DMD_PLUGIN_INSTALLATION_MESSAGE,
     853             :                                   PLUGIN_INSTALLATION_MESSAGE);
     854             : #endif
     855        1775 :         S111DriverSetCommonMetadata(poDriver);
     856        1775 :         GetGDALDriverManager()->DeclareDeferredPluginDriver(poDriver);
     857             :     }
     858             : }
     859             : #endif

Generated by: LCOV version 1.14