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

Generated by: LCOV version 1.14