LCOV - code coverage report
Current view: top level - apps - gdalalg_vector_pipeline.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 306 308 99.4 %
Date: 2026-03-10 09:22:28 Functions: 31 32 96.9 %

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

Generated by: LCOV version 1.14