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

Generated by: LCOV version 1.14