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-05-15 13:16:46 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 :         int i = 0;
     134          64 :         for (const char *pszSubTarget : cpl::Iterate(aosSiblingList))
     135             :         {
     136          63 :             if (!(EQUAL(pszSubTarget, "..") || EQUAL(pszSubTarget, ".")))
     137             :             {
     138             :                 const std::string osSubTarget =
     139         122 :                     CPLFormFilenameSafe(pszTarget, pszSubTarget, nullptr);
     140             : 
     141             :                 std::unique_ptr<void, decltype(&GDALDestroyScaledProgress)>
     142             :                     pScaledProgress(
     143             :                         GDALCreateScaledProgress(
     144         122 :                             static_cast<double>(i) / aosSiblingList.size(),
     145         122 :                             static_cast<double>(i + 1) / aosSiblingList.size(),
     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          63 :             ++i;
     154             :         }
     155             :     }
     156             : 
     157          70 :     return ret && (!pfnProgress || pfnProgress(1.0, "", pProgressData));
     158             : }
     159             : 
     160             : /************************************************************************/
     161             : /*                  GDALDatasetIdentifyAlgorithm::RunImpl()             */
     162             : /************************************************************************/
     163             : 
     164           8 : bool GDALDatasetIdentifyAlgorithm::RunImpl(GDALProgressFunc pfnProgress,
     165             :                                            void *pProgressData)
     166             : {
     167           8 :     if (m_format == "json")
     168           6 :         m_oWriter.StartArray();
     169           8 :     int i = 0;
     170           8 :     bool ret = true;
     171          17 :     for (const std::string &osPath : m_filename)
     172             :     {
     173             :         std::unique_ptr<void, decltype(&GDALDestroyScaledProgress)>
     174             :             pScaledProgress(GDALCreateScaledProgress(
     175           9 :                                 static_cast<double>(i) /
     176           9 :                                     static_cast<int>(m_filename.size()),
     177           9 :                                 static_cast<double>(i + 1) /
     178           9 :                                     static_cast<int>(m_filename.size()),
     179             :                                 pfnProgress, pProgressData),
     180           9 :                             GDALDestroyScaledProgress);
     181          18 :         ret = ret && Process(osPath.c_str(), nullptr,
     182           9 :                              pScaledProgress ? GDALScaledProgress : nullptr,
     183             :                              pScaledProgress.get());
     184           9 :         ++i;
     185             :     }
     186           8 :     if (m_format == "json")
     187           6 :         m_oWriter.EndArray();
     188             : 
     189           8 :     return ret;
     190             : }
     191             : 
     192             : //! @endcond

Generated by: LCOV version 1.14