LCOV - code coverage report
Current view: top level - apps - gdalalg_pipeline.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 341 344 99.1 %
Date: 2026-03-10 09:22:28 Functions: 16 16 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  GDAL
       4             :  * Purpose:  gdal "pipeline" subcommand
       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             : //! @cond Doxygen_Suppress
      14             : 
      15             : #include "gdalalg_pipeline.h"
      16             : #include "cpl_error.h"
      17             : #include "gdal_priv.h"
      18             : 
      19             : #include "gdalalg_external.h"
      20             : 
      21             : #include "gdalalg_raster_read.h"
      22             : #include "gdalalg_raster_mosaic.h"
      23             : #include "gdalalg_raster_stack.h"
      24             : #include "gdalalg_raster_write.h"
      25             : #include "gdalalg_raster_zonal_stats.h"
      26             : 
      27             : #include "gdalalg_vector_read.h"
      28             : #include "gdalalg_vector_write.h"
      29             : 
      30             : #include "gdalalg_raster_as_features.h"
      31             : #include "gdalalg_raster_compare.h"
      32             : #include "gdalalg_raster_contour.h"
      33             : #include "gdalalg_raster_footprint.h"
      34             : #include "gdalalg_raster_polygonize.h"
      35             : #include "gdalalg_raster_info.h"
      36             : #include "gdalalg_raster_pixel_info.h"
      37             : #include "gdalalg_raster_tile.h"
      38             : #include "gdalalg_vector_grid.h"
      39             : #include "gdalalg_vector_info.h"
      40             : #include "gdalalg_vector_rasterize.h"
      41             : 
      42             : #include <algorithm>
      43             : #include <cassert>
      44             : 
      45             : #ifndef _
      46             : #define _(x) (x)
      47             : #endif
      48             : 
      49             : /************************************************************************/
      50             : /*                     GDALPipelineStepAlgorithm()                      */
      51             : /************************************************************************/
      52             : 
      53        9251 : GDALPipelineStepAlgorithm::GDALPipelineStepAlgorithm(
      54             :     const std::string &name, const std::string &description,
      55        9251 :     const std::string &helpURL, const ConstructorOptions &options)
      56             :     : GDALAlgorithm(name, description, helpURL),
      57        9251 :       m_standaloneStep(options.standaloneStep), m_constructorOptions(options)
      58             : {
      59        9251 : }
      60             : 
      61             : /************************************************************************/
      62             : /*     GDALPipelineStepAlgorithm::AddRasterHiddenInputDatasetArg()      */
      63             : /************************************************************************/
      64             : 
      65        2031 : void GDALPipelineStepAlgorithm::AddRasterHiddenInputDatasetArg()
      66             : {
      67        2031 :     AddInputDatasetArg(&m_inputDataset, GDAL_OF_RASTER, false)
      68        2031 :         .SetMinCount(0)
      69        2031 :         .SetMaxCount(m_constructorOptions.inputDatasetMaxCount)
      70        2031 :         .SetAutoOpenDataset(m_constructorOptions.autoOpenInputDatasets)
      71        2031 :         .SetMetaVar(m_constructorOptions.inputDatasetMetaVar)
      72        2031 :         .SetHidden();
      73        2031 : }
      74             : 
      75             : /************************************************************************/
      76             : /*           GDALPipelineStepAlgorithm::AddRasterInputArgs()            */
      77             : /************************************************************************/
      78             : 
      79        3063 : void GDALPipelineStepAlgorithm::AddRasterInputArgs(
      80             :     bool openForMixedRasterVector, bool hiddenForCLI)
      81             : {
      82        3063 :     AddInputFormatsArg(&m_inputFormats)
      83             :         .AddMetadataItem(
      84             :             GAAMDI_REQUIRED_CAPABILITIES,
      85             :             openForMixedRasterVector
      86        9379 :                 ? std::vector<std::string>{GDAL_DCAP_RASTER, GDAL_DCAP_VECTOR}
      87        8999 :                 : std::vector<std::string>{GDAL_DCAP_RASTER})
      88        3063 :         .SetHiddenForCLI(hiddenForCLI);
      89        3063 :     AddOpenOptionsArg(&m_openOptions).SetHiddenForCLI(hiddenForCLI);
      90             :     auto &arg =
      91             :         AddInputDatasetArg(
      92             :             &m_inputDataset,
      93             :             openForMixedRasterVector ? (GDAL_OF_RASTER | GDAL_OF_VECTOR)
      94             :                                      : GDAL_OF_RASTER,
      95        3063 :             false, m_constructorOptions.inputDatasetHelpMsg.c_str())
      96        3063 :             .SetMinCount(m_constructorOptions.inputDatasetRequired ? 1 : 0)
      97        3063 :             .SetMaxCount(m_constructorOptions.inputDatasetMaxCount)
      98        3063 :             .SetAutoOpenDataset(m_constructorOptions.autoOpenInputDatasets)
      99        3063 :             .SetMetaVar(m_constructorOptions.inputDatasetMetaVar)
     100        3063 :             .SetHiddenForCLI(hiddenForCLI);
     101        3063 :     if (m_constructorOptions.inputDatasetPositional && !hiddenForCLI)
     102        2818 :         arg.SetPositional();
     103        3063 :     if (m_constructorOptions.inputDatasetRequired && !hiddenForCLI)
     104        2818 :         arg.SetRequired();
     105        3063 :     if (!m_constructorOptions.inputDatasetAlias.empty())
     106         600 :         arg.AddAlias(m_constructorOptions.inputDatasetAlias);
     107        3063 : }
     108             : 
     109             : /************************************************************************/
     110             : /*           GDALPipelineStepAlgorithm::AddRasterOutputArgs()           */
     111             : /************************************************************************/
     112             : 
     113        1868 : void GDALPipelineStepAlgorithm::AddRasterOutputArgs(bool hiddenForCLI)
     114             : {
     115        1868 :     m_outputFormatArg =
     116             :         &(AddOutputFormatArg(&m_format, /* bStreamAllowed = */ true,
     117        1868 :                              /* bGDALGAllowed = */ true)
     118             :               .AddMetadataItem(
     119             :                   GAAMDI_REQUIRED_CAPABILITIES,
     120             :                   {GDAL_DCAP_RASTER,
     121        7472 :                    m_constructorOptions.outputFormatCreateCapability.c_str()})
     122        1868 :               .SetHiddenForCLI(hiddenForCLI));
     123             :     AddOutputDatasetArg(&m_outputDataset, GDAL_OF_RASTER,
     124        1868 :                         /* positionalAndRequired = */ !hiddenForCLI,
     125        1868 :                         m_constructorOptions.outputDatasetHelpMsg.c_str())
     126        1868 :         .SetHiddenForCLI(hiddenForCLI)
     127        1868 :         .SetDatasetInputFlags(GADV_NAME | GADV_OBJECT);
     128        1868 :     AddCreationOptionsArg(&m_creationOptions).SetHiddenForCLI(hiddenForCLI);
     129        1868 :     constexpr const char *MUTUAL_EXCLUSION_GROUP_OVERWRITE_APPEND =
     130             :         "overwrite-append";
     131        1868 :     AddOverwriteArg(&m_overwrite)
     132        1868 :         .SetHiddenForCLI(hiddenForCLI)
     133        1868 :         .SetMutualExclusionGroup(MUTUAL_EXCLUSION_GROUP_OVERWRITE_APPEND);
     134             :     AddArg(GDAL_ARG_NAME_APPEND, 0,
     135        3736 :            _("Append as a subdataset to existing output"), &m_appendRaster)
     136        1868 :         .SetDefault(false)
     137        1868 :         .SetHiddenForCLI(hiddenForCLI)
     138        1868 :         .SetMutualExclusionGroup(MUTUAL_EXCLUSION_GROUP_OVERWRITE_APPEND);
     139        1868 : }
     140             : 
     141             : /************************************************************************/
     142             : /*     GDALPipelineStepAlgorithm::AddVectorHiddenInputDatasetArg()      */
     143             : /************************************************************************/
     144             : 
     145        1703 : void GDALPipelineStepAlgorithm::AddVectorHiddenInputDatasetArg()
     146             : {
     147        1703 :     AddInputDatasetArg(&m_inputDataset, GDAL_OF_VECTOR, false)
     148        1703 :         .SetMinCount(0)
     149        1703 :         .SetMaxCount(m_constructorOptions.inputDatasetMaxCount)
     150        1703 :         .SetAutoOpenDataset(m_constructorOptions.autoOpenInputDatasets)
     151        1703 :         .SetMetaVar(m_constructorOptions.inputDatasetMetaVar)
     152        1703 :         .SetHidden();
     153        1703 : }
     154             : 
     155             : /************************************************************************/
     156             : /*           GDALPipelineStepAlgorithm::AddVectorInputArgs()            */
     157             : /************************************************************************/
     158             : 
     159        1259 : void GDALPipelineStepAlgorithm::AddVectorInputArgs(bool hiddenForCLI)
     160             : {
     161        1259 :     AddInputFormatsArg(&m_inputFormats)
     162        3777 :         .AddMetadataItem(GAAMDI_REQUIRED_CAPABILITIES, {GDAL_DCAP_VECTOR})
     163        1259 :         .SetHiddenForCLI(hiddenForCLI);
     164        1259 :     AddOpenOptionsArg(&m_openOptions).SetHiddenForCLI(hiddenForCLI);
     165             :     auto &datasetArg =
     166        1259 :         AddInputDatasetArg(&m_inputDataset, GDAL_OF_VECTOR, false)
     167        1259 :             .SetMinCount(m_constructorOptions.inputDatasetRequired ? 1 : 0)
     168        1259 :             .SetMaxCount(m_constructorOptions.inputDatasetMaxCount)
     169        1259 :             .SetAutoOpenDataset(m_constructorOptions.autoOpenInputDatasets)
     170        1259 :             .SetHiddenForCLI(hiddenForCLI);
     171        1259 :     if (m_constructorOptions.inputDatasetPositional && !hiddenForCLI)
     172        1155 :         datasetArg.SetPositional();
     173        1259 :     if (m_constructorOptions.inputDatasetRequired && !hiddenForCLI)
     174        1155 :         datasetArg.SetRequired();
     175        1259 :     if (m_constructorOptions.addInputLayerNameArgument)
     176             :     {
     177             :         auto &layerArg = AddArg(GDAL_ARG_NAME_INPUT_LAYER, 'l',
     178        2314 :                                 _("Input layer name(s)"), &m_inputLayerNames)
     179        2314 :                              .AddAlias("layer")
     180        1157 :                              .SetHiddenForCLI(hiddenForCLI);
     181        1157 :         SetAutoCompleteFunctionForLayerName(layerArg, datasetArg);
     182             :     }
     183        1259 : }
     184             : 
     185             : /************************************************************************/
     186             : /*           GDALPipelineStepAlgorithm::AddVectorOutputArgs()           */
     187             : /************************************************************************/
     188             : 
     189        1594 : void GDALPipelineStepAlgorithm::AddVectorOutputArgs(
     190             :     bool hiddenForCLI, bool shortNameOutputLayerAllowed)
     191             : {
     192             :     AddOutputFormatArg(&m_format, /* bStreamAllowed = */ true,
     193        1594 :                        /* bGDALGAllowed = */ true)
     194             :         .AddMetadataItem(GAAMDI_REQUIRED_CAPABILITIES,
     195        6376 :                          {GDAL_DCAP_VECTOR, GDAL_DCAP_CREATE})
     196        1594 :         .SetHiddenForCLI(hiddenForCLI);
     197        1594 :     AddOutputOpenOptionsArg(&m_outputOpenOptions).SetHiddenForCLI(hiddenForCLI);
     198             :     auto &outputDatasetArg =
     199             :         AddOutputDatasetArg(&m_outputDataset, GDAL_OF_VECTOR,
     200        1594 :                             /* positionalAndRequired = */ false)
     201        1594 :             .SetHiddenForCLI(hiddenForCLI)
     202        1594 :             .SetDatasetInputFlags(GADV_NAME | GADV_OBJECT);
     203        1594 :     if (!hiddenForCLI)
     204        1490 :         outputDatasetArg.SetPositional();
     205        1594 :     if (!hiddenForCLI && m_constructorOptions.outputDatasetRequired)
     206        1468 :         outputDatasetArg.SetRequired();
     207             : 
     208        1594 :     AddCreationOptionsArg(&m_creationOptions).SetHiddenForCLI(hiddenForCLI);
     209        1594 :     AddLayerCreationOptionsArg(&m_layerCreationOptions)
     210        1594 :         .SetHiddenForCLI(hiddenForCLI);
     211        1594 :     AddOverwriteArg(&m_overwrite).SetHiddenForCLI(hiddenForCLI);
     212        1594 :     GDALInConstructionAlgorithmArg *updateArg = nullptr;
     213        1594 :     if (m_constructorOptions.addUpdateArgument)
     214             :     {
     215        1567 :         updateArg = &AddUpdateArg(&m_update).SetHiddenForCLI(hiddenForCLI);
     216             :     }
     217        1594 :     if (m_constructorOptions.addOverwriteLayerArgument)
     218             :     {
     219        1567 :         AddOverwriteLayerArg(&m_overwriteLayer).SetHiddenForCLI(hiddenForCLI);
     220             :     }
     221        1594 :     constexpr const char *MUTUAL_EXCLUSION_GROUP_APPEND_UPSERT =
     222             :         "append-upsert";
     223        1594 :     if (m_constructorOptions.addAppendLayerArgument)
     224             :     {
     225        1567 :         AddAppendLayerArg(&m_appendLayer)
     226        1567 :             .SetHiddenForCLI(hiddenForCLI)
     227        1567 :             .SetMutualExclusionGroup(MUTUAL_EXCLUSION_GROUP_APPEND_UPSERT);
     228             :     }
     229        1594 :     if (m_constructorOptions.addUpsertArgument)
     230             :     {
     231        3026 :         AddArg("upsert", 0, _("Upsert features (implies 'append')"), &m_upsert)
     232        1513 :             .SetHiddenForCLI(hiddenForCLI)
     233        3026 :             .SetMutualExclusionGroup(MUTUAL_EXCLUSION_GROUP_APPEND_UPSERT)
     234             :             .AddAction(
     235          12 :                 [updateArg, this]()
     236             :                 {
     237           4 :                     if (m_upsert && updateArg)
     238           4 :                         updateArg->Set(true);
     239        3026 :                 })
     240        1513 :             .SetCategory(GAAC_ADVANCED);
     241             :     }
     242        1594 :     if (m_constructorOptions.addOutputLayerNameArgument)
     243             :     {
     244        1538 :         AddOutputLayerNameArg(hiddenForCLI, shortNameOutputLayerAllowed);
     245             :     }
     246        1594 :     if (m_constructorOptions.addSkipErrorsArgument)
     247             :     {
     248             :         AddArg("skip-errors", 0, _("Skip errors when writing features"),
     249        3026 :                &m_skipErrors)
     250        1513 :             .AddHiddenAlias("skip-failures");  // For ogr2ogr nostalgic people
     251             :     }
     252        1594 :     if (m_constructorOptions.addNoCreateEmptyLayersArgument)
     253             :     {
     254             :         AddArg("no-create-empty-layers", 0,
     255             :                _("Avoid creating layers to which no features will be written"),
     256         805 :                &m_noCreateEmptyLayers);
     257             :     }
     258        1594 : }
     259             : 
     260             : /************************************************************************/
     261             : /*          GDALPipelineStepAlgorithm::AddOutputLayerNameArg()          */
     262             : /************************************************************************/
     263             : 
     264        1628 : void GDALPipelineStepAlgorithm::AddOutputLayerNameArg(
     265             :     bool hiddenForCLI, bool shortNameOutputLayerAllowed)
     266             : {
     267             :     AddArg(GDAL_ARG_NAME_OUTPUT_LAYER, shortNameOutputLayerAllowed ? 'l' : 0,
     268             :            _("Output layer name"),
     269        3256 :            &m_outputLayerName)
     270        3256 :         .AddHiddenAlias("nln")  // For ogr2ogr nostalgic people
     271        1628 :         .SetHiddenForCLI(hiddenForCLI);
     272        1628 : }
     273             : 
     274             : /************************************************************************/
     275             : /*                 GDALPipelineStepAlgorithm::RunImpl()                 */
     276             : /************************************************************************/
     277             : 
     278        2411 : bool GDALPipelineStepAlgorithm::RunImpl(GDALProgressFunc pfnProgress,
     279             :                                         void *pProgressData)
     280             : {
     281        2411 :     if (m_standaloneStep)
     282             :     {
     283        1039 :         std::unique_ptr<GDALPipelineStepAlgorithm> readAlg;
     284        1039 :         if (GetInputType() == GDAL_OF_RASTER)
     285         695 :             readAlg = std::make_unique<GDALRasterReadAlgorithm>();
     286             :         else
     287         344 :             readAlg = std::make_unique<GDALVectorReadAlgorithm>();
     288        8656 :         for (auto &arg : readAlg->GetArgs())
     289             :         {
     290        7617 :             auto stepArg = GetArg(arg->GetName());
     291        8668 :             if (stepArg && stepArg->IsExplicitlySet() &&
     292        1051 :                 stepArg->GetType() == arg->GetType())
     293             :             {
     294        1051 :                 arg->SetSkipIfAlreadySet(true);
     295        1051 :                 arg->SetFrom(*stepArg);
     296             :             }
     297             :         }
     298             : 
     299           0 :         std::unique_ptr<GDALPipelineStepAlgorithm> writeAlg;
     300        1039 :         if (GetOutputType() == GDAL_OF_RASTER)
     301             :         {
     302         480 :             if (GetName() == GDALRasterInfoAlgorithm::NAME)
     303          25 :                 writeAlg = std::make_unique<GDALRasterInfoAlgorithm>();
     304         455 :             else if (GetName() == GDALRasterCompareAlgorithm::NAME)
     305           0 :                 writeAlg = std::make_unique<GDALRasterCompareAlgorithm>();
     306             :             else
     307         455 :                 writeAlg = std::make_unique<GDALRasterWriteAlgorithm>();
     308             :         }
     309             :         else
     310             :         {
     311         559 :             if (GetName() == GDALVectorInfoAlgorithm::NAME)
     312          27 :                 writeAlg = std::make_unique<GDALVectorInfoAlgorithm>();
     313             :             else
     314         532 :                 writeAlg = std::make_unique<GDALVectorWriteAlgorithm>();
     315             :         }
     316       16201 :         for (auto &arg : writeAlg->GetArgs())
     317             :         {
     318       15162 :             auto stepArg = GetArg(arg->GetName());
     319       17755 :             if (stepArg && stepArg->IsExplicitlySet() &&
     320        2593 :                 stepArg->GetType() == arg->GetType())
     321             :             {
     322        2590 :                 arg->SetSkipIfAlreadySet(true);
     323        2590 :                 arg->SetFrom(*stepArg);
     324             :             }
     325             :         }
     326             : 
     327        1039 :         const bool bIsStreaming = m_format == "stream";
     328             : 
     329             :         // Already checked by GDALAlgorithm::Run()
     330        1039 :         CPLAssert(!m_executionForStreamOutput || bIsStreaming);
     331             : 
     332        1039 :         bool ret = false;
     333        1095 :         if (!m_outputVRTCompatible &&
     334         112 :             (EQUAL(m_format.c_str(), "VRT") ||
     335          56 :              (m_format.empty() &&
     336        1040 :               EQUAL(CPLGetExtensionSafe(m_outputDataset.GetName().c_str())
     337             :                         .c_str(),
     338             :                     "VRT"))))
     339             :         {
     340           0 :             ReportError(CE_Failure, CPLE_NotSupported,
     341             :                         "VRT output is not supported. Consider using the "
     342             :                         "GDALG driver instead (files with .gdalg.json "
     343             :                         "extension)");
     344             :         }
     345        1039 :         else if (readAlg->Run())
     346             :         {
     347        1035 :             auto outputArg = GetArg(GDAL_ARG_NAME_OUTPUT);
     348             :             const bool bOutputSpecified =
     349        1035 :                 outputArg && outputArg->IsExplicitlySet();
     350             : 
     351        1035 :             m_inputDataset.clear();
     352        1035 :             m_inputDataset.resize(1);
     353        1035 :             m_inputDataset[0].Set(readAlg->m_outputDataset.GetDatasetRef());
     354        1035 :             if (bOutputSpecified)
     355         780 :                 m_outputDataset.Set(nullptr);
     356             : 
     357             :             std::unique_ptr<void, decltype(&GDALDestroyScaledProgress)>
     358        2070 :                 pScaledData(nullptr, GDALDestroyScaledProgress);
     359             : 
     360             :             const bool bCanHandleNextStep =
     361        1035 :                 !bIsStreaming && CanHandleNextStep(writeAlg.get());
     362             : 
     363        1035 :             GDALPipelineStepRunContext stepCtxt;
     364        1035 :             if (pfnProgress && GetName() == GDALRasterCompareAlgorithm::NAME)
     365             :             {
     366           5 :                 stepCtxt.m_pfnProgress = pfnProgress;
     367           5 :                 stepCtxt.m_pProgressData = pProgressData;
     368             :             }
     369        1072 :             else if (pfnProgress &&
     370          42 :                      (bCanHandleNextStep || !IsNativelyStreamingCompatible()))
     371             :             {
     372          44 :                 pScaledData.reset(GDALCreateScaledProgress(
     373          18 :                     0.0, bIsStreaming || bCanHandleNextStep ? 1.0 : 0.5,
     374             :                     pfnProgress, pProgressData));
     375          26 :                 stepCtxt.m_pfnProgress =
     376          26 :                     pScaledData ? GDALScaledProgress : nullptr;
     377          26 :                 stepCtxt.m_pProgressData = pScaledData.get();
     378             :             }
     379             : 
     380        1035 :             if (bCanHandleNextStep)
     381          47 :                 stepCtxt.m_poNextUsableStep = writeAlg.get();
     382        1035 :             if (RunPreStepPipelineValidations() && RunStep(stepCtxt))
     383             :             {
     384         952 :                 if (bCanHandleNextStep || !bOutputSpecified)
     385             :                 {
     386         291 :                     ret = true;
     387             :                 }
     388             :                 else
     389             :                 {
     390         661 :                     writeAlg->m_outputVRTCompatible = m_outputVRTCompatible;
     391             : 
     392        1322 :                     std::vector<GDALArgDatasetValue> inputDataset(1);
     393         661 :                     inputDataset[0].Set(m_outputDataset.GetDatasetRef());
     394         661 :                     auto inputArg = writeAlg->GetArg(GDAL_ARG_NAME_INPUT);
     395         661 :                     CPLAssert(inputArg);
     396         661 :                     inputArg->Set(std::move(inputDataset));
     397             : 
     398         661 :                     if (pfnProgress)
     399             :                     {
     400          33 :                         pScaledData.reset(GDALCreateScaledProgress(
     401          33 :                             IsNativelyStreamingCompatible() ? 0.0 : 0.5, 1.0,
     402             :                             pfnProgress, pProgressData));
     403             :                     }
     404         661 :                     stepCtxt.m_pfnProgress =
     405         661 :                         pScaledData ? GDALScaledProgress : nullptr;
     406         661 :                     stepCtxt.m_pProgressData = pScaledData.get();
     407        1322 :                     if (writeAlg->ValidateArguments() &&
     408         661 :                         writeAlg->RunStep(stepCtxt))
     409             :                     {
     410         643 :                         if (pfnProgress)
     411          32 :                             pfnProgress(1.0, "", pProgressData);
     412             : 
     413         643 :                         m_outputDataset.Set(
     414         643 :                             writeAlg->m_outputDataset.GetDatasetRef());
     415         643 :                         ret = true;
     416             :                     }
     417             :                 }
     418             :             }
     419             :         }
     420             : 
     421        1039 :         return ret;
     422             :     }
     423             :     else
     424             :     {
     425        1372 :         GDALPipelineStepRunContext stepCtxt;
     426        1372 :         stepCtxt.m_pfnProgress = pfnProgress;
     427        1372 :         stepCtxt.m_pProgressData = pProgressData;
     428        1372 :         return RunPreStepPipelineValidations() && RunStep(stepCtxt);
     429             :     }
     430             : }
     431             : 
     432             : /************************************************************************/
     433             : /*                          SetInputDataset()                           */
     434             : /************************************************************************/
     435             : 
     436          11 : void GDALPipelineStepAlgorithm::SetInputDataset(GDALDataset *poDS)
     437             : {
     438          11 :     auto arg = GetArg(GDAL_ARG_NAME_INPUT);
     439          11 :     if (arg)
     440             :     {
     441          11 :         auto &val = arg->Get<std::vector<GDALArgDatasetValue>>();
     442          11 :         val.resize(1);
     443          11 :         val[0].Set(poDS);
     444          11 :         arg->NotifyValueSet();
     445          11 :         arg->SetSkipIfAlreadySet();
     446             :     }
     447          11 : }
     448             : 
     449             : /************************************************************************/
     450             : /*                         ProcessGDALGOutput()                         */
     451             : /************************************************************************/
     452             : 
     453             : GDALAlgorithm::ProcessGDALGOutputRet
     454        3311 : GDALPipelineStepAlgorithm::ProcessGDALGOutput()
     455             : {
     456        3311 :     if (m_standaloneStep)
     457             :     {
     458        1881 :         return GDALAlgorithm::ProcessGDALGOutput();
     459             :     }
     460             :     else
     461             :     {
     462             :         // GDALAbstractPipelineAlgorithm<StepAlgorithm>::RunStep() might
     463             :         // actually detect a GDALG output request and process it.
     464        1430 :         return GDALAlgorithm::ProcessGDALGOutputRet::NOT_GDALG;
     465             :     }
     466             : }
     467             : 
     468             : /************************************************************************/
     469             : /*        GDALPipelineStepAlgorithm::CheckSafeForStreamOutput()         */
     470             : /************************************************************************/
     471             : 
     472          80 : bool GDALPipelineStepAlgorithm::CheckSafeForStreamOutput()
     473             : {
     474          80 :     if (m_standaloneStep)
     475             :     {
     476          35 :         return GDALAlgorithm::CheckSafeForStreamOutput();
     477             :     }
     478             :     else
     479             :     {
     480             :         // The check is actually done in
     481             :         // GDALAbstractPipelineAlgorithm<StepAlgorithm>::RunStep()
     482             :         // so return true for now.
     483          45 :         return true;
     484             :     }
     485             : }
     486             : 
     487             : /************************************************************************/
     488             : /*                GDALPipelineStepAlgorithm::Finalize()                 */
     489             : /************************************************************************/
     490             : 
     491        1229 : bool GDALPipelineStepAlgorithm::Finalize()
     492             : {
     493        1229 :     bool ret = GDALAlgorithm::Finalize();
     494        2303 :     for (auto &argValue : m_inputDataset)
     495        1074 :         ret = argValue.Close() && ret;
     496        1229 :     ret = m_outputDataset.Close() && ret;
     497        1229 :     return ret;
     498             : }
     499             : 
     500             : GDALAlgorithmStepRegistry::~GDALAlgorithmStepRegistry() = default;
     501             : 
     502             : /************************************************************************/
     503             : /*                        GDALPipelineAlgorithm                         */
     504             : /************************************************************************/
     505             : 
     506         225 : GDALPipelineAlgorithm::GDALPipelineAlgorithm()
     507             :     : GDALAbstractPipelineAlgorithm(
     508             :           NAME, DESCRIPTION, HELP_URL,
     509         225 :           ConstructorOptions().SetStandaloneStep(false))
     510             : {
     511         225 :     m_supportsStreamedOutput = true;
     512             : 
     513         225 :     AddProgressArg();
     514             :     AddInputDatasetArg(&m_inputDataset, GDAL_OF_RASTER | GDAL_OF_VECTOR,
     515         225 :                        /* positionalAndRequired = */ false)
     516         225 :         .SetMinCount(1)
     517         225 :         .SetMaxCount(INT_MAX)
     518         225 :         .SetHiddenForCLI();
     519             :     AddOutputDatasetArg(&m_outputDataset, GDAL_OF_RASTER | GDAL_OF_VECTOR,
     520         225 :                         /* positionalAndRequired = */ false)
     521         225 :         .SetHiddenForCLI()
     522         225 :         .SetDatasetInputFlags(GADV_NAME | GADV_OBJECT);
     523             :     AddOutputFormatArg(&m_format, /* bStreamAllowed = */ true,
     524         225 :                        /* bGDALGAllowed = */ true)
     525         225 :         .SetHiddenForCLI();
     526         450 :     AddArg("pipeline", 0, _("Pipeline string or filename"), &m_pipeline)
     527         225 :         .SetHiddenForCLI()
     528         225 :         .SetPositional();
     529             : 
     530         225 :     AddOutputStringArg(&m_output).SetHiddenForCLI();
     531         225 :     AddStdoutArg(&m_stdout);
     532             : 
     533         225 :     AllowArbitraryLongNameArgs();
     534             : 
     535         225 :     GDALRasterPipelineAlgorithm::RegisterAlgorithms(m_stepRegistry, true);
     536         225 :     GDALVectorPipelineAlgorithm::RegisterAlgorithms(m_stepRegistry, true);
     537         225 :     m_stepRegistry.Register<GDALExternalRasterOrVectorAlgorithm>();
     538         225 :     m_stepRegistry.Register<GDALRasterAsFeaturesAlgorithm>();
     539         225 :     m_stepRegistry.Register<GDALRasterContourAlgorithm>();
     540         225 :     m_stepRegistry.Register<GDALRasterFootprintAlgorithm>();
     541         225 :     m_stepRegistry.Register<GDALRasterPixelInfoAlgorithm>();
     542         225 :     m_stepRegistry.Register<GDALRasterPolygonizeAlgorithm>();
     543         225 :     m_stepRegistry.Register<GDALRasterZonalStatsAlgorithm>();
     544         225 :     m_stepRegistry.Register<GDALVectorGridAlgorithm>();
     545         225 :     m_stepRegistry.Register<GDALVectorRasterizeAlgorithm>();
     546         225 : }
     547             : 
     548             : /************************************************************************/
     549             : /*               GDALPipelineAlgorithm::GetUsageForCLI()                */
     550             : /************************************************************************/
     551             : 
     552             : std::string
     553          18 : GDALPipelineAlgorithm::GetUsageForCLI(bool shortUsage,
     554             :                                       const UsageOptions &usageOptions) const
     555             : {
     556          18 :     UsageOptions stepUsageOptions;
     557          18 :     stepUsageOptions.isPipelineStep = true;
     558             : 
     559          18 :     if (!m_helpDocCategory.empty() && m_helpDocCategory != "main")
     560             :     {
     561           4 :         auto alg = GetStepAlg(m_helpDocCategory);
     562           2 :         if (alg)
     563             :         {
     564           3 :             alg->SetCallPath({CPLString(m_helpDocCategory)
     565           2 :                                   .replaceAll(RASTER_SUFFIX, "")
     566           3 :                                   .replaceAll(VECTOR_SUFFIX, "")});
     567           1 :             alg->GetArg("help-doc")->Set(true);
     568           1 :             return alg->GetUsageForCLI(shortUsage, stepUsageOptions);
     569             :         }
     570             :         else
     571             :         {
     572           1 :             fprintf(stderr, "ERROR: unknown pipeline step '%s'\n",
     573             :                     m_helpDocCategory.c_str());
     574             :             return CPLSPrintf("ERROR: unknown pipeline step '%s'\n",
     575           1 :                               m_helpDocCategory.c_str());
     576             :         }
     577             :     }
     578             : 
     579          16 :     UsageOptions usageOptionsMain(usageOptions);
     580          16 :     usageOptionsMain.isPipelineMain = true;
     581             :     std::string ret =
     582          32 :         GDALAlgorithm::GetUsageForCLI(shortUsage, usageOptionsMain);
     583          16 :     if (shortUsage)
     584          14 :         return ret;
     585             : 
     586             :     ret +=
     587             :         "\n<PIPELINE> is of the form: read|calc|concat|create|mosaic|stack "
     588             :         "[READ-OPTIONS] "
     589           2 :         "( ! <STEP-NAME> [STEP-OPTIONS] )* ! write!info!tile [WRITE-OPTIONS]\n";
     590             : 
     591           2 :     if (m_helpDocCategory == "main")
     592             :     {
     593           1 :         return ret;
     594             :     }
     595             : 
     596           1 :     ret += '\n';
     597           1 :     ret += "Example: 'gdal pipeline --progress ! read in.tif ! \\\n";
     598           1 :     ret += "               rasterize --size 256 256 ! buffer 20 ! ";
     599           1 :     ret += "write out.gpkg --overwrite'\n";
     600           1 :     ret += '\n';
     601           1 :     ret += "Potential steps are:\n";
     602             : 
     603          79 :     for (const std::string &name : m_stepRegistry.GetNames())
     604             :     {
     605         156 :         auto alg = GetStepAlg(name);
     606          78 :         assert(alg);
     607          78 :         auto [options, maxOptLen] = alg->GetArgNamesForCLI();
     608          78 :         stepUsageOptions.maxOptLen =
     609          78 :             std::max(stepUsageOptions.maxOptLen, maxOptLen);
     610             :     }
     611             : 
     612             :     {
     613           1 :         ret += '\n';
     614           1 :         auto alg = std::make_unique<GDALRasterReadAlgorithm>();
     615           2 :         alg->SetCallPath({alg->GetName()});
     616           1 :         ret += alg->GetUsageForCLI(shortUsage, stepUsageOptions);
     617             :     }
     618             :     {
     619           1 :         ret += '\n';
     620           1 :         auto alg = std::make_unique<GDALVectorReadAlgorithm>();
     621           2 :         alg->SetCallPath({alg->GetName()});
     622           1 :         ret += alg->GetUsageForCLI(shortUsage, stepUsageOptions);
     623             :     }
     624          79 :     for (const std::string &name : m_stepRegistry.GetNames())
     625             :     {
     626         156 :         auto alg = GetStepAlg(name);
     627          78 :         assert(alg);
     628          86 :         if (alg->CanBeFirstStep() && !alg->CanBeMiddleStep() &&
     629          92 :             !alg->IsHidden() &&
     630           6 :             !STARTS_WITH(name.c_str(), GDALRasterReadAlgorithm::NAME))
     631             :         {
     632           4 :             ret += '\n';
     633           8 :             alg->SetCallPath({name});
     634           4 :             ret += alg->GetUsageForCLI(shortUsage, stepUsageOptions);
     635             :         }
     636             :     }
     637          79 :     for (const std::string &name : m_stepRegistry.GetNames())
     638             :     {
     639         156 :         auto alg = GetStepAlg(name);
     640          78 :         assert(alg);
     641          78 :         if (alg->CanBeMiddleStep() && !alg->IsHidden())
     642             :         {
     643          65 :             ret += '\n';
     644         195 :             alg->SetCallPath({CPLString(alg->GetName())
     645         130 :                                   .replaceAll(RASTER_SUFFIX, "")
     646         195 :                                   .replaceAll(VECTOR_SUFFIX, "")});
     647          65 :             ret += alg->GetUsageForCLI(shortUsage, stepUsageOptions);
     648             :         }
     649             :     }
     650          79 :     for (const std::string &name : m_stepRegistry.GetNames())
     651             :     {
     652         156 :         auto alg = GetStepAlg(name);
     653          78 :         assert(alg);
     654          89 :         if (alg->CanBeLastStep() && !alg->CanBeMiddleStep() &&
     655          96 :             !alg->IsHidden() &&
     656           7 :             !STARTS_WITH(name.c_str(), GDALRasterWriteAlgorithm::NAME))
     657             :         {
     658           5 :             ret += '\n';
     659          10 :             alg->SetCallPath({name});
     660           5 :             ret += alg->GetUsageForCLI(shortUsage, stepUsageOptions);
     661             :         }
     662             :     }
     663             :     {
     664           1 :         ret += '\n';
     665           1 :         auto alg = std::make_unique<GDALRasterWriteAlgorithm>();
     666           2 :         alg->SetCallPath({alg->GetName()});
     667           1 :         ret += alg->GetUsageForCLI(shortUsage, stepUsageOptions);
     668             :     }
     669             :     {
     670           1 :         ret += '\n';
     671           1 :         auto alg = std::make_unique<GDALVectorWriteAlgorithm>();
     672           2 :         alg->SetCallPath({alg->GetName()});
     673           1 :         ret += alg->GetUsageForCLI(shortUsage, stepUsageOptions);
     674             :     }
     675             : 
     676           1 :     ret += GetUsageForCLIEnd();
     677             : 
     678           1 :     return ret;
     679             : }
     680             : 
     681             : //! @endcond

Generated by: LCOV version 1.14