LCOV - code coverage report
Current view: top level - gcore - gdalsubdatasetinfo.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 70 75 93.3 %
Date: 2025-06-28 21:28:23 Functions: 12 12 100.0 %

          Line data    Source code
       1             : /***************************************************************************
       2             :   gdal_subdatasetinfo.cpp - GDALSubdatasetInfo
       3             : 
       4             :  ---------------------
       5             :  begin                : 21.7.2023
       6             :  copyright            : (C) 2023 by Alessndro Pasotti
       7             :  email                : elpaso@itopen.it
       8             :  ***************************************************************************
       9             :  *                                                                         *
      10             :  * SPDX-License-Identifier: MIT
      11             :  *                                                                         *
      12             :  ***************************************************************************/
      13             : #include "gdalsubdatasetinfo.h"
      14             : #include "gdal_priv.h"
      15             : #include <algorithm>
      16             : #include <stdexcept>
      17             : 
      18             : /************************************************************************/
      19             : /*                     Subdataset informational functions               */
      20             : /************************************************************************/
      21             : 
      22        2757 : GDALSubdatasetInfoH GDALGetSubdatasetInfo(const char *pszFileName)
      23             : {
      24             :     // Iterate all drivers
      25        2757 :     GDALDriverManager *poDM_ = GetGDALDriverManager();
      26        2757 :     const int nDriverCount = poDM_->GetDriverCount();
      27      596360 :     for (int iDriver = 0; iDriver < nDriverCount; ++iDriver)
      28             :     {
      29      593697 :         GDALDriver *poDriver = poDM_->GetDriver(iDriver);
      30      593697 :         if (!poDriver->pfnGetSubdatasetInfoFunc)
      31             :         {
      32      574781 :             continue;
      33             :         }
      34             :         const char *pszDMDSubdatasets =
      35       18916 :             GDALGetMetadataItem(poDriver, GDAL_DMD_SUBDATASETS, nullptr);
      36       18916 :         if (!pszDMDSubdatasets || !CPLTestBool(pszDMDSubdatasets))
      37             :         {
      38           0 :             continue;
      39             :         }
      40             : 
      41             :         GDALSubdatasetInfo *poGetSubdatasetInfo =
      42       18916 :             poDriver->pfnGetSubdatasetInfoFunc(pszFileName);
      43             : 
      44       18916 :         if (!poGetSubdatasetInfo)
      45             :         {
      46       18822 :             continue;
      47             :         }
      48             : 
      49          94 :         return static_cast<GDALSubdatasetInfoH>(poGetSubdatasetInfo);
      50             :     }
      51        2663 :     return nullptr;
      52             : }
      53             : 
      54             : /************************************************************************/
      55             : /*                       GDALDestroySubdatasetInfo()                    */
      56             : /************************************************************************/
      57             : 
      58             : /**
      59             :  * \brief Destroys subdataset info.
      60             :  *
      61             :  * This function is the same as the C++ method GDALSubdatasetInfo::~GDALSubdatasetInfo()
      62             :  */
      63          94 : void GDALDestroySubdatasetInfo(GDALSubdatasetInfoH hInfo)
      64             : 
      65             : {
      66          94 :     delete hInfo;
      67          94 : }
      68             : 
      69          35 : char *GDALSubdatasetInfoGetPathComponent(GDALSubdatasetInfoH hInfo)
      70             : {
      71          35 :     return CPLStrdup(hInfo->GetPathComponent().c_str());
      72             : }
      73             : 
      74          63 : char *GDALSubdatasetInfoGetSubdatasetComponent(GDALSubdatasetInfoH hInfo)
      75             : {
      76          63 :     return CPLStrdup(hInfo->GetSubdatasetComponent().c_str());
      77             : }
      78             : 
      79          21 : char *GDALSubdatasetInfoModifyPathComponent(GDALSubdatasetInfoH hInfo,
      80             :                                             const char *pszNewFileName)
      81             : {
      82          21 :     return CPLStrdup(hInfo->ModifyPathComponent(pszNewFileName).c_str());
      83             : }
      84             : 
      85         108 : GDALSubdatasetInfo::GDALSubdatasetInfo(const std::string &fileName)
      86             :     : m_fileName(fileName), m_pathComponent(), m_cleanedPathComponent(),
      87         108 :       m_subdatasetComponent(), m_driverPrefixComponent()
      88             : {
      89         108 : }
      90             : 
      91             : GDALSubdatasetInfo::~GDALSubdatasetInfo() = default;
      92             : 
      93         151 : std::string GDALSubdatasetInfo::GetPathComponent() const
      94             : {
      95         151 :     init();
      96         151 :     return m_cleanedPathComponent;
      97             : }
      98             : 
      99             : std::string
     100          30 : GDALSubdatasetInfo::ModifyPathComponent(const std::string &newPathName) const
     101             : {
     102          30 :     init();
     103             : 
     104          60 :     std::string replaced{m_fileName};
     105             : 
     106             :     try
     107             :     {
     108          60 :         auto newPathName_{newPathName};
     109          30 :         if (m_isQuoted)
     110             :         {
     111          24 :             if (newPathName_.length() >= 2 && newPathName_.at(0) != '"' &&
     112           9 :                 newPathName_.at(newPathName_.length() - 1) != '"')
     113             :             {
     114           9 :                 newPathName_ = quote(newPathName_);
     115             :             }
     116             :         }
     117          30 :         replaced.replace(replaced.find(m_pathComponent),
     118          30 :                          m_pathComponent.length(), newPathName_);
     119             :     }
     120           0 :     catch (const std::out_of_range &)
     121             :     {
     122           0 :         return "";
     123             :     }
     124             : 
     125          30 :     return replaced;
     126             : }
     127             : 
     128         118 : std::string GDALSubdatasetInfo::GetSubdatasetComponent() const
     129             : {
     130         118 :     init();
     131         118 :     return m_subdatasetComponent;
     132             : }
     133             : 
     134             : //! @cond Doxygen_Suppress
     135          52 : std::string GDALSubdatasetInfo::unquote(const std::string &path)
     136             : {
     137          52 :     if (path.length() >= 2)
     138             :     {
     139          52 :         std::string cleanedPath{path};
     140         104 :         if (cleanedPath.at(0) == '"' &&
     141          52 :             cleanedPath.at(cleanedPath.length() - 1) == '"')
     142             :         {
     143          52 :             cleanedPath = cleanedPath.substr(1, cleanedPath.length() - 2);
     144          54 :             while (cleanedPath.find(R"(\")") != std::string::npos)
     145             :             {
     146           2 :                 const auto pos{cleanedPath.find(R"(\")")};
     147           2 :                 if (pos == 0 || cleanedPath.at(pos - 1) != '\\')
     148             :                 {
     149           2 :                     cleanedPath.erase(pos, 1);
     150             :                 }
     151             :             }
     152          52 :             return cleanedPath;
     153             :         }
     154             :     }
     155           0 :     return path;
     156             : }
     157             : 
     158           9 : std::string GDALSubdatasetInfo::quote(const std::string &path)
     159             : {
     160          18 :     std::string quotedPath{'"'};
     161         357 :     for (size_t i = 0; i < path.length(); ++i)
     162             :     {
     163         348 :         if (path.at(i) == '"')
     164             :         {
     165           0 :             quotedPath += R"(\")";
     166             :         }
     167             :         else
     168             :         {
     169         348 :             quotedPath += path.at(i);
     170             :         }
     171             :     }
     172          18 :     return quotedPath + '"';
     173             : }
     174             : 
     175         299 : void GDALSubdatasetInfo::init() const
     176             : {
     177         299 :     if (!m_initialized)
     178             :     {
     179         108 :         GDALSubdatasetInfo *this_ = const_cast<GDALSubdatasetInfo *>(this);
     180         108 :         this_->parseFileName();
     181         108 :         this_->m_isQuoted =
     182         160 :             m_pathComponent.length() >= 2 && m_pathComponent.at(0) == '"' &&
     183          52 :             m_pathComponent.at(m_pathComponent.length() - 1) == '"';
     184             :         this_->m_cleanedPathComponent =
     185         108 :             m_isQuoted ? unquote(m_pathComponent) : m_pathComponent;
     186         108 :         m_initialized = true;
     187             :     }
     188         299 : }
     189             : 
     190             : //! @endcond

Generated by: LCOV version 1.14