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

Generated by: LCOV version 1.14