LCOV - code coverage report
Current view: top level - apps - gdalalg_dataset_identify.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 84 85 98.8 %
Date: 2025-08-01 10:10:57 Functions: 5 5 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  GDAL
       4             :  * Purpose:  gdal "dataset identify" subcommand
       5             :  * Author:   Even Rouault <even dot rouault at spatialys.com>
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2025, Even Rouault <even dot rouault at spatialys.com>
       9             :  *
      10             :  * SPDX-License-Identifier: MIT
      11             :  ****************************************************************************/
      12             : 
      13             : #include "gdalalg_dataset_identify.h"
      14             : 
      15             : #include "cpl_string.h"
      16             : 
      17             : //! @cond Doxygen_Suppress
      18             : 
      19             : #ifndef _
      20             : #define _(x) (x)
      21             : #endif
      22             : 
      23             : /************************************************************************/
      24             : /*                       GDALDatasetIdentifyAlgorithm()                 */
      25             : /************************************************************************/
      26             : 
      27          10 : GDALDatasetIdentifyAlgorithm::GDALDatasetIdentifyAlgorithm()
      28          10 :     : GDALAlgorithm(NAME, DESCRIPTION, HELP_URL), m_oWriter(JSONPrint, this)
      29             : {
      30          10 :     AddProgressArg();
      31             : 
      32          20 :     auto &arg = AddArg("filename", 0, _("File or directory name"), &m_filename)
      33          10 :                     .SetPositional()
      34          10 :                     .SetRequired();
      35          10 :     SetAutoCompleteFunctionForFilename(arg, 0);
      36             : 
      37          10 :     AddOutputFormatArg(&m_format).SetChoices("json", "text");
      38             : 
      39             :     AddArg("recursive", 'r', _("Recursively scan files/folders for datasets"),
      40          10 :            &m_recursive);
      41             : 
      42             :     AddArg("force-recursive", 0,
      43             :            _("Recursively scan folders for datasets, forcing "
      44             :              "recursion in folders recognized as valid formats"),
      45          10 :            &m_forceRecursive);
      46             : 
      47             :     AddArg("report-failures", 0,
      48             :            _("Report failures if file type is unidentified"),
      49          10 :            &m_reportFailures);
      50             : 
      51          10 :     AddOutputStringArg(&m_output);
      52             :     AddArg(
      53             :         "stdout", 0,
      54             :         _("Directly output on stdout. If enabled, output-string will be empty"),
      55          20 :         &m_stdout)
      56          10 :         .SetHiddenForCLI();
      57          10 : }
      58             : 
      59             : /************************************************************************/
      60             : /*                GDALDatasetIdentifyAlgorithm::Print()                 */
      61             : /************************************************************************/
      62             : 
      63         954 : void GDALDatasetIdentifyAlgorithm::Print(const char *str)
      64             : {
      65         954 :     if (m_stdout)
      66           1 :         fwrite(str, 1, strlen(str), stdout);
      67             :     else
      68         953 :         m_output += str;
      69         954 : }
      70             : 
      71             : /************************************************************************/
      72             : /*                 GDALDatasetIdentifyAlgorithm::JSONPrint()            */
      73             : /************************************************************************/
      74             : 
      75         951 : /* static */ void GDALDatasetIdentifyAlgorithm::JSONPrint(const char *pszTxt,
      76             :                                                           void *pUserData)
      77             : {
      78         951 :     static_cast<GDALDatasetIdentifyAlgorithm *>(pUserData)->Print(pszTxt);
      79         951 : }
      80             : 
      81             : /************************************************************************/
      82             : /*                              Process()                               */
      83             : /************************************************************************/
      84             : 
      85          71 : bool GDALDatasetIdentifyAlgorithm::Process(const char *pszTarget,
      86             :                                            CSLConstList papszSiblingList,
      87             :                                            GDALProgressFunc pfnProgress,
      88             :                                            void *pProgressData)
      89             : 
      90             : {
      91          71 :     if (IsCalledFromCommandLine())
      92           1 :         pfnProgress = nullptr;
      93             : 
      94          71 :     if (m_format.empty())
      95           0 :         m_format = IsCalledFromCommandLine() ? "text" : "json";
      96             : 
      97          71 :     GDALDriverH hDriver = nullptr;
      98             :     {
      99          71 :         CPLErrorStateBackuper oBackuper(CPLQuietErrorHandler);
     100          71 :         hDriver = GDALIdentifyDriver(pszTarget, papszSiblingList);
     101             :     }
     102             : 
     103          71 :     if (m_format == "json")
     104             :     {
     105          68 :         if (hDriver)
     106             :         {
     107          51 :             m_oWriter.StartObj();
     108          51 :             m_oWriter.AddObjKey("name");
     109          51 :             m_oWriter.Add(pszTarget);
     110          51 :             m_oWriter.AddObjKey("driver");
     111          51 :             m_oWriter.Add(GDALGetDriverShortName(hDriver));
     112          51 :             m_oWriter.EndObj();
     113             :         }
     114          17 :         else if (m_reportFailures)
     115             :         {
     116           1 :             m_oWriter.StartObj();
     117           1 :             m_oWriter.AddObjKey("name");
     118           1 :             m_oWriter.Add(pszTarget);
     119           1 :             m_oWriter.AddObjKey("driver");
     120           1 :             m_oWriter.AddNull();
     121           1 :             m_oWriter.EndObj();
     122             :         }
     123             :     }
     124             :     else
     125             :     {
     126           3 :         if (hDriver)
     127           2 :             Print(CPLSPrintf("%s: %s\n", pszTarget,
     128             :                              GDALGetDriverShortName(hDriver)));
     129           1 :         else if (m_reportFailures)
     130           1 :             Print(CPLSPrintf("%s: unrecognized\n", pszTarget));
     131             :     }
     132             : 
     133          71 :     bool ret = true;
     134             :     VSIStatBufL sStatBuf;
     135           8 :     if ((m_forceRecursive || (m_recursive && hDriver == nullptr)) &&
     136          79 :         VSIStatL(pszTarget, &sStatBuf) == 0 && VSI_ISDIR(sStatBuf.st_mode))
     137             :     {
     138           2 :         const CPLStringList aosSiblingList(VSIReadDir(pszTarget));
     139           1 :         const int nListSize = aosSiblingList.size();
     140          65 :         for (int i = 0; i < nListSize; ++i)
     141             :         {
     142          64 :             const char *pszSubTarget = aosSiblingList[i];
     143          64 :             if (!(EQUAL(pszSubTarget, "..") || EQUAL(pszSubTarget, ".")))
     144             :             {
     145             :                 const std::string osSubTarget =
     146         124 :                     CPLFormFilenameSafe(pszTarget, pszSubTarget, nullptr);
     147             : 
     148             :                 std::unique_ptr<void, decltype(&GDALDestroyScaledProgress)>
     149             :                     pScaledProgress(GDALCreateScaledProgress(
     150          62 :                                         static_cast<double>(i) / nListSize,
     151          62 :                                         static_cast<double>(i + 1) / nListSize,
     152             :                                         pfnProgress, pProgressData),
     153          62 :                                     GDALDestroyScaledProgress);
     154         124 :                 ret = ret &&
     155         124 :                       Process(osSubTarget.c_str(), aosSiblingList.List(),
     156          62 :                               pScaledProgress ? GDALScaledProgress : nullptr,
     157             :                               pScaledProgress.get());
     158             :             }
     159             :         }
     160             :     }
     161             : 
     162          71 :     return ret && (!pfnProgress || pfnProgress(1.0, "", pProgressData));
     163             : }
     164             : 
     165             : /************************************************************************/
     166             : /*                  GDALDatasetIdentifyAlgorithm::RunImpl()             */
     167             : /************************************************************************/
     168             : 
     169           8 : bool GDALDatasetIdentifyAlgorithm::RunImpl(GDALProgressFunc pfnProgress,
     170             :                                            void *pProgressData)
     171             : {
     172           8 :     if (m_format.empty())
     173           6 :         m_format = IsCalledFromCommandLine() ? "text" : "json";
     174             : 
     175           8 :     if (m_format == "json")
     176           5 :         m_oWriter.StartArray();
     177           8 :     int i = 0;
     178           8 :     bool ret = true;
     179          17 :     for (const std::string &osPath : m_filename)
     180             :     {
     181             :         std::unique_ptr<void, decltype(&GDALDestroyScaledProgress)>
     182             :             pScaledProgress(GDALCreateScaledProgress(
     183           9 :                                 static_cast<double>(i) /
     184           9 :                                     static_cast<int>(m_filename.size()),
     185           9 :                                 static_cast<double>(i + 1) /
     186           9 :                                     static_cast<int>(m_filename.size()),
     187             :                                 pfnProgress, pProgressData),
     188           9 :                             GDALDestroyScaledProgress);
     189          18 :         ret = ret && Process(osPath.c_str(), nullptr,
     190           9 :                              pScaledProgress ? GDALScaledProgress : nullptr,
     191             :                              pScaledProgress.get());
     192           9 :         ++i;
     193             :     }
     194           8 :     if (m_format == "json")
     195           5 :         m_oWriter.EndArray();
     196             : 
     197           8 :     return ret;
     198             : }
     199             : 
     200             : //! @endcond

Generated by: LCOV version 1.14