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

Generated by: LCOV version 1.14