LCOV - code coverage report
Current view: top level - frmts/hdf4 - hdf4drivercore.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 92 93 98.9 %
Date: 2024-11-21 22:18:42 Functions: 12 12 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  GDAL
       4             :  * Purpose:  HDF4 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 "hdf4drivercore.h"
      14             : 
      15             : #include <cctype>
      16             : 
      17             : /************************************************************************/
      18             : /*                              Identify()                              */
      19             : /************************************************************************/
      20             : 
      21       56001 : int HDF4DatasetIdentify(GDALOpenInfo *poOpenInfo)
      22             : 
      23             : {
      24       56001 :     if (poOpenInfo->nHeaderBytes < 4)
      25       49722 :         return FALSE;
      26             : 
      27        6279 :     if (memcmp(poOpenInfo->pabyHeader, "\016\003\023\001", 4) != 0)
      28        5654 :         return FALSE;
      29             : 
      30         625 :     return TRUE;
      31             : }
      32             : 
      33             : /************************************************************************/
      34             : /*                    HDF4DriverGetSubdatasetInfo()                     */
      35             : /************************************************************************/
      36             : 
      37             : struct HDF4DriverSubdatasetInfo : public GDALSubdatasetInfo
      38             : {
      39             :   public:
      40          17 :     explicit HDF4DriverSubdatasetInfo(const std::string &fileName)
      41          17 :         : GDALSubdatasetInfo(fileName)
      42             :     {
      43          17 :     }
      44             : 
      45             :     // GDALSubdatasetInfo interface
      46             :   private:
      47          17 :     void parseFileName() override
      48             :     {
      49             : 
      50          34 :         if (!STARTS_WITH_CI(m_fileName.c_str(), "HDF4_SDS:") &&
      51          17 :             !STARTS_WITH_CI(m_fileName.c_str(), "HDF4_EOS:"))
      52             :         {
      53           0 :             return;
      54             :         }
      55             : 
      56          34 :         CPLStringList aosParts{CSLTokenizeString2(m_fileName.c_str(), ":", 0)};
      57          17 :         const int iPartsCount{CSLCount(aosParts)};
      58             : 
      59          17 :         if (iPartsCount >= 3)
      60             :         {
      61             : 
      62             :             // prefix + mode
      63          14 :             m_driverPrefixComponent = aosParts[0];
      64          14 :             m_driverPrefixComponent.append(":");
      65          14 :             m_driverPrefixComponent.append(aosParts[1]);
      66             : 
      67          14 :             int subdatasetIndex{3};
      68             : 
      69          14 :             if (iPartsCount >= 4)
      70             :             {
      71             :                 const bool hasDriveLetter{
      72          12 :                     (strlen(aosParts[3]) > 1 &&
      73          18 :                      (aosParts[3][0] == '\\' || aosParts[3][0] == '/')) &&
      74           6 :                     ((strlen(aosParts[2]) == 2 &&
      75           2 :                       std::isalpha(
      76           2 :                           static_cast<unsigned char>(aosParts[2][1]))) ||
      77           4 :                      (strlen(aosParts[2]) == 1 &&
      78           3 :                       std::isalpha(
      79           3 :                           static_cast<unsigned char>(aosParts[2][0]))))};
      80          12 :                 m_pathComponent = aosParts[2];
      81             : 
      82          12 :                 const bool hasProtocol{m_pathComponent.find("/vsicurl/") !=
      83          12 :                                        std::string::npos};
      84             : 
      85          12 :                 if (hasDriveLetter || hasProtocol)
      86             :                 {
      87           6 :                     m_pathComponent.append(":");
      88           6 :                     m_pathComponent.append(aosParts[3]);
      89           6 :                     subdatasetIndex++;
      90             :                 }
      91             :             }
      92             : 
      93          14 :             if (iPartsCount > subdatasetIndex)
      94             :             {
      95          12 :                 m_subdatasetComponent = aosParts[subdatasetIndex];
      96             : 
      97             :                 // Append any remaining part
      98          23 :                 for (int i = subdatasetIndex + 1; i < iPartsCount; ++i)
      99             :                 {
     100          11 :                     m_subdatasetComponent.append(":");
     101          11 :                     m_subdatasetComponent.append(aosParts[i]);
     102             :                 }
     103             :             }
     104             :         }
     105             :     }
     106             : };
     107             : 
     108        2627 : static GDALSubdatasetInfo *HDF4DriverGetSubdatasetInfo(const char *pszFileName)
     109             : {
     110        2627 :     if (STARTS_WITH_CI(pszFileName, "HDF4_SDS:") ||
     111        2627 :         STARTS_WITH_CI(pszFileName, "HDF4_EOS:"))
     112             :     {
     113             :         std::unique_ptr<GDALSubdatasetInfo> info =
     114          17 :             std::make_unique<HDF4DriverSubdatasetInfo>(pszFileName);
     115          46 :         if (!info->GetSubdatasetComponent().empty() &&
     116          29 :             !info->GetPathComponent().empty())
     117             :         {
     118          12 :             return info.release();
     119             :         }
     120             :     }
     121        2615 :     return nullptr;
     122             : }
     123             : 
     124             : /************************************************************************/
     125             : /*                   HDF4DriverSetCommonMetadata()                      */
     126             : /************************************************************************/
     127             : 
     128        1302 : void HDF4DriverSetCommonMetadata(GDALDriver *poDriver)
     129             : {
     130        1302 :     poDriver->SetDescription(HDF4_DRIVER_NAME);
     131        1302 :     poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
     132        1302 :     poDriver->SetMetadataItem(GDAL_DMD_LONGNAME,
     133        1302 :                               "Hierarchical Data Format Release 4");
     134        1302 :     poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/hdf4.html");
     135        1302 :     poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "hdf");
     136        1302 :     poDriver->SetMetadataItem(GDAL_DMD_SUBDATASETS, "YES");
     137             : 
     138        1302 :     poDriver->SetMetadataItem(GDAL_DCAP_MULTIDIM_RASTER, "YES");
     139             : 
     140        1302 :     poDriver->SetMetadataItem(
     141             :         GDAL_DMD_OPENOPTIONLIST,
     142             :         "<OpenOptionList>"
     143             :         "  <Option name='LIST_SDS' type='string-select' "
     144             :         "description='Whether to report Scientific Data Sets' default='AUTO'>"
     145             :         "       <Value>AUTO</Value>"
     146             :         "       <Value>YES</Value>"
     147             :         "       <Value>NO</Value>"
     148             :         "  </Option>"
     149        1302 :         "</OpenOptionList>");
     150             : 
     151        1302 :     poDriver->pfnIdentify = HDF4DatasetIdentify;
     152        1302 :     poDriver->SetMetadataItem(GDAL_DCAP_OPEN, "YES");
     153        1302 :     poDriver->pfnGetSubdatasetInfoFunc = HDF4DriverGetSubdatasetInfo;
     154        1302 : }
     155             : 
     156             : /************************************************************************/
     157             : /*                     HDF4ImageDatasetIdentify()                       */
     158             : /************************************************************************/
     159             : 
     160       55088 : int HDF4ImageDatasetIdentify(GDALOpenInfo *poOpenInfo)
     161             : {
     162       55088 :     if (!STARTS_WITH_CI(poOpenInfo->pszFilename, "HDF4_SDS:") &&
     163       54491 :         !STARTS_WITH_CI(poOpenInfo->pszFilename, "HDF4_GR:") &&
     164       54487 :         !STARTS_WITH_CI(poOpenInfo->pszFilename, "HDF4_GD:") &&
     165       54486 :         !STARTS_WITH_CI(poOpenInfo->pszFilename, "HDF4_EOS:"))
     166       54487 :         return false;
     167         601 :     return true;
     168             : }
     169             : 
     170             : /************************************************************************/
     171             : /*                 HDF4ImageDriverSetCommonMetadata()                   */
     172             : /************************************************************************/
     173             : 
     174        1302 : void HDF4ImageDriverSetCommonMetadata(GDALDriver *poDriver)
     175             : {
     176        1302 :     poDriver->SetDescription(HDF4_IMAGE_DRIVER_NAME);
     177        1302 :     poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
     178        1302 :     poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "HDF4 Dataset");
     179        1302 :     poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/hdf4.html");
     180        1302 :     poDriver->SetMetadataItem(GDAL_DMD_CREATIONDATATYPES,
     181             :                               "Byte Int8 Int16 UInt16 Int32 UInt32 "
     182             :                               // "Int64 UInt64 "
     183        1302 :                               "Float32 Float64");
     184        1302 :     poDriver->SetMetadataItem(
     185             :         GDAL_DMD_CREATIONOPTIONLIST,
     186             :         "<CreationOptionList>"
     187             :         "   <Option name='RANK' type='int' description='Rank of output SDS'/>"
     188        1302 :         "</CreationOptionList>");
     189             : 
     190        1302 :     poDriver->SetMetadataItem(GDAL_DCAP_OPEN, "YES");
     191        1302 :     poDriver->pfnIdentify = HDF4ImageDatasetIdentify;
     192        1302 :     poDriver->SetMetadataItem(GDAL_DCAP_CREATE, "YES");
     193        1302 : }
     194             : 
     195             : /************************************************************************/
     196             : /*                    DeclareDeferredHDF4Plugin()                       */
     197             : /************************************************************************/
     198             : 
     199             : #ifdef PLUGIN_FILENAME
     200        1595 : void DeclareDeferredHDF4Plugin()
     201             : {
     202        1595 :     if (GDALGetDriverByName(HDF4_DRIVER_NAME) != nullptr)
     203             :     {
     204         302 :         return;
     205             :     }
     206             :     {
     207        1293 :         auto poDriver = new GDALPluginDriverProxy(PLUGIN_FILENAME);
     208             : #ifdef PLUGIN_INSTALLATION_MESSAGE
     209             :         poDriver->SetMetadataItem(GDAL_DMD_PLUGIN_INSTALLATION_MESSAGE,
     210             :                                   PLUGIN_INSTALLATION_MESSAGE);
     211             : #endif
     212        1293 :         HDF4DriverSetCommonMetadata(poDriver);
     213        1293 :         GetGDALDriverManager()->DeclareDeferredPluginDriver(poDriver);
     214             :     }
     215             :     {
     216        1293 :         auto poDriver = new GDALPluginDriverProxy(PLUGIN_FILENAME);
     217             : #ifdef PLUGIN_INSTALLATION_MESSAGE
     218             :         poDriver->SetMetadataItem(GDAL_DMD_PLUGIN_INSTALLATION_MESSAGE,
     219             :                                   PLUGIN_INSTALLATION_MESSAGE);
     220             : #endif
     221        1293 :         HDF4ImageDriverSetCommonMetadata(poDriver);
     222        1293 :         GetGDALDriverManager()->DeclareDeferredPluginDriver(poDriver);
     223             :     }
     224             : }
     225             : #endif

Generated by: LCOV version 1.14