LCOV - code coverage report
Current view: top level - apps - gdalalg_mdim_pipeline.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 67 121 55.4 %
Date: 2026-09-11 05:09:32 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         356 : GDALMdimPipelineStepAlgorithm::GDALMdimPipelineStepAlgorithm(
      45             :     const std::string &name, const std::string &description,
      46         356 :     const std::string &helpURL, const ConstructorOptions &options)
      47         356 :     : GDALPipelineStepAlgorithm(name, description, helpURL, options)
      48             : {
      49         356 :     if (m_standaloneStep)
      50             :     {
      51         295 :         m_supportsStreamedOutput = true;
      52             : 
      53         295 :         if (m_constructorOptions.addDefaultArguments)
      54             :         {
      55          47 :             AddMdimInputArgs(false, false, /* acceptRaster = */ false);
      56          47 :             AddProgressArg();
      57          47 :             AddMdimOutputArgs(false);
      58             :         }
      59             :     }
      60          61 :     else if (m_constructorOptions.addDefaultArguments)
      61             :     {
      62          13 :         AddMdimHiddenInputDatasetArg();
      63             :     }
      64         356 : }
      65             : 
      66             : GDALMdimPipelineStepAlgorithm::~GDALMdimPipelineStepAlgorithm() = default;
      67             : 
      68             : /************************************************************************/
      69             : /*        GDALMdimPipelineAlgorithm::GDALMdimPipelineAlgorithm()        */
      70             : /************************************************************************/
      71             : 
      72          55 : GDALMdimPipelineAlgorithm::GDALMdimPipelineAlgorithm(
      73          55 :     bool openForMixedMdimVector)
      74             :     : GDALAbstractPipelineAlgorithm(
      75             :           NAME, DESCRIPTION, HELP_URL,
      76           0 :           ConstructorOptions()
      77          55 :               .SetAddDefaultArguments(false)
      78          55 :               .SetInputDatasetRequired(false)
      79          55 :               .SetInputDatasetPositional(false)
      80          55 :               .SetInputDatasetMaxCount(INT_MAX)
      81         110 :               .SetMdimOutputAcceptsClassicRaster(true))
      82             : {
      83          55 :     m_supportsStreamedOutput = true;
      84             : 
      85          55 :     AddMdimInputArgs(openForMixedMdimVector, /* hiddenForCLI = */ true,
      86             :                      /* acceptRaster = */ false);
      87          55 :     AddProgressArg();
      88         110 :     AddArg("pipeline", 0, _("Pipeline string"), &m_pipeline)
      89          55 :         .SetHiddenForCLI()
      90          55 :         .SetPositional();
      91          55 :     AddMdimOutputArgs(/* hiddenForCLI = */ true);
      92             : 
      93          55 :     AddOutputStringArg(&m_output).SetHiddenForCLI();
      94          55 :     AddStdoutArg(&m_stdout);
      95             : 
      96          55 :     RegisterAlgorithms(m_stepRegistry, false);
      97          55 : }
      98             : 
      99             : /************************************************************************/
     100             : /*           GDALMdimPipelineAlgorithm::RegisterAlgorithms()            */
     101             : /************************************************************************/
     102             : 
     103             : /* static */
     104          55 : void GDALMdimPipelineAlgorithm::RegisterAlgorithms(
     105             :     GDALMdimAlgorithmStepRegistry &registry, bool forMixedPipeline)
     106             : {
     107          55 :     GDALAlgorithmRegistry::AlgInfo algInfo;
     108             : 
     109             :     const auto addSuffixIfNeeded =
     110         330 :         [forMixedPipeline](const char *name) -> std::string
     111             :     {
     112         330 :         return forMixedPipeline ? std::string(name).append(MULTIDIM_SUFFIX)
     113         660 :                                 : std::string(name);
     114          55 :     };
     115             : 
     116          55 :     registry.Register<GDALMdimReadAlgorithm>(
     117         110 :         addSuffixIfNeeded(GDALMdimReadAlgorithm::NAME));
     118             : 
     119          55 :     registry.Register<GDALMdimMosaicAlgorithm>(
     120         110 :         addSuffixIfNeeded(GDALMdimMosaicAlgorithm::NAME));
     121             : 
     122          55 :     registry.Register<GDALMdimCompareAlgorithm>(
     123         110 :         addSuffixIfNeeded(GDALMdimCompareAlgorithm::NAME));
     124             : 
     125          55 :     registry.Register<GDALMdimWriteAlgorithm>(
     126         110 :         addSuffixIfNeeded(GDALMdimWriteAlgorithm::NAME));
     127             : 
     128          55 :     registry.Register<GDALMdimInfoAlgorithm>(
     129         110 :         addSuffixIfNeeded(GDALMdimInfoAlgorithm::NAME));
     130             : 
     131          55 :     registry.Register<GDALMdimReprojectAlgorithm>(
     132         110 :         addSuffixIfNeeded(GDALMdimReprojectAlgorithm::NAME));
     133          55 : }
     134             : 
     135             : /************************************************************************/
     136             : /*             GDALMdimPipelineAlgorithm::GetUsageForCLI()              */
     137             : /************************************************************************/
     138             : 
     139           3 : std::string GDALMdimPipelineAlgorithm::GetUsageForCLI(
     140             :     bool shortUsage, const UsageOptions &usageOptions) const
     141             : {
     142           3 :     UsageOptions stepUsageOptions;
     143           3 :     stepUsageOptions.isPipelineStep = true;
     144             : 
     145           3 :     if (!m_helpDocCategory.empty() && m_helpDocCategory != "main")
     146             :     {
     147           4 :         auto alg = GetStepAlg(m_helpDocCategory);
     148           2 :         if (alg)
     149             :         {
     150           2 :             alg->SetCallPath({m_helpDocCategory});
     151           1 :             alg->GetArg("help-doc")->Set(true);
     152           1 :             return alg->GetUsageForCLI(shortUsage, stepUsageOptions);
     153             :         }
     154             :         else
     155             :         {
     156           1 :             fprintf(stderr, "ERROR: unknown pipeline step '%s'\n",
     157             :                     m_helpDocCategory.c_str());
     158             :             return CPLSPrintf("ERROR: unknown pipeline step '%s'\n",
     159           1 :                               m_helpDocCategory.c_str());
     160             :         }
     161             :     }
     162             : 
     163           1 :     UsageOptions usageOptionsMain(usageOptions);
     164           1 :     usageOptionsMain.isPipelineMain = true;
     165             :     std::string ret =
     166           2 :         GDALAlgorithm::GetUsageForCLI(shortUsage, usageOptionsMain);
     167           1 :     if (shortUsage)
     168           0 :         return ret;
     169             : 
     170             :     ret += "\n<PIPELINE> is of the form: read|mosaic [READ-OPTIONS] "
     171             :            "( ! <STEP-NAME> [STEP-OPTIONS] )* ! info|write "
     172           1 :            "[WRITE-OPTIONS]\n";
     173             : 
     174           1 :     if (m_helpDocCategory == "main")
     175             :     {
     176           1 :         return ret;
     177             :     }
     178             : 
     179           0 :     ret += '\n';
     180           0 :     ret += "Example: 'gdal mdim pipeline --progress ! read in.nc ! \\\n";
     181           0 :     ret += "               reproject --output-crs=EPSG:32632 ! ";
     182           0 :     ret += "write out.nc --overwrite'\n";
     183           0 :     ret += '\n';
     184           0 :     ret += "Potential steps are:\n";
     185             : 
     186           0 :     for (const std::string &name : m_stepRegistry.GetNames())
     187             :     {
     188           0 :         auto alg = GetStepAlg(name);
     189           0 :         auto [options, maxOptLen] = alg->GetArgNamesForCLI();
     190           0 :         stepUsageOptions.maxOptLen =
     191           0 :             std::max(stepUsageOptions.maxOptLen, maxOptLen);
     192             :     }
     193             : 
     194             :     {
     195           0 :         const auto name = GDALMdimReadAlgorithm::NAME;
     196           0 :         ret += '\n';
     197           0 :         auto alg = GetStepAlg(name);
     198           0 :         alg->SetCallPath({name});
     199           0 :         ret += alg->GetUsageForCLI(shortUsage, stepUsageOptions);
     200             :     }
     201             :     {
     202           0 :         const auto name = GDALMdimMosaicAlgorithm::NAME;
     203           0 :         ret += '\n';
     204           0 :         auto alg = GetStepAlg(name);
     205           0 :         alg->SetCallPath({name});
     206           0 :         ret += alg->GetUsageForCLI(shortUsage, stepUsageOptions);
     207             :     }
     208           0 :     for (const std::string &name : m_stepRegistry.GetNames())
     209             :     {
     210           0 :         auto alg = GetStepAlg(name);
     211           0 :         assert(alg);
     212           0 :         if (alg->CanBeFirstStep() && !alg->CanBeMiddleStep() &&
     213           0 :             !alg->IsHidden() && name != GDALMdimReadAlgorithm::NAME &&
     214           0 :             name != GDALMdimMosaicAlgorithm::NAME)
     215             :         {
     216           0 :             ret += '\n';
     217           0 :             alg->SetCallPath({name});
     218           0 :             ret += alg->GetUsageForCLI(shortUsage, stepUsageOptions);
     219             :         }
     220             :     }
     221           0 :     for (const std::string &name : m_stepRegistry.GetNames())
     222             :     {
     223           0 :         auto alg = GetStepAlg(name);
     224           0 :         assert(alg);
     225           0 :         if (alg->CanBeMiddleStep() && !alg->IsHidden())
     226             :         {
     227           0 :             ret += '\n';
     228           0 :             alg->SetCallPath({name});
     229           0 :             ret += alg->GetUsageForCLI(shortUsage, stepUsageOptions);
     230             :         }
     231             :     }
     232           0 :     for (const std::string &name : m_stepRegistry.GetNames())
     233             :     {
     234           0 :         auto alg = GetStepAlg(name);
     235           0 :         assert(alg);
     236           0 :         if (alg->CanBeLastStep() && !alg->CanBeMiddleStep() &&
     237           0 :             !alg->IsHidden() && name != GDALMdimWriteAlgorithm::NAME)
     238             :         {
     239           0 :             ret += '\n';
     240           0 :             alg->SetCallPath({name});
     241           0 :             ret += alg->GetUsageForCLI(shortUsage, stepUsageOptions);
     242             :         }
     243             :     }
     244             :     {
     245           0 :         const auto name = GDALMdimWriteAlgorithm::NAME;
     246           0 :         ret += '\n';
     247           0 :         auto alg = GetStepAlg(name);
     248           0 :         alg->SetCallPath({name});
     249           0 :         ret += alg->GetUsageForCLI(shortUsage, stepUsageOptions);
     250             :     }
     251           0 :     ret += GetUsageForCLIEnd();
     252             : 
     253           0 :     return ret;
     254             : }
     255             : 
     256             : //! @endcond

Generated by: LCOV version 1.14