LCOV - code coverage report
Current view: top level - apps - gdalalg_vector_pipeline.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 301 303 99.3 %
Date: 2025-12-21 22:14:19 Functions: 30 31 96.8 %

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

Generated by: LCOV version 1.14