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

Generated by: LCOV version 1.14