LCOV - code coverage report
Current view: top level - apps - gdalalg_mdim_pipeline.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 66 120 55.0 %
Date: 2026-06-23 16:35:19 Functions: 5 5 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  GDAL
       4             :  * Purpose:  gdal "mdim pipeline" subcommand
       5             :  * Author:   Even Rouault <even dot rouault at spatialys.com>
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2026, Even Rouault <even dot rouault at spatialys.com>
       9             :  *
      10             :  * SPDX-License-Identifier: MIT
      11             :  ****************************************************************************/
      12             : 
      13             : #include "gdalalg_mdim_pipeline.h"
      14             : #include "gdalalg_mdim_compare.h"
      15             : #include "gdalalg_mdim_read.h"
      16             : #include "gdalalg_mdim_write.h"
      17             : #include "gdalalg_mdim_info.h"
      18             : #include "gdalalg_mdim_mosaic.h"
      19             : #include "gdalalg_mdim_reproject.h"
      20             : 
      21             : #include "cpl_conv.h"
      22             : #include "cpl_progress.h"
      23             : #include "cpl_string.h"
      24             : #include "cpl_vsi.h"
      25             : #include "gdal_priv.h"
      26             : #include "gdal_utils.h"
      27             : 
      28             : #include <algorithm>
      29             : #include <array>
      30             : #include <cassert>
      31             : 
      32             : //! @cond Doxygen_Suppress
      33             : 
      34             : #ifndef _
      35             : #define _(x) (x)
      36             : #endif
      37             : 
      38             : GDALMdimAlgorithmStepRegistry::~GDALMdimAlgorithmStepRegistry() = default;
      39             : 
      40             : /************************************************************************/
      41             : /*    GDALMdimPipelineStepAlgorithm::GDALMdimPipelineStepAlgorithm()    */
      42             : /************************************************************************/
      43             : 
      44         306 : GDALMdimPipelineStepAlgorithm::GDALMdimPipelineStepAlgorithm(
      45             :     const std::string &name, const std::string &description,
      46         306 :     const std::string &helpURL, const ConstructorOptions &options)
      47         306 :     : GDALPipelineStepAlgorithm(name, description, helpURL, options)
      48             : {
      49         306 :     if (m_standaloneStep)
      50             :     {
      51         284 :         m_supportsStreamedOutput = true;
      52             : 
      53         284 :         if (m_constructorOptions.addDefaultArguments)
      54             :         {
      55          44 :             AddMdimInputArgs(false, false, /* acceptRaster = */ false);
      56          44 :             AddProgressArg();
      57          44 :             AddMdimOutputArgs(false);
      58             :         }
      59             :     }
      60          22 :     else if (m_constructorOptions.addDefaultArguments)
      61             :     {
      62           8 :         AddMdimHiddenInputDatasetArg();
      63             :     }
      64         306 : }
      65             : 
      66             : GDALMdimPipelineStepAlgorithm::~GDALMdimPipelineStepAlgorithm() = default;
      67             : 
      68             : /************************************************************************/
      69             : /*        GDALMdimPipelineAlgorithm::GDALMdimPipelineAlgorithm()        */
      70             : /************************************************************************/
      71             : 
      72          53 : GDALMdimPipelineAlgorithm::GDALMdimPipelineAlgorithm(
      73          53 :     bool openForMixedMdimVector)
      74             :     : GDALAbstractPipelineAlgorithm(NAME, DESCRIPTION, HELP_URL,
      75           0 :                                     ConstructorOptions()
      76          53 :                                         .SetAddDefaultArguments(false)
      77          53 :                                         .SetInputDatasetRequired(false)
      78          53 :                                         .SetInputDatasetPositional(false)
      79         106 :                                         .SetInputDatasetMaxCount(INT_MAX))
      80             : {
      81          53 :     m_supportsStreamedOutput = true;
      82             : 
      83          53 :     AddMdimInputArgs(openForMixedMdimVector, /* hiddenForCLI = */ true,
      84             :                      /* acceptRaster = */ false);
      85          53 :     AddProgressArg();
      86         106 :     AddArg("pipeline", 0, _("Pipeline string"), &m_pipeline)
      87          53 :         .SetHiddenForCLI()
      88          53 :         .SetPositional();
      89          53 :     AddMdimOutputArgs(/* hiddenForCLI = */ true);
      90             : 
      91          53 :     AddOutputStringArg(&m_output).SetHiddenForCLI();
      92          53 :     AddStdoutArg(&m_stdout);
      93             : 
      94          53 :     RegisterAlgorithms(m_stepRegistry, false);
      95          53 : }
      96             : 
      97             : /************************************************************************/
      98             : /*           GDALMdimPipelineAlgorithm::RegisterAlgorithms()            */
      99             : /************************************************************************/
     100             : 
     101             : /* static */
     102          53 : void GDALMdimPipelineAlgorithm::RegisterAlgorithms(
     103             :     GDALMdimAlgorithmStepRegistry &registry, bool forMixedPipeline)
     104             : {
     105          53 :     GDALAlgorithmRegistry::AlgInfo algInfo;
     106             : 
     107             :     const auto addSuffixIfNeeded =
     108         318 :         [forMixedPipeline](const char *name) -> std::string
     109             :     {
     110         318 :         return forMixedPipeline ? std::string(name).append(MULTIDIM_SUFFIX)
     111         636 :                                 : std::string(name);
     112          53 :     };
     113             : 
     114          53 :     registry.Register<GDALMdimReadAlgorithm>(
     115         106 :         addSuffixIfNeeded(GDALMdimReadAlgorithm::NAME));
     116             : 
     117          53 :     registry.Register<GDALMdimMosaicAlgorithm>(
     118         106 :         addSuffixIfNeeded(GDALMdimMosaicAlgorithm::NAME));
     119             : 
     120          53 :     registry.Register<GDALMdimCompareAlgorithm>(
     121         106 :         addSuffixIfNeeded(GDALMdimCompareAlgorithm::NAME));
     122             : 
     123          53 :     registry.Register<GDALMdimWriteAlgorithm>(
     124         106 :         addSuffixIfNeeded(GDALMdimWriteAlgorithm::NAME));
     125             : 
     126          53 :     registry.Register<GDALMdimInfoAlgorithm>(
     127         106 :         addSuffixIfNeeded(GDALMdimInfoAlgorithm::NAME));
     128             : 
     129          53 :     registry.Register<GDALMdimReprojectAlgorithm>(
     130         106 :         addSuffixIfNeeded(GDALMdimReprojectAlgorithm::NAME));
     131          53 : }
     132             : 
     133             : /************************************************************************/
     134             : /*             GDALMdimPipelineAlgorithm::GetUsageForCLI()              */
     135             : /************************************************************************/
     136             : 
     137           3 : std::string GDALMdimPipelineAlgorithm::GetUsageForCLI(
     138             :     bool shortUsage, const UsageOptions &usageOptions) const
     139             : {
     140           3 :     UsageOptions stepUsageOptions;
     141           3 :     stepUsageOptions.isPipelineStep = true;
     142             : 
     143           3 :     if (!m_helpDocCategory.empty() && m_helpDocCategory != "main")
     144             :     {
     145           4 :         auto alg = GetStepAlg(m_helpDocCategory);
     146           2 :         if (alg)
     147             :         {
     148           2 :             alg->SetCallPath({m_helpDocCategory});
     149           1 :             alg->GetArg("help-doc")->Set(true);
     150           1 :             return alg->GetUsageForCLI(shortUsage, stepUsageOptions);
     151             :         }
     152             :         else
     153             :         {
     154           1 :             fprintf(stderr, "ERROR: unknown pipeline step '%s'\n",
     155             :                     m_helpDocCategory.c_str());
     156             :             return CPLSPrintf("ERROR: unknown pipeline step '%s'\n",
     157           1 :                               m_helpDocCategory.c_str());
     158             :         }
     159             :     }
     160             : 
     161           1 :     UsageOptions usageOptionsMain(usageOptions);
     162           1 :     usageOptionsMain.isPipelineMain = true;
     163             :     std::string ret =
     164           2 :         GDALAlgorithm::GetUsageForCLI(shortUsage, usageOptionsMain);
     165           1 :     if (shortUsage)
     166           0 :         return ret;
     167             : 
     168             :     ret += "\n<PIPELINE> is of the form: read|mosaic [READ-OPTIONS] "
     169             :            "( ! <STEP-NAME> [STEP-OPTIONS] )* ! info|write "
     170           1 :            "[WRITE-OPTIONS]\n";
     171             : 
     172           1 :     if (m_helpDocCategory == "main")
     173             :     {
     174           1 :         return ret;
     175             :     }
     176             : 
     177           0 :     ret += '\n';
     178           0 :     ret += "Example: 'gdal mdim pipeline --progress ! read in.nc ! \\\n";
     179           0 :     ret += "               reproject --output-crs=EPSG:32632 ! ";
     180           0 :     ret += "write out.nc --overwrite'\n";
     181           0 :     ret += '\n';
     182           0 :     ret += "Potential steps are:\n";
     183             : 
     184           0 :     for (const std::string &name : m_stepRegistry.GetNames())
     185             :     {
     186           0 :         auto alg = GetStepAlg(name);
     187           0 :         auto [options, maxOptLen] = alg->GetArgNamesForCLI();
     188           0 :         stepUsageOptions.maxOptLen =
     189           0 :             std::max(stepUsageOptions.maxOptLen, maxOptLen);
     190             :     }
     191             : 
     192             :     {
     193           0 :         const auto name = GDALMdimReadAlgorithm::NAME;
     194           0 :         ret += '\n';
     195           0 :         auto alg = GetStepAlg(name);
     196           0 :         alg->SetCallPath({name});
     197           0 :         ret += alg->GetUsageForCLI(shortUsage, stepUsageOptions);
     198             :     }
     199             :     {
     200           0 :         const auto name = GDALMdimMosaicAlgorithm::NAME;
     201           0 :         ret += '\n';
     202           0 :         auto alg = GetStepAlg(name);
     203           0 :         alg->SetCallPath({name});
     204           0 :         ret += alg->GetUsageForCLI(shortUsage, stepUsageOptions);
     205             :     }
     206           0 :     for (const std::string &name : m_stepRegistry.GetNames())
     207             :     {
     208           0 :         auto alg = GetStepAlg(name);
     209           0 :         assert(alg);
     210           0 :         if (alg->CanBeFirstStep() && !alg->CanBeMiddleStep() &&
     211           0 :             !alg->IsHidden() && name != GDALMdimReadAlgorithm::NAME &&
     212           0 :             name != GDALMdimMosaicAlgorithm::NAME)
     213             :         {
     214           0 :             ret += '\n';
     215           0 :             alg->SetCallPath({name});
     216           0 :             ret += alg->GetUsageForCLI(shortUsage, stepUsageOptions);
     217             :         }
     218             :     }
     219           0 :     for (const std::string &name : m_stepRegistry.GetNames())
     220             :     {
     221           0 :         auto alg = GetStepAlg(name);
     222           0 :         assert(alg);
     223           0 :         if (alg->CanBeMiddleStep() && !alg->IsHidden())
     224             :         {
     225           0 :             ret += '\n';
     226           0 :             alg->SetCallPath({name});
     227           0 :             ret += alg->GetUsageForCLI(shortUsage, stepUsageOptions);
     228             :         }
     229             :     }
     230           0 :     for (const std::string &name : m_stepRegistry.GetNames())
     231             :     {
     232           0 :         auto alg = GetStepAlg(name);
     233           0 :         assert(alg);
     234           0 :         if (alg->CanBeLastStep() && !alg->CanBeMiddleStep() &&
     235           0 :             !alg->IsHidden() && name != GDALMdimWriteAlgorithm::NAME)
     236             :         {
     237           0 :             ret += '\n';
     238           0 :             alg->SetCallPath({name});
     239           0 :             ret += alg->GetUsageForCLI(shortUsage, stepUsageOptions);
     240             :         }
     241             :     }
     242             :     {
     243           0 :         const auto name = GDALMdimWriteAlgorithm::NAME;
     244           0 :         ret += '\n';
     245           0 :         auto alg = GetStepAlg(name);
     246           0 :         alg->SetCallPath({name});
     247           0 :         ret += alg->GetUsageForCLI(shortUsage, stepUsageOptions);
     248             :     }
     249           0 :     ret += GetUsageForCLIEnd();
     250             : 
     251           0 :     return ret;
     252             : }
     253             : 
     254             : //! @endcond

Generated by: LCOV version 1.14