LCOV - code coverage report
Current view: top level - apps - gdalalg_main.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 60 72 83.3 %
Date: 2026-07-09 08:35:43 Functions: 4 4 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             : *
       3             : * Project:  GDAL
       4             : * Purpose:  gdal "main" command
       5             : * Author:   Even Rouault <even dot rouault at spatialys.com>
       6             : *
       7             : ******************************************************************************
       8             : * Copyright (c) 2024, Even Rouault <even dot rouault at spatialys.com>
       9             : *
      10             : * SPDX-License-Identifier: MIT
      11             : ****************************************************************************/
      12             : 
      13             : #include "gdalalg_main.h"
      14             : 
      15             : #include "gdal_priv.h"
      16             : 
      17             : #if !defined(_WIN32)
      18             : #include <unistd.h>
      19             : #endif
      20             : 
      21             : //! @cond Doxygen_Suppress
      22             : 
      23             : #ifndef _
      24             : #define _(x) (x)
      25             : #endif
      26             : 
      27             : /************************************************************************/
      28             : /*                GDALMainAlgorithm::GDALMainAlgorithm()                */
      29             : /************************************************************************/
      30             : 
      31         489 : GDALMainAlgorithm::GDALMainAlgorithm()
      32         489 :     : GDALAlgorithm(NAME, DESCRIPTION, HELP_URL)
      33             : {
      34        3912 :     for (const std::string &subAlgName :
      35        8313 :          GDALGlobalAlgorithmRegistry::GetSingleton().GetNames())
      36             :     {
      37             :         const auto pInfo =
      38        3912 :             GDALGlobalAlgorithmRegistry::GetSingleton().GetInfo(subAlgName);
      39        3912 :         if (pInfo)
      40        3912 :             RegisterSubAlgorithm(*pInfo);
      41             :     }
      42             : 
      43         978 :     SetCallPath({NAME});
      44             : 
      45         978 :     AddArg("version", 0, _("Display GDAL version and exit"), &m_version)
      46         489 :         .SetHiddenForAPI();
      47         489 :     AddArg("drivers", 0, _("Display driver list as JSON document"), &m_drivers);
      48             : 
      49         489 :     AddOutputStringArg(&m_output);
      50             : 
      51             :     m_longDescription = "'gdal <FILENAME>' can also be used as a shortcut for "
      52             :                         "'gdal info <FILENAME>'.\n"
      53             :                         "And 'gdal read <FILENAME> ! ...' as a shortcut for "
      54         489 :                         "'gdal pipeline <FILENAME> ! ...'.";
      55             : 
      56         489 :     SetDisplayInJSONUsage(false);
      57         489 : }
      58             : 
      59             : /************************************************************************/
      60             : /*            GDALMainAlgorithm::ParseCommandLineArguments()            */
      61             : /************************************************************************/
      62             : 
      63         274 : bool GDALMainAlgorithm::ParseCommandLineArguments(
      64             :     const std::vector<std::string> &args)
      65             : {
      66             :     // Detect shortest form of pipeline:
      67             :     // "gdal read in.tif ! .... ! write out.tif"
      68         274 :     if (args.size() >= 2 && args[0] == "read")
      69             :     {
      70             :         m_subAlg =
      71           1 :             GDALGlobalAlgorithmRegistry::GetSingleton().Instantiate("pipeline");
      72           1 :         if (m_subAlg)
      73             :         {
      74           1 :             if (IsCalledFromCommandLine())
      75           1 :                 m_subAlg->SetCalledFromCommandLine();
      76           1 :             bool ret = m_subAlg->ParseCommandLineArguments(args);
      77           1 :             if (ret)
      78             :             {
      79           0 :                 m_selectedSubAlg = &(m_subAlg->GetActualAlgorithm());
      80           0 :                 std::vector<std::string> callPath(m_callPath);
      81           0 :                 callPath.push_back("vector");
      82           0 :                 m_selectedSubAlg->SetCallPath(callPath);
      83           0 :                 return true;
      84             :             }
      85           1 :             else if (strstr(CPLGetLastErrorMsg(),
      86           1 :                             "has both raster and vector content"))
      87             :             {
      88           0 :                 m_showUsage = false;
      89           0 :                 return false;
      90             :             }
      91             :         }
      92             : 
      93           1 :         return false;
      94             :     }
      95         276 :     else if (args.size() == 1 && args[0].size() >= 2 && args[0][0] == '-' &&
      96           3 :              args[0][1] == '-')
      97             :     {
      98           3 :         return GDALAlgorithm::ParseCommandLineArguments(args);
      99             :     }
     100             : 
     101             :     // Generic case: "gdal {subcommand} arguments"
     102             :     // where subcommand is a known subcommand
     103         270 :     else if (args.size() >= 1)
     104             :     {
     105         269 :         const auto nCounter = CPLGetErrorCounter();
     106         269 :         if (InstantiateSubAlgorithm(args[0]))
     107         265 :             return GDALAlgorithm::ParseCommandLineArguments(args);
     108           5 :         if (CPLGetErrorCounter() == nCounter + 1 &&
     109           1 :             strstr(CPLGetLastErrorMsg(), "Do you mean"))
     110             :         {
     111           1 :             return false;
     112             :         }
     113             :     }
     114             : 
     115             :     // Otherwise check if that is the shortest form of "gdal read mydataset"
     116             :     // where "read" is omitted: "gdal in.tif"
     117             :     {
     118             :         VSIStatBufL sStat;
     119           8 :         std::vector<char> osResolvedFilename(2048);
     120           8 :         for (const auto &arg : args)
     121             :         {
     122           6 :             if (VSIStatL(arg.c_str(), &sStat) == 0
     123             : #if !defined(_WIN32)
     124           6 :                 || readlink(arg.c_str(), osResolvedFilename.data(),
     125             :                             osResolvedFilename.size()) != -1
     126             : #endif
     127             :             )
     128             :             {
     129             :                 m_subAlg =
     130           4 :                     GDALGlobalAlgorithmRegistry::GetSingleton().Instantiate(
     131           2 :                         "info");
     132           2 :                 if (m_subAlg)
     133             :                 {
     134           2 :                     bool ret = m_subAlg->ParseCommandLineArguments(args);
     135           2 :                     if (ret)
     136             :                     {
     137           2 :                         m_selectedSubAlg = &(m_subAlg->GetActualAlgorithm());
     138           2 :                         std::vector<std::string> callPath(m_callPath);
     139           2 :                         callPath.push_back(m_selectedSubAlg->GetArg("layer")
     140             :                                                ? "vector"
     141             :                                                : "raster");
     142           2 :                         m_selectedSubAlg->SetCallPath(callPath);
     143           2 :                         return true;
     144             :                     }
     145           0 :                     else if (strstr(CPLGetLastErrorMsg(),
     146           0 :                                     "has both raster and vector content"))
     147             :                     {
     148           0 :                         m_showUsage = false;
     149           0 :                         return false;
     150             :                     }
     151             :                 }
     152             :             }
     153             :         }
     154             : 
     155           2 :         return GDALAlgorithm::ParseCommandLineArguments(args);
     156             :     }
     157             : }
     158             : 
     159             : /************************************************************************/
     160             : /*                 GDALMainAlgorithm::GetUsageForCLI()                  */
     161             : /************************************************************************/
     162             : 
     163             : std::string
     164          24 : GDALMainAlgorithm::GetUsageForCLI(bool shortUsage,
     165             :                                   const UsageOptions &usageOptions) const
     166             : {
     167          24 :     if (m_selectedSubAlg)
     168          20 :         return m_selectedSubAlg->GetUsageForCLI(shortUsage, usageOptions);
     169           4 :     if (m_showUsage)
     170           4 :         return GDALAlgorithm::GetUsageForCLI(shortUsage, usageOptions);
     171           0 :     return std::string();
     172             : }
     173             : 
     174             : /************************************************************************/
     175             : /*                     GDALMainAlgorithm::RunImpl()                     */
     176             : /************************************************************************/
     177             : 
     178           1 : bool GDALMainAlgorithm::RunImpl(GDALProgressFunc, void *)
     179             : {
     180           1 :     if (m_drivers)
     181             :     {
     182           1 :         m_output = GDALPrintDriverList(GDAL_OF_KIND_MASK, true);
     183             :     }
     184           1 :     return true;
     185             : }
     186             : 
     187             : //! @endcond

Generated by: LCOV version 1.14