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

Generated by: LCOV version 1.14