LCOV - code coverage report
Current view: top level - apps - gdalalg_vector_pipeline.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 330 332 99.4 %
Date: 2026-04-20 19:56:30 Functions: 36 38 94.7 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  GDAL
       4             :  * Purpose:  gdal "vector 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             : #include "gdalalg_vector_pipeline.h"
      14             : #include "gdalalg_external.h"
      15             : #include "gdalalg_materialize.h"
      16             : #include "gdalalg_vector_read.h"
      17             : #include "gdalalg_vector_buffer.h"
      18             : #include "gdalalg_vector_check_coverage.h"
      19             : #include "gdalalg_vector_check_geometry.h"
      20             : #include "gdalalg_vector_clean_coverage.h"
      21             : #include "gdalalg_vector_clip.h"
      22             : #include "gdalalg_vector_combine.h"
      23             : #include "gdalalg_vector_concat.h"
      24             : #include "gdalalg_vector_concave_hull.h"
      25             : #include "gdalalg_vector_convex_hull.h"
      26             : #include "gdalalg_vector_create.h"
      27             : #include "gdalalg_vector_dissolve.h"
      28             : #include "gdalalg_vector_edit.h"
      29             : #include "gdalalg_vector_explode_collections.h"
      30             : #include "gdalalg_vector_export_schema.h"
      31             : #include "gdalalg_vector_filter.h"
      32             : #include "gdalalg_vector_info.h"
      33             : #include "gdalalg_vector_limit.h"
      34             : #include "gdalalg_vector_make_point.h"
      35             : #include "gdalalg_vector_make_valid.h"
      36             : #include "gdalalg_vector_partition.h"
      37             : #include "gdalalg_vector_rename_layer.h"
      38             : #include "gdalalg_vector_reproject.h"
      39             : #include "gdalalg_vector_segmentize.h"
      40             : #include "gdalalg_vector_select.h"
      41             : #include "gdalalg_vector_set_field_type.h"
      42             : #include "gdalalg_vector_set_geom_type.h"
      43             : #include "gdalalg_vector_simplify.h"
      44             : #include "gdalalg_vector_simplify_coverage.h"
      45             : #include "gdalalg_vector_sort.h"
      46             : #include "gdalalg_vector_sql.h"
      47             : #include "gdalalg_vector_swap_xy.h"
      48             : #include "gdalalg_vector_update.h"
      49             : #include "gdalalg_vector_write.h"
      50             : #include "gdalalg_tee.h"
      51             : 
      52             : #include "../frmts/mem/memdataset.h"
      53             : 
      54             : #include "cpl_conv.h"
      55             : #include "cpl_string.h"
      56             : 
      57             : #include <algorithm>
      58             : #include <cassert>
      59             : 
      60             : //! @cond Doxygen_Suppress
      61             : 
      62             : #ifndef _
      63             : #define _(x) (x)
      64             : #endif
      65             : 
      66             : GDALVectorAlgorithmStepRegistry::~GDALVectorAlgorithmStepRegistry() = default;
      67             : 
      68             : /************************************************************************/
      69             : /*  GDALVectorPipelineStepAlgorithm::GDALVectorPipelineStepAlgorithm()  */
      70             : /************************************************************************/
      71             : 
      72        1806 : GDALVectorPipelineStepAlgorithm::GDALVectorPipelineStepAlgorithm(
      73             :     const std::string &name, const std::string &description,
      74        1806 :     const std::string &helpURL, bool standaloneStep)
      75             :     : GDALVectorPipelineStepAlgorithm(
      76             :           name, description, helpURL,
      77        1806 :           ConstructorOptions().SetStandaloneStep(standaloneStep))
      78             : {
      79        1806 : }
      80             : 
      81             : /************************************************************************/
      82             : /*  GDALVectorPipelineStepAlgorithm::GDALVectorPipelineStepAlgorithm()  */
      83             : /************************************************************************/
      84             : 
      85        4708 : GDALVectorPipelineStepAlgorithm::GDALVectorPipelineStepAlgorithm(
      86             :     const std::string &name, const std::string &description,
      87        4708 :     const std::string &helpURL, const ConstructorOptions &options)
      88        4708 :     : GDALPipelineStepAlgorithm(name, description, helpURL, options)
      89             : {
      90        4708 :     if (m_standaloneStep)
      91             :     {
      92        2082 :         m_supportsStreamedOutput = true;
      93             : 
      94        2082 :         if (m_constructorOptions.addDefaultArguments)
      95             :         {
      96        1621 :             AddVectorInputArgs(false);
      97        1621 :             AddProgressArg();
      98        1621 :             AddVectorOutputArgs(false, false);
      99             :         }
     100             :     }
     101             :     else
     102             :     {
     103        2626 :         if (m_constructorOptions.addDefaultArguments)
     104             :         {
     105        1751 :             AddVectorHiddenInputDatasetArg();
     106             :         }
     107             :     }
     108        4708 : }
     109             : 
     110             : GDALVectorPipelineStepAlgorithm::~GDALVectorPipelineStepAlgorithm() = default;
     111             : 
     112             : /************************************************************************/
     113             : /*      GDALVectorPipelineAlgorithm::GDALVectorPipelineAlgorithm()      */
     114             : /************************************************************************/
     115             : 
     116         154 : GDALVectorPipelineAlgorithm::GDALVectorPipelineAlgorithm()
     117             :     : GDALAbstractPipelineAlgorithm(
     118             :           NAME, DESCRIPTION, HELP_URL,
     119         154 :           ConstructorOptions().SetInputDatasetMaxCount(INT_MAX))
     120             : {
     121         154 :     m_supportsStreamedOutput = true;
     122             : 
     123         154 :     AddVectorInputArgs(/* hiddenForCLI = */ true);
     124         154 :     AddProgressArg();
     125         308 :     AddArg("pipeline", 0, _("Pipeline string"), &m_pipeline)
     126         154 :         .SetHiddenForCLI()
     127         154 :         .SetPositional();
     128         154 :     AddVectorOutputArgs(/* hiddenForCLI = */ true,
     129             :                         /* shortNameOutputLayerAllowed=*/false);
     130             : 
     131         154 :     AddOutputStringArg(&m_output).SetHiddenForCLI();
     132         154 :     AddStdoutArg(&m_stdout);
     133             : 
     134         154 :     RegisterAlgorithms(m_stepRegistry, false);
     135         154 : }
     136             : 
     137             : /************************************************************************/
     138             : /*          GDALVectorPipelineAlgorithm::RegisterAlgorithms()           */
     139             : /************************************************************************/
     140             : 
     141             : /* static */
     142         419 : void GDALVectorPipelineAlgorithm::RegisterAlgorithms(
     143             :     GDALVectorAlgorithmStepRegistry &registry, bool forMixedPipeline)
     144             : {
     145         838 :     GDALAlgorithmRegistry::AlgInfo algInfo;
     146             : 
     147             :     const auto addSuffixIfNeeded =
     148        4609 :         [forMixedPipeline](const char *name) -> std::string
     149             :     {
     150        7524 :         return forMixedPipeline ? std::string(name).append(VECTOR_SUFFIX)
     151       12133 :                                 : std::string(name);
     152         419 :     };
     153             : 
     154         419 :     registry.Register<GDALVectorReadAlgorithm>(
     155         838 :         addSuffixIfNeeded(GDALVectorReadAlgorithm::NAME));
     156             : 
     157         419 :     registry.Register<GDALVectorWriteAlgorithm>(
     158         838 :         addSuffixIfNeeded(GDALVectorWriteAlgorithm::NAME));
     159             : 
     160         419 :     registry.Register<GDALVectorInfoAlgorithm>(
     161         838 :         addSuffixIfNeeded(GDALVectorInfoAlgorithm::NAME));
     162             : 
     163         419 :     registry.Register<GDALVectorBufferAlgorithm>();
     164         419 :     registry.Register<GDALVectorCheckCoverageAlgorithm>();
     165         419 :     registry.Register<GDALVectorCheckGeometryAlgorithm>();
     166         419 :     registry.Register<GDALVectorCombineAlgorithm>();
     167         419 :     registry.Register<GDALVectorConcatAlgorithm>();
     168         419 :     registry.Register<GDALVectorConcaveHullAlgorithm>();
     169         419 :     registry.Register<GDALVectorConvexHullAlgorithm>();
     170         419 :     registry.Register<GDALVectorCleanCoverageAlgorithm>();
     171             : 
     172         419 :     registry.Register<GDALVectorClipAlgorithm>(
     173         838 :         addSuffixIfNeeded(GDALVectorClipAlgorithm::NAME));
     174         419 :     registry.Register<GDALVectorDissolveAlgorithm>();
     175             : 
     176         419 :     registry.Register<GDALVectorCreateAlgorithm>(
     177         838 :         addSuffixIfNeeded(GDALVectorCreateAlgorithm::NAME));
     178             : 
     179         419 :     registry.Register<GDALVectorEditAlgorithm>(
     180         838 :         addSuffixIfNeeded(GDALVectorEditAlgorithm::NAME));
     181             : 
     182         419 :     registry.Register<GDALVectorExplodeCollectionsAlgorithm>();
     183         419 :     registry.Register<GDALVectorExportSchemaAlgorithm>();
     184             : 
     185         419 :     registry.Register<GDALMaterializeVectorAlgorithm>(
     186         838 :         addSuffixIfNeeded(GDALMaterializeVectorAlgorithm::NAME));
     187             : 
     188         419 :     registry.Register<GDALVectorReprojectAlgorithm>(
     189         838 :         addSuffixIfNeeded(GDALVectorReprojectAlgorithm::NAME));
     190             : 
     191         419 :     registry.Register<GDALVectorFilterAlgorithm>();
     192         419 :     registry.Register<GDALVectorLimitAlgorithm>();
     193         419 :     registry.Register<GDALVectorMakePointAlgorithm>();
     194         419 :     registry.Register<GDALVectorMakeValidAlgorithm>();
     195         419 :     registry.Register<GDALVectorPartitionAlgorithm>();
     196         419 :     registry.Register<GDALVectorRenameLayerAlgorithm>();
     197         419 :     registry.Register<GDALVectorSegmentizeAlgorithm>();
     198             : 
     199         419 :     registry.Register<GDALVectorSelectAlgorithm>(
     200         838 :         addSuffixIfNeeded(GDALVectorSelectAlgorithm::NAME));
     201             : 
     202         419 :     registry.Register<GDALVectorSetFieldTypeAlgorithm>();
     203         419 :     registry.Register<GDALVectorSetGeomTypeAlgorithm>();
     204         419 :     registry.Register<GDALVectorSimplifyAlgorithm>();
     205         419 :     registry.Register<GDALVectorSimplifyCoverageAlgorithm>();
     206         419 :     registry.Register<GDALVectorSortAlgorithm>();
     207         419 :     registry.Register<GDALVectorSQLAlgorithm>();
     208         419 :     registry.Register<GDALVectorUpdateAlgorithm>(
     209         838 :         addSuffixIfNeeded(GDALVectorUpdateAlgorithm::NAME));
     210         419 :     registry.Register<GDALVectorSwapXYAlgorithm>();
     211             : 
     212         419 :     registry.Register<GDALTeeVectorAlgorithm>(
     213         838 :         addSuffixIfNeeded(GDALTeeVectorAlgorithm::NAME));
     214             : 
     215         419 :     if (!forMixedPipeline)
     216             :     {
     217         154 :         registry.Register<GDALExternalVectorAlgorithm>();
     218             :     }
     219         419 : }
     220             : 
     221             : /************************************************************************/
     222             : /*            GDALVectorPipelineAlgorithm::GetUsageForCLI()             */
     223             : /************************************************************************/
     224             : 
     225           8 : std::string GDALVectorPipelineAlgorithm::GetUsageForCLI(
     226             :     bool shortUsage, const UsageOptions &usageOptions) const
     227             : {
     228           8 :     UsageOptions stepUsageOptions;
     229           8 :     stepUsageOptions.isPipelineStep = true;
     230             : 
     231           8 :     if (!m_helpDocCategory.empty() && m_helpDocCategory != "main")
     232             :     {
     233           4 :         auto alg = GetStepAlg(m_helpDocCategory);
     234           2 :         if (alg)
     235             :         {
     236           2 :             alg->SetCallPath({m_helpDocCategory});
     237           1 :             alg->GetArg("help-doc")->Set(true);
     238           1 :             return alg->GetUsageForCLI(shortUsage, stepUsageOptions);
     239             :         }
     240             :         else
     241             :         {
     242           1 :             fprintf(stderr, "ERROR: unknown pipeline step '%s'\n",
     243             :                     m_helpDocCategory.c_str());
     244             :             return CPLSPrintf("ERROR: unknown pipeline step '%s'\n",
     245           1 :                               m_helpDocCategory.c_str());
     246             :         }
     247             :     }
     248             : 
     249           6 :     UsageOptions usageOptionsMain(usageOptions);
     250           6 :     usageOptionsMain.isPipelineMain = true;
     251             :     std::string ret =
     252          12 :         GDALAlgorithm::GetUsageForCLI(shortUsage, usageOptionsMain);
     253           6 :     if (shortUsage)
     254           2 :         return ret;
     255             : 
     256             :     ret += "\n<PIPELINE> is of the form: read|concat [READ-OPTIONS] "
     257           4 :            "( ! <STEP-NAME> [STEP-OPTIONS] )* ! write|info [WRITE-OPTIONS]\n";
     258             : 
     259           4 :     if (m_helpDocCategory == "main")
     260             :     {
     261           1 :         return ret;
     262             :     }
     263             : 
     264           3 :     ret += '\n';
     265           3 :     ret += "Example: 'gdal vector pipeline --progress ! read in.gpkg ! \\\n";
     266           3 :     ret += "               reproject --dst-crs=EPSG:32632 ! ";
     267           3 :     ret += "write out.gpkg --overwrite'\n";
     268           3 :     ret += '\n';
     269           3 :     ret += "Potential steps are:\n";
     270             : 
     271         114 :     for (const std::string &name : m_stepRegistry.GetNames())
     272             :     {
     273         222 :         auto alg = GetStepAlg(name);
     274         111 :         assert(alg);
     275         111 :         auto [options, maxOptLen] = alg->GetArgNamesForCLI();
     276         111 :         stepUsageOptions.maxOptLen =
     277         111 :             std::max(stepUsageOptions.maxOptLen, maxOptLen);
     278             :     }
     279             : 
     280             :     {
     281           3 :         const auto name = GDALVectorReadAlgorithm::NAME;
     282           3 :         ret += '\n';
     283           6 :         auto alg = GetStepAlg(name);
     284           6 :         alg->SetCallPath({name});
     285           3 :         ret += alg->GetUsageForCLI(shortUsage, stepUsageOptions);
     286             :     }
     287         114 :     for (const std::string &name : m_stepRegistry.GetNames())
     288             :     {
     289         222 :         auto alg = GetStepAlg(name);
     290         111 :         assert(alg);
     291         123 :         if (alg->CanBeFirstStep() && !alg->CanBeMiddleStep() &&
     292         123 :             !alg->IsHidden() && name != GDALVectorReadAlgorithm::NAME)
     293             :         {
     294           3 :             ret += '\n';
     295           6 :             alg->SetCallPath({name});
     296           3 :             ret += alg->GetUsageForCLI(shortUsage, stepUsageOptions);
     297             :         }
     298             :     }
     299         114 :     for (const std::string &name : m_stepRegistry.GetNames())
     300             :     {
     301         222 :         auto alg = GetStepAlg(name);
     302         111 :         assert(alg);
     303         111 :         if (alg->CanBeMiddleStep() && !alg->IsHidden())
     304             :         {
     305          93 :             ret += '\n';
     306         186 :             alg->SetCallPath({name});
     307          93 :             ret += alg->GetUsageForCLI(shortUsage, stepUsageOptions);
     308             :         }
     309             :     }
     310         114 :     for (const std::string &name : m_stepRegistry.GetNames())
     311             :     {
     312         222 :         auto alg = GetStepAlg(name);
     313         111 :         assert(alg);
     314         132 :         if (alg->CanBeLastStep() && !alg->CanBeMiddleStep() &&
     315         132 :             !alg->IsHidden() && name != GDALVectorWriteAlgorithm::NAME)
     316             :         {
     317           9 :             ret += '\n';
     318          18 :             alg->SetCallPath({name});
     319           9 :             ret += alg->GetUsageForCLI(shortUsage, stepUsageOptions);
     320             :         }
     321             :     }
     322             :     {
     323           3 :         const auto name = GDALVectorWriteAlgorithm::NAME;
     324           3 :         ret += '\n';
     325           6 :         auto alg = GetStepAlg(name);
     326           6 :         alg->SetCallPath({name});
     327           3 :         ret += alg->GetUsageForCLI(shortUsage, stepUsageOptions);
     328             :     }
     329             : 
     330           3 :     ret += GetUsageForCLIEnd();
     331             : 
     332           3 :     return ret;
     333             : }
     334             : 
     335             : /************************************************************************/
     336             : /*                      GDALVectorDecoratedDataset                      */
     337             : /************************************************************************/
     338             : 
     339             : namespace
     340             : {
     341             : class DummyDataset final : public GDALDataset
     342             : {
     343             :   public:
     344          16 :     DummyDataset() = default;
     345             : };
     346             : }  // namespace
     347             : 
     348             : /************************************************************************/
     349             : /*                     GDALVectorDecoratedDataset()                     */
     350             : /************************************************************************/
     351             : 
     352         365 : GDALVectorDecoratedDataset::GDALVectorDecoratedDataset(GDALDataset *poSrcDS)
     353         730 :     : m_dummySrcDS(poSrcDS ? nullptr : std::make_unique<DummyDataset>()),
     354        1095 :       m_srcDS(poSrcDS ? *poSrcDS : *(m_dummySrcDS.get()))
     355             : {
     356         365 :     m_srcDS.Reference();
     357         365 :     SetDescription(m_srcDS.GetDescription());
     358         365 : }
     359             : 
     360             : /************************************************************************/
     361             : /*                    ~GDALVectorDecoratedDataset()                     */
     362             : /************************************************************************/
     363             : 
     364         365 : GDALVectorDecoratedDataset::~GDALVectorDecoratedDataset()
     365             : {
     366         365 :     m_srcDS.ReleaseRef();
     367         365 : }
     368             : 
     369             : /************************************************************************/
     370             : /*                    GDALVectorPipelineOutputLayer                     */
     371             : /************************************************************************/
     372             : 
     373             : /************************************************************************/
     374             : /*                   GDALVectorPipelineOutputLayer()                    */
     375             : /************************************************************************/
     376             : 
     377         296 : GDALVectorPipelineOutputLayer::GDALVectorPipelineOutputLayer(OGRLayer &srcLayer)
     378         296 :     : m_srcLayer(srcLayer)
     379             : {
     380         296 : }
     381             : 
     382             : /************************************************************************/
     383             : /*                   ~GDALVectorPipelineOutputLayer()                   */
     384             : /************************************************************************/
     385             : 
     386             : GDALVectorPipelineOutputLayer::~GDALVectorPipelineOutputLayer() = default;
     387             : 
     388             : /************************************************************************/
     389             : /*            GDALVectorPipelineOutputLayer::ResetReading()             */
     390             : /************************************************************************/
     391             : 
     392        1606 : void GDALVectorPipelineOutputLayer::ResetReading()
     393             : {
     394        1606 :     m_srcLayer.ResetReading();
     395        1606 :     m_pendingFeatures.clear();
     396        1606 :     m_idxInPendingFeatures = 0;
     397        1606 : }
     398             : 
     399             : /************************************************************************/
     400             : /*          GDALVectorPipelineOutputLayer::GetNextRawFeature()          */
     401             : /************************************************************************/
     402             : 
     403        4048 : OGRFeature *GDALVectorPipelineOutputLayer::GetNextRawFeature()
     404             : {
     405        4048 :     if (m_idxInPendingFeatures < m_pendingFeatures.size())
     406             :     {
     407             :         OGRFeature *poFeature =
     408          14 :             m_pendingFeatures[m_idxInPendingFeatures].release();
     409          14 :         ++m_idxInPendingFeatures;
     410          14 :         return poFeature;
     411             :     }
     412        4034 :     m_pendingFeatures.clear();
     413        4034 :     m_idxInPendingFeatures = 0;
     414             :     while (true)
     415             :     {
     416             :         auto poSrcFeature =
     417        4361 :             std::unique_ptr<OGRFeature>(m_srcLayer.GetNextFeature());
     418        4361 :         if (!poSrcFeature)
     419         703 :             return nullptr;
     420        3658 :         TranslateFeature(std::move(poSrcFeature), m_pendingFeatures);
     421        3658 :         if (m_translateError)
     422             :         {
     423           7 :             return nullptr;
     424             :         }
     425        3651 :         if (!m_pendingFeatures.empty())
     426        3324 :             break;
     427         327 :     }
     428        3324 :     OGRFeature *poFeature = m_pendingFeatures[0].release();
     429        3324 :     m_idxInPendingFeatures = 1;
     430        3324 :     return poFeature;
     431             : }
     432             : 
     433             : /************************************************************************/
     434             : /*                       GDALVectorOutputDataset                        */
     435             : /************************************************************************/
     436             : 
     437             : /************************************************************************/
     438             : /*                      GDALVectorOutputDataset()                       */
     439             : /************************************************************************/
     440             : 
     441          18 : GDALVectorOutputDataset::GDALVectorOutputDataset(GDALDataset *poSrcDS)
     442          18 :     : GDALVectorDecoratedDataset(poSrcDS)
     443             : {
     444          18 : }
     445             : 
     446             : /************************************************************************/
     447             : /*                           TestCapability()                           */
     448             : /************************************************************************/
     449             : 
     450          15 : int GDALVectorOutputDataset::TestCapability(const char *) const
     451             : {
     452          15 :     return 0;
     453             : }
     454             : 
     455             : /************************************************************************/
     456             : /*                   GDALVectorPipelineOutputDataset                    */
     457             : /************************************************************************/
     458             : 
     459             : /************************************************************************/
     460             : /*                  GDALVectorPipelineOutputDataset()                   */
     461             : /************************************************************************/
     462             : 
     463         252 : GDALVectorPipelineOutputDataset::GDALVectorPipelineOutputDataset(
     464         252 :     GDALDataset &srcDS)
     465         252 :     : GDALVectorDecoratedDataset(&srcDS)
     466             : {
     467         252 : }
     468             : 
     469             : /************************************************************************/
     470             : /*             GDALVectorPipelineOutputDataset::AddLayer()              */
     471             : /************************************************************************/
     472             : 
     473         300 : void GDALVectorPipelineOutputDataset::AddLayer(
     474             :     OGRLayer &oSrcLayer,
     475             :     std::unique_ptr<OGRLayerWithTranslateFeature> poNewLayer)
     476             : {
     477         300 :     m_layersToDestroy.push_back(std::move(poNewLayer));
     478             :     OGRLayerWithTranslateFeature *poNewLayerRaw =
     479         300 :         m_layersToDestroy.back().get();
     480         300 :     m_layers.push_back(poNewLayerRaw);
     481         300 :     m_mapSrcLayerToNewLayer[&oSrcLayer] = poNewLayerRaw;
     482         300 : }
     483             : 
     484             : /************************************************************************/
     485             : /*           GDALVectorPipelineOutputDataset::GetLayerCount()           */
     486             : /************************************************************************/
     487             : 
     488        1564 : int GDALVectorPipelineOutputDataset::GetLayerCount() const
     489             : {
     490        1564 :     return static_cast<int>(m_layers.size());
     491             : }
     492             : 
     493             : /************************************************************************/
     494             : /*             GDALVectorPipelineOutputDataset::GetLayer()              */
     495             : /************************************************************************/
     496             : 
     497         736 : OGRLayer *GDALVectorPipelineOutputDataset::GetLayer(int idx) const
     498             : {
     499         736 :     return idx >= 0 && idx < GetLayerCount() ? m_layers[idx] : nullptr;
     500             : }
     501             : 
     502             : /************************************************************************/
     503             : /*          GDALVectorPipelineOutputDataset::TestCapability()           */
     504             : /************************************************************************/
     505             : 
     506         194 : int GDALVectorPipelineOutputDataset::TestCapability(const char *pszCap) const
     507             : {
     508         194 :     if (EQUAL(pszCap, ODsCRandomLayerRead) ||
     509          73 :         EQUAL(pszCap, ODsCMeasuredGeometries) || EQUAL(pszCap, ODsCZGeometries))
     510             :     {
     511         158 :         return m_srcDS.TestCapability(pszCap);
     512             :     }
     513          36 :     return false;
     514             : }
     515             : 
     516             : /************************************************************************/
     517             : /*           GDALVectorPipelineOutputDataset::ResetReading()            */
     518             : /************************************************************************/
     519             : 
     520           3 : void GDALVectorPipelineOutputDataset::ResetReading()
     521             : {
     522           3 :     m_srcDS.ResetReading();
     523           3 :     m_pendingFeatures.clear();
     524           3 :     m_idxInPendingFeatures = 0;
     525           3 : }
     526             : 
     527             : /************************************************************************/
     528             : /*          GDALVectorPipelineOutputDataset::GetNextFeature()           */
     529             : /************************************************************************/
     530             : 
     531          23 : OGRFeature *GDALVectorPipelineOutputDataset::GetNextFeature(
     532             :     OGRLayer **ppoBelongingLayer, double *pdfProgressPct,
     533             :     GDALProgressFunc pfnProgress, void *pProgressData)
     534             : {
     535          23 :     if (m_idxInPendingFeatures < m_pendingFeatures.size())
     536             :     {
     537             :         OGRFeature *poFeature =
     538           3 :             m_pendingFeatures[m_idxInPendingFeatures].release();
     539           3 :         if (ppoBelongingLayer)
     540           3 :             *ppoBelongingLayer = m_belongingLayer;
     541           3 :         ++m_idxInPendingFeatures;
     542           3 :         return poFeature;
     543             :     }
     544             : 
     545          20 :     m_pendingFeatures.clear();
     546          20 :     m_idxInPendingFeatures = 0;
     547             : 
     548             :     while (true)
     549             :     {
     550          20 :         OGRLayer *poSrcBelongingLayer = nullptr;
     551          20 :         auto poSrcFeature = std::unique_ptr<OGRFeature>(m_srcDS.GetNextFeature(
     552          20 :             &poSrcBelongingLayer, pdfProgressPct, pfnProgress, pProgressData));
     553          20 :         if (!poSrcFeature)
     554           3 :             return nullptr;
     555          17 :         auto iterToDstLayer = m_mapSrcLayerToNewLayer.find(poSrcBelongingLayer);
     556          17 :         if (iterToDstLayer != m_mapSrcLayerToNewLayer.end())
     557             :         {
     558          17 :             m_belongingLayer = iterToDstLayer->second;
     559          17 :             m_belongingLayer->TranslateFeature(std::move(poSrcFeature),
     560          17 :                                                m_pendingFeatures);
     561             : 
     562          17 :             if (!m_pendingFeatures.empty())
     563          17 :                 break;
     564             :         }
     565           0 :     }
     566          17 :     OGRFeature *poFeature = m_pendingFeatures[0].release();
     567          17 :     if (ppoBelongingLayer)
     568          17 :         *ppoBelongingLayer = m_belongingLayer;
     569          17 :     m_idxInPendingFeatures = 1;
     570          17 :     return poFeature;
     571             : }
     572             : 
     573             : /************************************************************************/
     574             : /*          GDALVectorPipelinePassthroughLayer::GetLayerDefn()          */
     575             : /************************************************************************/
     576             : 
     577        2468 : const OGRFeatureDefn *GDALVectorPipelinePassthroughLayer::GetLayerDefn() const
     578             : {
     579        2468 :     return m_srcLayer.GetLayerDefn();
     580             : }
     581             : 
     582             : /************************************************************************/
     583             : /*          GDALVectorPipelinePassthroughLayer::GetLayerDefn()          */
     584             : /************************************************************************/
     585             : 
     586        1086 : void GDALVectorPipelinePassthroughLayer::TranslateFeature(
     587             :     std::unique_ptr<OGRFeature> poSrcFeature,
     588             :     std::vector<std::unique_ptr<OGRFeature>> &apoOutFeatures)
     589             : {
     590        2105 :     if ((!m_poFilterGeom || FilterGeometry(poSrcFeature->GetGeometryRef())) &&
     591        1019 :         (!m_poAttrQuery || m_poAttrQuery->Evaluate(poSrcFeature.get())))
     592             :     {
     593         906 :         apoOutFeatures.push_back(std::move(poSrcFeature));
     594             :     }
     595        1086 : }
     596             : 
     597             : /************************************************************************/
     598             : /*               GDALVectorNonStreamingAlgorithmDataset()               */
     599             : /************************************************************************/
     600             : 
     601          78 : GDALVectorNonStreamingAlgorithmDataset::GDALVectorNonStreamingAlgorithmDataset(
     602          78 :     GDALDataset &oSrcDS)
     603          78 :     : GDALVectorDecoratedDataset(&oSrcDS)
     604             : {
     605          78 : }
     606             : 
     607             : /************************************************************************/
     608             : /*              ~GDALVectorNonStreamingAlgorithmDataset()               */
     609             : /************************************************************************/
     610             : 
     611             : GDALVectorNonStreamingAlgorithmDataset::
     612             :     ~GDALVectorNonStreamingAlgorithmDataset() = default;
     613             : 
     614             : /************************************************************************/
     615             : /*     GDALVectorNonStreamingAlgorithmDataset::AddProcessedLayer()      */
     616             : /************************************************************************/
     617             : 
     618          71 : bool GDALVectorNonStreamingAlgorithmDataset::AddProcessedLayer(
     619             :     std::unique_ptr<GDALVectorNonStreamingAlgorithmLayer> layer,
     620             :     GDALProgressFunc progressFn, void *progressData)
     621             : {
     622          71 :     if (!layer->Process(progressFn, progressData))
     623             :     {
     624           6 :         return false;
     625             :     }
     626             : 
     627          65 :     m_owned_layers.emplace_back(std::move(layer));
     628          65 :     m_layers.push_back(m_owned_layers.back().get());
     629             : 
     630          65 :     return true;
     631             : }
     632             : 
     633             : /************************************************************************/
     634             : /*    GDALVectorNonStreamingAlgorithmDataset::AddPassThroughLayer()     */
     635             : /************************************************************************/
     636             : 
     637           6 : void GDALVectorNonStreamingAlgorithmDataset::AddPassThroughLayer(
     638             :     OGRLayer &oLayer)
     639             : {
     640           6 :     m_owned_layers.push_back(
     641          12 :         std::make_unique<GDALVectorPipelinePassthroughLayer>(oLayer));
     642           6 :     m_layers.push_back(m_owned_layers.back().get());
     643           6 : }
     644             : 
     645             : /************************************************************************/
     646             : /*       GDALVectorNonStreamingAlgorithmDataset::GetLayerCount()        */
     647             : /************************************************************************/
     648             : 
     649         244 : int GDALVectorNonStreamingAlgorithmDataset::GetLayerCount() const
     650             : {
     651         244 :     return static_cast<int>(m_layers.size());
     652             : }
     653             : 
     654             : /************************************************************************/
     655             : /*          GDALVectorNonStreamingAlgorithmDataset::GetLayer()          */
     656             : /************************************************************************/
     657             : 
     658         169 : OGRLayer *GDALVectorNonStreamingAlgorithmDataset::GetLayer(int idx) const
     659             : {
     660         169 :     if (idx < 0 || idx >= static_cast<int>(m_layers.size()))
     661             :     {
     662           8 :         return nullptr;
     663             :     }
     664         161 :     return m_layers[idx];
     665             : }
     666             : 
     667             : /************************************************************************/
     668             : /*       GDALVectorNonStreamingAlgorithmDataset::TestCapability()       */
     669             : /************************************************************************/
     670             : 
     671          33 : int GDALVectorNonStreamingAlgorithmDataset::TestCapability(
     672             :     const char *pszCap) const
     673             : {
     674          33 :     if (EQUAL(pszCap, ODsCCurveGeometries) ||
     675          29 :         EQUAL(pszCap, ODsCMeasuredGeometries) || EQUAL(pszCap, ODsCZGeometries))
     676             :     {
     677          16 :         return true;
     678             :     }
     679             : 
     680          17 :     return false;
     681             : }
     682             : 
     683             : /************************************************************************/
     684             : /*               GDALVectorAlgorithmLayerProgressHelper()               */
     685             : /************************************************************************/
     686             : 
     687          78 : GDALVectorAlgorithmLayerProgressHelper::GDALVectorAlgorithmLayerProgressHelper(
     688          78 :     GDALProgressFunc pfnProgress, void *pProgressData)
     689          78 :     : m_pfnProgress(pfnProgress), m_pProgressData(pProgressData)
     690             : {
     691          78 : }
     692             : 
     693             : /************************************************************************/
     694             : /*               GDALVectorAlgorithmLayerProgressHelper()               */
     695             : /************************************************************************/
     696             : 
     697          78 : GDALVectorAlgorithmLayerProgressHelper::GDALVectorAlgorithmLayerProgressHelper(
     698          78 :     const GDALPipelineStepRunContext &ctxt)
     699          78 :     : GDALVectorAlgorithmLayerProgressHelper(ctxt.m_pfnProgress,
     700          78 :                                              ctxt.m_pProgressData)
     701             : {
     702          78 : }
     703             : 
     704             : /************************************************************************/
     705             : /*     GDALVectorAlgorithmLayerProgressHelper::AddProcessedLayer()      */
     706             : /************************************************************************/
     707             : 
     708          74 : void GDALVectorAlgorithmLayerProgressHelper::AddProcessedLayer(
     709             :     OGRLayer &srcLayer)
     710             : {
     711          74 :     m_apoSrcLayers.emplace_back(&srcLayer, true);
     712          82 :     if (m_pfnProgress && m_nTotalFeatures >= 0 &&
     713           8 :         srcLayer.TestCapability(OLCFastFeatureCount))
     714             :     {
     715           8 :         const auto nLayerFeatures = srcLayer.GetFeatureCount(false);
     716           8 :         if (nLayerFeatures < 0)
     717           0 :             m_nTotalFeatures = -1;
     718             :         else
     719           8 :             m_nTotalFeatures += nLayerFeatures;
     720           8 :         m_anFeatures.push_back(nLayerFeatures);
     721             :     }
     722             :     else
     723             :     {
     724          66 :         m_anFeatures.push_back(-1);
     725          66 :         m_nTotalFeatures = -1;
     726             :     }
     727          74 : }
     728             : 
     729             : /************************************************************************/
     730             : /*    GDALVectorAlgorithmLayerProgressHelper::AddPassThroughLayer()     */
     731             : /************************************************************************/
     732             : 
     733          10 : void GDALVectorAlgorithmLayerProgressHelper::AddPassThroughLayer(
     734             :     OGRLayer &srcLayer)
     735             : {
     736          10 :     m_apoSrcLayers.emplace_back(&srcLayer, false);
     737          10 : }
     738             : 
     739             : /************************************************************************/
     740             : /*                GDALVectorNonStreamingAlgorithmLayer()                */
     741             : /************************************************************************/
     742             : 
     743          71 : GDALVectorNonStreamingAlgorithmLayer::GDALVectorNonStreamingAlgorithmLayer(
     744          71 :     OGRLayer &srcLayer, int geomFieldIndex)
     745          71 :     : m_srcLayer(srcLayer), m_geomFieldIndex(geomFieldIndex)
     746             : {
     747          71 : }
     748             : 
     749             : /************************************************************************/
     750             : /*               ~GDALVectorNonStreamingAlgorithmLayer()                */
     751             : /************************************************************************/
     752             : 
     753             : GDALVectorNonStreamingAlgorithmLayer::~GDALVectorNonStreamingAlgorithmLayer() =
     754             :     default;
     755             : 
     756             : /************************************************************************/
     757             : /*      GDALVectorNonStreamingAlgorithmLayer::GetNextRawFeature()       */
     758             : /************************************************************************/
     759             : 
     760        2492 : OGRFeature *GDALVectorNonStreamingAlgorithmLayer::GetNextRawFeature()
     761             : {
     762        2492 :     return GetNextProcessedFeature().release();
     763             : }
     764             : 
     765             : /************************************************************************/
     766             : /*    GDALVectorAlgorithmLayerProgressHelper::iterator::operator*()     */
     767             : /************************************************************************/
     768             : 
     769             : GDALVectorAlgorithmLayerProgressHelper::iterator::value_type
     770          80 : GDALVectorAlgorithmLayerProgressHelper::iterator::operator*() const
     771             : {
     772             :     const double dfProgressStart =
     773         156 :         m_helper.m_anFeatures.empty() ? 0
     774          76 :         : m_helper.m_nTotalFeatures > 0
     775          76 :             ? static_cast<double>(m_nFeatureIdx) /
     776           8 :                   static_cast<double>(m_helper.m_nTotalFeatures)
     777          68 :             : static_cast<double>(m_nProcessedLayerIdx) /
     778          68 :                   std::max(1.0,
     779          68 :                            static_cast<double>(m_helper.m_anFeatures.size()));
     780             :     const double dfProgressEnd =
     781         156 :         m_helper.m_anFeatures.empty() ? 0
     782          76 :         : m_helper.m_nTotalFeatures > 0
     783          76 :             ? static_cast<double>(m_nFeatureIdx +
     784           8 :                                   m_helper.m_anFeatures[m_nProcessedLayerIdx]) /
     785           8 :                   static_cast<double>(m_helper.m_nTotalFeatures)
     786          68 :             : static_cast<double>(m_nProcessedLayerIdx + 1) /
     787          68 :                   std::max(1.0,
     788          68 :                            static_cast<double>(m_helper.m_anFeatures.size()));
     789             : 
     790             :     progress_data_unique_ptr pScaledProgressData(nullptr,
     791          80 :                                                  GDALDestroyScaledProgress);
     792          80 :     if (m_helper.m_pfnProgress && m_helper.m_apoSrcLayers[m_nLayerIdx].second)
     793             :     {
     794           8 :         pScaledProgressData.reset(GDALCreateScaledProgress(
     795           8 :             dfProgressStart, dfProgressEnd, m_helper.m_pfnProgress,
     796           8 :             m_helper.m_pProgressData));
     797             :     }
     798             : 
     799         160 :     return value_type(m_helper.m_apoSrcLayers[m_nLayerIdx].first,
     800          80 :                       m_helper.m_apoSrcLayers[m_nLayerIdx].second,
     801         160 :                       m_helper.m_pfnProgress ? GDALScaledProgress : nullptr,
     802         240 :                       std::move(pScaledProgressData));
     803             : }
     804             : 
     805             : //! @endcond

Generated by: LCOV version 1.14