LCOV - code coverage report
Current view: top level - apps - gdalalg_vector_pipeline.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 242 243 99.6 %
Date: 2025-09-10 17:48:50 Functions: 24 25 96.0 %

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

Generated by: LCOV version 1.14