LCOV - code coverage report
Current view: top level - apps - gdalalg_vector_pipeline.h (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 43 49 87.8 %
Date: 2025-10-21 22:35:35 Functions: 77 84 91.7 %

          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             : #ifndef GDALALG_VECTOR_PIPELINE_INCLUDED
      14             : #define GDALALG_VECTOR_PIPELINE_INCLUDED
      15             : 
      16             : #include "gdalalgorithm.h"
      17             : #include "gdalalg_abstract_pipeline.h"
      18             : 
      19             : #include "ogrsf_frmts.h"
      20             : #include "ogrlayerwithtranslatefeature.h"
      21             : 
      22             : #include <map>
      23             : #include <vector>
      24             : 
      25             : //! @cond Doxygen_Suppress
      26             : 
      27             : /************************************************************************/
      28             : /*                GDALVectorPipelineStepAlgorithm                       */
      29             : /************************************************************************/
      30             : 
      31             : class GDALRasterAlgorithmStepRegistry;
      32             : 
      33        2268 : class GDALVectorPipelineStepAlgorithm /* non final */
      34             :     : public GDALPipelineStepAlgorithm
      35             : {
      36             :   public:
      37             :     ~GDALVectorPipelineStepAlgorithm() override;
      38             : 
      39             :   protected:
      40             :     GDALVectorPipelineStepAlgorithm(const std::string &name,
      41             :                                     const std::string &description,
      42             :                                     const std::string &helpURL,
      43             :                                     bool standaloneStep);
      44             : 
      45             :     GDALVectorPipelineStepAlgorithm(const std::string &name,
      46             :                                     const std::string &description,
      47             :                                     const std::string &helpURL,
      48             :                                     const ConstructorOptions &options);
      49             : 
      50             :     friend class GDALVectorPipelineAlgorithm;
      51             :     friend class GDALVectorConcatAlgorithm;
      52             : 
      53         335 :     int GetInputType() const override
      54             :     {
      55         335 :         return GDAL_OF_VECTOR;
      56             :     }
      57             : 
      58         321 :     int GetOutputType() const override
      59             :     {
      60         321 :         return GDAL_OF_VECTOR;
      61             :     }
      62             : };
      63             : 
      64             : /************************************************************************/
      65             : /*                      GDALVectorAlgorithmStepRegistry                 */
      66             : /************************************************************************/
      67             : 
      68         285 : class GDALVectorAlgorithmStepRegistry : public virtual GDALAlgorithmRegistry
      69             : {
      70             :   public:
      71         285 :     GDALVectorAlgorithmStepRegistry() = default;
      72             :     ~GDALVectorAlgorithmStepRegistry() override;
      73             : 
      74             :     /** Register the algorithm of type MyAlgorithm.
      75             :      */
      76             :     template <class MyAlgorithm>
      77        7980 :     bool Register(const std::string &name = std::string())
      78             :     {
      79             :         static_assert(
      80             :             std::is_base_of_v<GDALVectorPipelineStepAlgorithm, MyAlgorithm>,
      81             :             "Algorithm is not a GDALVectorPipelineStepAlgorithm");
      82             : 
      83       15960 :         AlgInfo info;
      84        7980 :         info.m_name = name.empty() ? MyAlgorithm::NAME : name;
      85        7980 :         info.m_aliases = MyAlgorithm::GetAliasesStatic();
      86        9226 :         info.m_creationFunc = []() -> std::unique_ptr<GDALAlgorithm>
      87        1246 :         { return std::make_unique<MyAlgorithm>(); };
      88       15960 :         return GDALAlgorithmRegistry::Register(info);
      89             :     }
      90             : };
      91             : 
      92             : /************************************************************************/
      93             : /*                     GDALVectorPipelineAlgorithm                      */
      94             : /************************************************************************/
      95             : 
      96             : class GDALVectorPipelineAlgorithm final : public GDALAbstractPipelineAlgorithm
      97             : {
      98             :   public:
      99             :     static constexpr const char *NAME = "pipeline";
     100             :     static constexpr const char *DESCRIPTION =
     101             :         "Process a vector dataset applying several steps.";
     102             :     static constexpr const char *HELP_URL =
     103             :         "/programs/gdal_vector_pipeline.html";
     104             : 
     105         701 :     static std::vector<std::string> GetAliasesStatic()
     106             :     {
     107             :         return {
     108             : #ifdef GDAL_PIPELINE_PROJ_NOSTALGIA
     109             :             GDALAlgorithmRegistry::HIDDEN_ALIAS_SEPARATOR,
     110             :             "+pipeline",
     111             :             "+gdal=pipeline",
     112             : #endif
     113        2804 :         };
     114             :     }
     115             : 
     116             :     GDALVectorPipelineAlgorithm();
     117             : 
     118             :     std::string GetUsageForCLI(bool shortUsage,
     119             :                                const UsageOptions &usageOptions) const override;
     120             : 
     121             :     static void RegisterAlgorithms(GDALVectorAlgorithmStepRegistry &registry,
     122             :                                    bool forMixedPipeline);
     123             : 
     124          95 :     int GetInputType() const override
     125             :     {
     126          95 :         return GDAL_OF_VECTOR;
     127             :     }
     128             : 
     129           0 :     int GetOutputType() const override
     130             :     {
     131           0 :         return GDAL_OF_VECTOR;
     132             :     }
     133             : 
     134             :   protected:
     135             :     GDALVectorAlgorithmStepRegistry m_stepRegistry{};
     136             : 
     137         163 :     GDALAlgorithmRegistry &GetStepRegistry() override
     138             :     {
     139         163 :         return m_stepRegistry;
     140             :     }
     141             : 
     142         653 :     const GDALAlgorithmRegistry &GetStepRegistry() const override
     143             :     {
     144         653 :         return m_stepRegistry;
     145             :     }
     146             : 
     147             :   private:
     148             :     std::unique_ptr<GDALAbstractPipelineAlgorithm>
     149           0 :     CreateNestedPipeline() const override
     150             :     {
     151           0 :         auto pipeline = std::make_unique<GDALVectorPipelineAlgorithm>();
     152           0 :         pipeline->m_bInnerPipeline = true;
     153           0 :         return pipeline;
     154             :     }
     155             : };
     156             : 
     157             : /************************************************************************/
     158             : /*                  GDALVectorOutputDataset                             */
     159             : /************************************************************************/
     160             : 
     161             : class GDALVectorOutputDataset final : public GDALDataset
     162             : {
     163             : 
     164             :   public:
     165          30 :     int GetLayerCount() const override
     166             :     {
     167          30 :         return static_cast<int>(m_layers.size());
     168             :     }
     169             : 
     170          16 :     const OGRLayer *GetLayer(int idx) const override
     171             :     {
     172          16 :         return m_layers[idx].get();
     173             :     }
     174             : 
     175             :     int TestCapability(const char *) const override;
     176             : 
     177          16 :     void AddLayer(std::unique_ptr<OGRLayer> layer)
     178             :     {
     179          16 :         m_layers.emplace_back(std::move(layer));
     180          16 :     }
     181             : 
     182             :   private:
     183             :     std::vector<std::unique_ptr<OGRLayer>> m_layers{};
     184             : };
     185             : 
     186             : /************************************************************************/
     187             : /*                  GDALVectorPipelineOutputLayer                       */
     188             : /************************************************************************/
     189             : 
     190             : /** Class that implements GetNextFeature() by forwarding to
     191             :  * OGRLayerWithTranslateFeature::TranslateFeature() implementation, which
     192             :  * might return several features.
     193             :  */
     194         180 : class GDALVectorPipelineOutputLayer /* non final */
     195             :     : public OGRLayerWithTranslateFeature,
     196             :       public OGRGetNextFeatureThroughRaw<GDALVectorPipelineOutputLayer>
     197             : {
     198             :   protected:
     199             :     explicit GDALVectorPipelineOutputLayer(OGRLayer &oSrcLayer);
     200             :     ~GDALVectorPipelineOutputLayer() override;
     201             : 
     202        1929 :     DEFINE_GET_NEXT_FEATURE_THROUGH_RAW(GDALVectorPipelineOutputLayer)
     203             : 
     204             :     OGRLayer &m_srcLayer;
     205             : 
     206           7 :     void FailTranslation()
     207             :     {
     208           7 :         m_translateError = true;
     209           7 :     }
     210             : 
     211             :   public:
     212             :     void ResetReading() override;
     213             :     OGRFeature *GetNextRawFeature();
     214             : 
     215             :   private:
     216             :     std::vector<std::unique_ptr<OGRFeature>> m_pendingFeatures{};
     217             :     size_t m_idxInPendingFeatures = 0;
     218             :     bool m_translateError = false;
     219             : };
     220             : 
     221             : /************************************************************************/
     222             : /*                  GDALVectorPipelinePassthroughLayer                  */
     223             : /************************************************************************/
     224             : 
     225             : /** Class that forwards GetNextFeature() calls to the source layer and
     226             :  * can be added to GDALVectorPipelineOutputDataset::AddLayer()
     227             :  */
     228             : class GDALVectorPipelinePassthroughLayer /* non final */
     229             :     : public GDALVectorPipelineOutputLayer
     230             : {
     231             :   public:
     232          12 :     explicit GDALVectorPipelinePassthroughLayer(OGRLayer &oSrcLayer)
     233          12 :         : GDALVectorPipelineOutputLayer(oSrcLayer)
     234             :     {
     235          12 :     }
     236             : 
     237             :     const OGRFeatureDefn *GetLayerDefn() const override;
     238             : 
     239           4 :     int TestCapability(const char *pszCap) const override
     240             :     {
     241           4 :         return m_srcLayer.TestCapability(pszCap);
     242             :     }
     243             : 
     244          28 :     void TranslateFeature(
     245             :         std::unique_ptr<OGRFeature> poSrcFeature,
     246             :         std::vector<std::unique_ptr<OGRFeature>> &apoOutFeatures) override
     247             :     {
     248          28 :         apoOutFeatures.push_back(std::move(poSrcFeature));
     249          28 :     }
     250             : };
     251             : 
     252             : /************************************************************************/
     253             : /*                 GDALVectorNonStreamingAlgorithmDataset               */
     254             : /************************************************************************/
     255             : 
     256             : class MEMDataset;
     257             : 
     258             : /**
     259             :  * Dataset used to read all input features into memory and perform some
     260             :  * processing.
     261             :  */
     262          30 : class GDALVectorNonStreamingAlgorithmDataset /* non final */
     263             :     : public GDALDataset
     264             : {
     265             :   public:
     266             :     GDALVectorNonStreamingAlgorithmDataset();
     267             :     ~GDALVectorNonStreamingAlgorithmDataset() override;
     268             : 
     269             :     virtual bool Process(OGRLayer &srcLayer, OGRLayer &dstLayer) = 0;
     270             : 
     271             :     bool AddProcessedLayer(OGRLayer &srcLayer);
     272             :     bool AddProcessedLayer(OGRLayer &srcLayer, OGRFeatureDefn &dstDefn);
     273             :     void AddPassThroughLayer(OGRLayer &oLayer);
     274             :     int GetLayerCount() const final override;
     275             :     OGRLayer *GetLayer(int idx) const final override;
     276             :     int TestCapability(const char *pszCap) const override;
     277             : 
     278             :   private:
     279             :     std::vector<std::unique_ptr<OGRLayer>> m_passthrough_layers{};
     280             :     std::vector<OGRLayer *> m_layers{};
     281             :     std::unique_ptr<MEMDataset> m_ds{};
     282             : };
     283             : 
     284             : /************************************************************************/
     285             : /*                 GDALVectorPipelineOutputDataset                      */
     286             : /************************************************************************/
     287             : 
     288             : /** Class used by vector pipeline steps to create an output on-the-fly
     289             :  * dataset where they can store on-the-fly layers.
     290             :  */
     291             : class GDALVectorPipelineOutputDataset final : public GDALDataset
     292             : {
     293             :     GDALDataset &m_srcDS;
     294             :     std::map<OGRLayer *, OGRLayerWithTranslateFeature *>
     295             :         m_mapSrcLayerToNewLayer{};
     296             :     std::vector<std::unique_ptr<OGRLayerWithTranslateFeature>>
     297             :         m_layersToDestroy{};
     298             :     std::vector<OGRLayerWithTranslateFeature *> m_layers{};
     299             : 
     300             :     OGRLayerWithTranslateFeature *m_belongingLayer = nullptr;
     301             :     std::vector<std::unique_ptr<OGRFeature>> m_pendingFeatures{};
     302             :     size_t m_idxInPendingFeatures = 0;
     303             : 
     304             :     CPL_DISALLOW_COPY_ASSIGN(GDALVectorPipelineOutputDataset)
     305             : 
     306             :   public:
     307             :     explicit GDALVectorPipelineOutputDataset(GDALDataset &oSrcDS);
     308             : 
     309             :     void AddLayer(OGRLayer &oSrcLayer,
     310             :                   std::unique_ptr<OGRLayerWithTranslateFeature> poNewLayer);
     311             : 
     312             :     int GetLayerCount() const override;
     313             : 
     314             :     OGRLayer *GetLayer(int idx) const override;
     315             : 
     316             :     int TestCapability(const char *pszCap) const override;
     317             : 
     318             :     void ResetReading() override;
     319             : 
     320             :     OGRFeature *GetNextFeature(OGRLayer **ppoBelongingLayer,
     321             :                                double *pdfProgressPct,
     322             :                                GDALProgressFunc pfnProgress,
     323             :                                void *pProgressData) override;
     324             : };
     325             : 
     326             : //! @endcond
     327             : 
     328             : #endif

Generated by: LCOV version 1.14