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

Generated by: LCOV version 1.14