LCOV - code coverage report
Current view: top level - apps - gdalalg_dataset_identify.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 79 79 100.0 %
Date: 2025-06-19 12:30:01 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).SetDefault("json").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         956 : void GDALDatasetIdentifyAlgorithm::Print(const char *str)
      64             : {
      65         956 :     if (m_stdout)
      66          21 :         fwrite(str, 1, strlen(str), stdout);
      67             :     else
      68         935 :         m_output += str;
      69         956 : }
      70             : 
      71             : /************************************************************************/
      72             : /*                 GDALDatasetIdentifyAlgorithm::JSONPrint()            */
      73             : /************************************************************************/
      74             : 
      75         954 : /* static */ void GDALDatasetIdentifyAlgorithm::JSONPrint(const char *pszTxt,
      76             :                                                           void *pUserData)
      77             : {
      78         954 :     static_cast<GDALDatasetIdentifyAlgorithm *>(pUserData)->Print(pszTxt);
      79         954 : }
      80             : 
      81             : /************************************************************************/
      82             : /*                              Process()                               */
      83             : /************************************************************************/
      84             : 
      85          70 : bool GDALDatasetIdentifyAlgorithm::Process(const char *pszTarget,
      86             :                                            CSLConstList papszSiblingList,
      87             :                                            GDALProgressFunc pfnProgress,
      88             :                                            void *pProgressData)
      89             : 
      90             : {
      91          70 :     GDALDriverH hDriver = nullptr;
      92             :     {
      93          70 :         CPLErrorStateBackuper oBackuper(CPLQuietErrorHandler);
      94          70 :         hDriver = GDALIdentifyDriver(pszTarget, papszSiblingList);
      95             :     }
      96             : 
      97          70 :     if (m_format == "json")
      98             :     {
      99          68 :         if (hDriver)
     100             :         {
     101          51 :             m_oWriter.StartObj();
     102          51 :             m_oWriter.AddObjKey("name");
     103          51 :             m_oWriter.Add(pszTarget);
     104          51 :             m_oWriter.AddObjKey("driver");
     105          51 :             m_oWriter.Add(GDALGetDriverShortName(hDriver));
     106          51 :             m_oWriter.EndObj();
     107             :         }
     108          17 :         else if (m_reportFailures)
     109             :         {
     110           1 :             m_oWriter.StartObj();
     111           1 :             m_oWriter.AddObjKey("name");
     112           1 :             m_oWriter.Add(pszTarget);
     113           1 :             m_oWriter.AddObjKey("driver");
     114           1 :             m_oWriter.AddNull();
     115           1 :             m_oWriter.EndObj();
     116             :         }
     117             :     }
     118             :     else
     119             :     {
     120           2 :         if (hDriver)
     121           1 :             Print(CPLSPrintf("%s: %s\n", pszTarget,
     122             :                              GDALGetDriverShortName(hDriver)));
     123           1 :         else if (m_reportFailures)
     124           1 :             Print(CPLSPrintf("%s: unrecognized\n", pszTarget));
     125             :     }
     126             : 
     127          70 :     bool ret = true;
     128             :     VSIStatBufL sStatBuf;
     129           8 :     if ((m_forceRecursive || (m_recursive && hDriver == nullptr)) &&
     130          78 :         VSIStatL(pszTarget, &sStatBuf) == 0 && VSI_ISDIR(sStatBuf.st_mode))
     131             :     {
     132           2 :         const CPLStringList aosSiblingList(VSIReadDir(pszTarget));
     133           1 :         const int nListSize = aosSiblingList.size();
     134          64 :         for (int i = 0; i < nListSize; ++i)
     135             :         {
     136          63 :             const char *pszSubTarget = aosSiblingList[i];
     137          63 :             if (!(EQUAL(pszSubTarget, "..") || EQUAL(pszSubTarget, ".")))
     138             :             {
     139             :                 const std::string osSubTarget =
     140         122 :                     CPLFormFilenameSafe(pszTarget, pszSubTarget, nullptr);
     141             : 
     142             :                 std::unique_ptr<void, decltype(&GDALDestroyScaledProgress)>
     143             :                     pScaledProgress(GDALCreateScaledProgress(
     144          61 :                                         static_cast<double>(i) / nListSize,
     145          61 :                                         static_cast<double>(i + 1) / nListSize,
     146             :                                         pfnProgress, pProgressData),
     147          61 :                                     GDALDestroyScaledProgress);
     148         122 :                 ret = ret &&
     149         122 :                       Process(osSubTarget.c_str(), aosSiblingList.List(),
     150          61 :                               pScaledProgress ? GDALScaledProgress : nullptr,
     151             :                               pScaledProgress.get());
     152             :             }
     153             :         }
     154             :     }
     155             : 
     156          70 :     return ret && (!pfnProgress || pfnProgress(1.0, "", pProgressData));
     157             : }
     158             : 
     159             : /************************************************************************/
     160             : /*                  GDALDatasetIdentifyAlgorithm::RunImpl()             */
     161             : /************************************************************************/
     162             : 
     163           8 : bool GDALDatasetIdentifyAlgorithm::RunImpl(GDALProgressFunc pfnProgress,
     164             :                                            void *pProgressData)
     165             : {
     166           8 :     if (m_format == "json")
     167           6 :         m_oWriter.StartArray();
     168           8 :     int i = 0;
     169           8 :     bool ret = true;
     170          17 :     for (const std::string &osPath : m_filename)
     171             :     {
     172             :         std::unique_ptr<void, decltype(&GDALDestroyScaledProgress)>
     173             :             pScaledProgress(GDALCreateScaledProgress(
     174           9 :                                 static_cast<double>(i) /
     175           9 :                                     static_cast<int>(m_filename.size()),
     176           9 :                                 static_cast<double>(i + 1) /
     177           9 :                                     static_cast<int>(m_filename.size()),
     178             :                                 pfnProgress, pProgressData),
     179           9 :                             GDALDestroyScaledProgress);
     180          18 :         ret = ret && Process(osPath.c_str(), nullptr,
     181           9 :                              pScaledProgress ? GDALScaledProgress : nullptr,
     182             :                              pScaledProgress.get());
     183           9 :         ++i;
     184             :     }
     185           8 :     if (m_format == "json")
     186           6 :         m_oWriter.EndArray();
     187             : 
     188           8 :     return ret;
     189             : }
     190             : 
     191             : //! @endcond

Generated by: LCOV version 1.14