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

Generated by: LCOV version 1.14