LCOV - code coverage report
Current view: top level - apps - gdalvectorpipelinestepalgorithm.h (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 62 63 98.4 %
Date: 2026-06-23 16:35:19 Functions: 29 33 87.9 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  GDAL
       4             :  * Purpose:  gdal "vector pipeline" subcommand
       5             :  * Author:   Even Rouault <even dot rouault at spatialys.com>
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2024, Even Rouault <even dot rouault at spatialys.com>
       9             :  *
      10             :  * SPDX-License-Identifier: MIT
      11             :  ****************************************************************************/
      12             : 
      13             : #ifndef GDALVECTORRPIPELINESTEPALGORITHM_INCLUDED
      14             : #define GDALVECTORRPIPELINESTEPALGORITHM_INCLUDED
      15             : 
      16             : #include "gdalalgorithm.h"
      17             : #include "gdalpipelinestepalgorithm.h"
      18             : 
      19             : #include "ogrsf_frmts.h"
      20             : #include "ogrlayerwithtranslatefeature.h"
      21             : 
      22             : #include <map>
      23             : #include <tuple>
      24             : #include <vector>
      25             : 
      26             : //! @cond Doxygen_Suppress
      27             : 
      28             : /************************************************************************/
      29             : /*                   GDALVectorPipelineStepAlgorithm                    */
      30             : /************************************************************************/
      31             : 
      32        5279 : class GDALVectorPipelineStepAlgorithm /* non final */
      33             :     : public GDALPipelineStepAlgorithm
      34             : {
      35             :   public:
      36             :     ~GDALVectorPipelineStepAlgorithm() override;
      37             : 
      38             :   protected:
      39             :     GDALVectorPipelineStepAlgorithm(const std::string &name,
      40             :                                     const std::string &description,
      41             :                                     const std::string &helpURL,
      42             :                                     bool standaloneStep);
      43             : 
      44             :     GDALVectorPipelineStepAlgorithm(const std::string &name,
      45             :                                     const std::string &description,
      46             :                                     const std::string &helpURL,
      47             :                                     const ConstructorOptions &options);
      48             : 
      49             :     friend class GDALVectorPipelineAlgorithm;
      50             :     friend class GDALVectorConcatAlgorithm;
      51             : 
      52         642 :     int GetInputType() const override
      53             :     {
      54         642 :         return GDAL_OF_VECTOR;
      55             :     }
      56             : 
      57         563 :     int GetOutputType() const override
      58             :     {
      59         563 :         return GDAL_OF_VECTOR;
      60             :     }
      61             : };
      62             : 
      63             : /************************************************************************/
      64             : /*                      GDALVectorDecoratedDataset                      */
      65             : /************************************************************************/
      66             : 
      67             : /** Base class for GDALVectorOutputDataset, GDALVectorNonStreamingAlgorithmDataset
      68             :  * and GDALVectorPipelineOutputDataset
      69             :  */
      70             : class GDALVectorDecoratedDataset /* non final */
      71             :     : public GDALDataset
      72             : {
      73             :   public:
      74             :     ~GDALVectorDecoratedDataset() override;
      75             : 
      76          19 :     CSLConstList GetMetadata(const char *pszDomain) override
      77             :     {
      78          19 :         return m_srcDS.GetMetadata(pszDomain);
      79             :     }
      80             : 
      81          15 :     const char *GetMetadataItem(const char *pszName,
      82             :                                 const char *pszDomain) override
      83             :     {
      84          15 :         return m_srcDS.GetMetadataItem(pszName, pszDomain);
      85             :     }
      86             : 
      87             :     std::vector<std::string>
      88           7 :     GetFieldDomainNames(CSLConstList papszOptions) const override
      89             :     {
      90           7 :         return m_srcDS.GetFieldDomainNames(papszOptions);
      91             :     }
      92             : 
      93           3 :     const OGRFieldDomain *GetFieldDomain(const std::string &name) const override
      94             :     {
      95           3 :         return m_srcDS.GetFieldDomain(name);
      96             :     }
      97             : 
      98             :     std::vector<std::string>
      99         151 :     GetRelationshipNames(CSLConstList papszOptions) const override
     100             :     {
     101         151 :         return m_srcDS.GetRelationshipNames(papszOptions);
     102             :     }
     103             : 
     104             :     const GDALRelationship *
     105           1 :     GetRelationship(const std::string &name) const override
     106             :     {
     107           1 :         return m_srcDS.GetRelationship(name);
     108             :     }
     109             : 
     110             :   private:
     111             :     std::unique_ptr<GDALDataset> m_dummySrcDS{};
     112             : 
     113             :   protected:
     114             :     explicit GDALVectorDecoratedDataset(GDALDataset *poSrcDS);
     115             : 
     116             :     GDALDataset &m_srcDS;
     117             : };
     118             : 
     119             : /************************************************************************/
     120             : /*                       GDALVectorOutputDataset                        */
     121             : /************************************************************************/
     122             : 
     123             : class GDALVectorOutputDataset : public GDALVectorDecoratedDataset
     124             : {
     125             : 
     126             :   public:
     127             :     explicit GDALVectorOutputDataset(GDALDataset *poSrcDS);
     128             : 
     129         134 :     int GetLayerCount() const override
     130             :     {
     131         134 :         return static_cast<int>(m_layers.size());
     132             :     }
     133             : 
     134          43 :     const OGRLayer *GetLayer(int idx) const override
     135             :     {
     136          43 :         return idx >= 0 && idx < GetLayerCount() ? m_layers[idx].get()
     137          43 :                                                  : nullptr;
     138             :     }
     139             : 
     140             :     int TestCapability(const char *) const override;
     141             : 
     142          20 :     void AddLayer(std::unique_ptr<OGRLayer> layer)
     143             :     {
     144          20 :         m_layers.emplace_back(std::move(layer));
     145          20 :     }
     146             : 
     147             :   private:
     148             :     std::vector<std::unique_ptr<OGRLayer>> m_layers{};
     149             : };
     150             : 
     151             : /************************************************************************/
     152             : /*                GDALVectorAlgorithmLayerProgressHelper                */
     153             : /************************************************************************/
     154             : 
     155             : /**
     156             :  * This class helps doing progress report for algorithm iterating over layers
     157             :  * of the source dataset.
     158             :  */
     159             : class GDALVectorAlgorithmLayerProgressHelper
     160             : {
     161             :   public:
     162             :     /** Constructor */
     163             :     GDALVectorAlgorithmLayerProgressHelper(GDALProgressFunc pfnProgress,
     164             :                                            void *pProgressData);
     165             :     /** Constructor */
     166             :     explicit GDALVectorAlgorithmLayerProgressHelper(
     167             :         const GDALPipelineStepRunContext &ctxt);
     168             : 
     169             :     /** Register the passed layer as a layer that will be processed. */
     170             :     void AddProcessedLayer(OGRLayer &srcLayer);
     171             : 
     172             :     /** Register the passed layer as a layer that will be forwarded without
     173             :      * processing. */
     174             :     void AddPassThroughLayer(OGRLayer &srcLayer);
     175             : 
     176             :     //! @cond Doxygen_Suppress
     177             :     class iterator
     178             :     {
     179             :       public:
     180         152 :         explicit iterator(const GDALVectorAlgorithmLayerProgressHelper &helper,
     181             :                           bool start)
     182         152 :             : m_helper(helper),
     183         152 :               m_nLayerIdx(start ? 0 : m_helper.m_apoSrcLayers.size())
     184             :         {
     185         152 :         }
     186             : 
     187             :         inline bool operator==(const iterator &other) const
     188             :         {
     189             :             return m_nLayerIdx == other.m_nLayerIdx;
     190             :         }
     191             : 
     192         150 :         inline bool operator!=(const iterator &other) const
     193             :         {
     194         150 :             return m_nLayerIdx != other.m_nLayerIdx;
     195             :         }
     196             : 
     197          74 :         inline iterator &operator++()
     198             :         {
     199          74 :             if (!m_helper.m_anFeatures.empty())
     200          68 :                 m_nFeatureIdx += m_helper.m_anFeatures[m_nProcessedLayerIdx];
     201          74 :             if (m_helper.m_apoSrcLayers[m_nLayerIdx].second)
     202          66 :                 ++m_nProcessedLayerIdx;
     203          74 :             ++m_nLayerIdx;
     204          74 :             return *this;
     205             :         }
     206             : 
     207             :         using progress_data_unique_ptr =
     208             :             std::unique_ptr<void, decltype(&GDALDestroyScaledProgress)>;
     209             :         using value_type = std::tuple<OGRLayer *, bool, GDALProgressFunc,
     210             :                                       progress_data_unique_ptr>;
     211             : 
     212             :         value_type operator*() const;
     213             : 
     214             :       private:
     215             :         const GDALVectorAlgorithmLayerProgressHelper &m_helper;
     216             :         size_t m_nLayerIdx = 0;
     217             :         size_t m_nProcessedLayerIdx = 0;
     218             :         GIntBig m_nFeatureIdx = 0;
     219             :     };
     220             : 
     221             :     //! @endcond
     222             : 
     223             :     /** Start of an iterator over layers registered with AddProcessedLayer()
     224             :      * and AddUnprocessedLayer() */
     225          76 :     iterator begin() const
     226             :     {
     227          76 :         return iterator(*this, true);
     228             :     }
     229             : 
     230             :     /** End of an iterator over layers registered with AddProcessedLayer()
     231             :      * and AddUnprocessedLayer() */
     232          76 :     iterator end() const
     233             :     {
     234          76 :         return iterator(*this, false);
     235             :     }
     236             : 
     237             :     /** Return if AddProcessedLayer() has been called at least once. */
     238           4 :     bool HasProcessedLayers() const
     239             :     {
     240           4 :         return !m_anFeatures.empty();
     241             :     }
     242             : 
     243             :   private:
     244             :     GDALProgressFunc m_pfnProgress = nullptr;
     245             :     void *m_pProgressData = nullptr;
     246             :     int64_t m_nTotalFeatures = 0;
     247             :     std::vector<std::pair<OGRLayer *, bool>> m_apoSrcLayers{};
     248             :     std::vector<int64_t> m_anFeatures{};
     249             : 
     250             :     CPL_DISALLOW_COPY_ASSIGN(GDALVectorAlgorithmLayerProgressHelper)
     251             : };
     252             : 
     253             : /************************************************************************/
     254             : /*                    GDALVectorPipelineOutputLayer                     */
     255             : /************************************************************************/
     256             : 
     257             : /** Class that implements GetNextFeature() by forwarding to
     258             :  * OGRLayerWithTranslateFeature::TranslateFeature() implementation, which
     259             :  * might return several features, and must apply layer filters.
     260             :  */
     261         347 : class GDALVectorPipelineOutputLayer /* non final */
     262             :     : public OGRLayerWithTranslateFeature
     263             : {
     264             :   protected:
     265             :     explicit GDALVectorPipelineOutputLayer(OGRLayer &oSrcLayer);
     266             :     ~GDALVectorPipelineOutputLayer() override;
     267             : 
     268             :     OGRLayer &m_srcLayer;
     269             : 
     270             :     void FailTranslation()
     271             :     {
     272             :         m_translateError = true;
     273             :     }
     274             : 
     275             :     bool PassesFilters(const OGRFeature *poFeature);
     276             : 
     277             :   public:
     278             :     void ResetReading() override;
     279             : 
     280             :     OGRFeature *GetNextFeature() override final;
     281             : 
     282             :   private:
     283             :     std::vector<std::unique_ptr<OGRFeature>> m_pendingFeatures{};
     284             :     size_t m_idxInPendingFeatures = 0;
     285             :     bool m_translateError = false;
     286             : };
     287             : 
     288             : /************************************************************************/
     289             : /*                  GDALVectorPipelinePassthroughLayer                  */
     290             : /************************************************************************/
     291             : 
     292             : /** Class that forwards GetNextFeature() calls to the source layer and
     293             :  * can be added to GDALVectorPipelineOutputDataset::AddLayer()
     294             :  */
     295             : class GDALVectorPipelinePassthroughLayer /* non final */
     296             :     : public GDALVectorPipelineOutputLayer
     297             : {
     298             :   public:
     299          75 :     explicit GDALVectorPipelinePassthroughLayer(OGRLayer &oSrcLayer)
     300          75 :         : GDALVectorPipelineOutputLayer(oSrcLayer)
     301             :     {
     302          75 :         GDALVectorPipelinePassthroughLayer::SetDescription(
     303          75 :             oSrcLayer.GetDescription());
     304          75 :     }
     305             : 
     306             :     const OGRFeatureDefn *GetLayerDefn() const override;
     307             : 
     308         284 :     int TestCapability(const char *pszCap) const override
     309             :     {
     310         284 :         if (EQUAL(pszCap, OLCFastFeatureCount))
     311           0 :             return false;
     312         284 :         return m_srcLayer.TestCapability(pszCap);
     313             :     }
     314             : 
     315          19 :     OGRErr IGetExtent(int iGeomField, OGREnvelope *psExtent,
     316             :                       bool bForce) override
     317             :     {
     318          19 :         return m_srcLayer.GetExtent(iGeomField, psExtent, bForce);
     319             :     }
     320             : 
     321           1 :     OGRErr IGetExtent3D(int iGeomField, OGREnvelope3D *psExtent,
     322             :                         bool bForce) override
     323             :     {
     324           1 :         return m_srcLayer.GetExtent3D(iGeomField, psExtent, bForce);
     325             :     }
     326             : 
     327             :     bool TranslateFeature(
     328             :         std::unique_ptr<OGRFeature> poSrcFeature,
     329             :         std::vector<std::unique_ptr<OGRFeature>> &apoOutFeatures) override;
     330             : };
     331             : 
     332             : /************************************************************************/
     333             : /*                 GDALVectorNonStreamingAlgorithmLayer                 */
     334             : /************************************************************************/
     335             : 
     336             : /**
     337             :  * This class represents a layer for algorithms that process vector data
     338             :  * in a non-streaming manner.
     339             :  *
     340             :  * Implementations must override the following methods:
     341             :  * - Process(), which is called when the first feature is read
     342             :  * - GetNextProcessedFeature() method which provides features in sequential order
     343             :  */
     344          72 : class GDALVectorNonStreamingAlgorithmLayer
     345             :     : public OGRLayer,
     346             :       public OGRGetNextFeatureThroughRaw<GDALVectorNonStreamingAlgorithmLayer>
     347             : {
     348             :   public:
     349             :     GDALVectorNonStreamingAlgorithmLayer(OGRLayer &srcLayer,
     350             :                                          int geomFieldIndex);
     351             : 
     352             :     ~GDALVectorNonStreamingAlgorithmLayer() override;
     353             : 
     354           6 :     const char *GetDescription() const override
     355             :     {
     356           6 :         return GetName();
     357             :     }
     358             : 
     359             :     virtual bool Process(GDALProgressFunc pfnProgress, void *pProgressData) = 0;
     360             : 
     361             :     virtual std::unique_ptr<OGRFeature> GetNextProcessedFeature() = 0;
     362             : 
     363             :     OGRFeature *GetNextRawFeature();
     364             : 
     365        2143 :     DEFINE_GET_NEXT_FEATURE_THROUGH_RAW(GDALVectorNonStreamingAlgorithmLayer)
     366             : 
     367             :   protected:
     368             :     OGRLayer &m_srcLayer;
     369             :     int m_geomFieldIndex{0};
     370             : 
     371             :   private:
     372             :     CPL_DISALLOW_COPY_ASSIGN(GDALVectorNonStreamingAlgorithmLayer)
     373             : };
     374             : 
     375             : /************************************************************************/
     376             : /*                GDALVectorNonStreamingAlgorithmDataset                */
     377             : /************************************************************************/
     378             : 
     379             : /**
     380             :  * Dataset used to read all input features into memory and perform some
     381             :  * processing.
     382             :  */
     383         160 : class GDALVectorNonStreamingAlgorithmDataset /* non final */
     384             :     : public GDALVectorDecoratedDataset
     385             : {
     386             :   public:
     387             :     explicit GDALVectorNonStreamingAlgorithmDataset(GDALDataset &oSrcDS);
     388             :     ~GDALVectorNonStreamingAlgorithmDataset() override;
     389             : 
     390             :     /** Add a layer to the dataset and perform the associated processing. */
     391             :     bool AddProcessedLayer(
     392             :         std::unique_ptr<GDALVectorNonStreamingAlgorithmLayer> srcLayer,
     393             :         GDALProgressFunc progressFunc, void *progressData);
     394             : 
     395             :     void AddPassThroughLayer(OGRLayer &oLayer);
     396             : 
     397             :     int GetLayerCount() const final override;
     398             :     OGRLayer *GetLayer(int idx) const final override;
     399             :     int TestCapability(const char *pszCap) const override;
     400             : 
     401             :   private:
     402             :     std::vector<std::unique_ptr<OGRLayer>> m_owned_layers{};
     403             :     std::vector<OGRLayer *> m_layers{};
     404             : };
     405             : 
     406             : /************************************************************************/
     407             : /*                   GDALVectorPipelineOutputDataset                    */
     408             : /************************************************************************/
     409             : 
     410             : /** Class used by vector pipeline steps to create an output on-the-fly
     411             :  * dataset where they can store on-the-fly layers.
     412             :  */
     413             : class GDALVectorPipelineOutputDataset /* non final */
     414             :     : public GDALVectorDecoratedDataset
     415             : {
     416             :     std::map<OGRLayer *, OGRLayerWithTranslateFeature *>
     417             :         m_mapSrcLayerToNewLayer{};
     418             :     std::vector<std::unique_ptr<OGRLayerWithTranslateFeature>>
     419             :         m_layersToDestroy{};
     420             :     std::vector<OGRLayerWithTranslateFeature *> m_layers{};
     421             : 
     422             :     OGRLayerWithTranslateFeature *m_belongingLayer = nullptr;
     423             :     std::vector<std::unique_ptr<OGRFeature>> m_pendingFeatures{};
     424             :     size_t m_idxInPendingFeatures = 0;
     425             : 
     426             :     CPL_DISALLOW_COPY_ASSIGN(GDALVectorPipelineOutputDataset)
     427             : 
     428             :   public:
     429             :     explicit GDALVectorPipelineOutputDataset(GDALDataset &oSrcDS);
     430             : 
     431             :     void AddLayer(OGRLayer &oSrcLayer,
     432             :                   std::unique_ptr<OGRLayerWithTranslateFeature> poNewLayer);
     433             : 
     434             :     int GetLayerCount() const override;
     435             : 
     436             :     OGRLayer *GetLayer(int idx) const override;
     437             : 
     438             :     int TestCapability(const char *pszCap) const override;
     439             : 
     440             :     void ResetReading() override;
     441             : 
     442             :     OGRFeature *GetNextFeature(OGRLayer **ppoBelongingLayer,
     443             :                                double *pdfProgressPct,
     444             :                                GDALProgressFunc pfnProgress,
     445             :                                void *pProgressData) override;
     446             : };
     447             : 
     448             : //! @endcond
     449             : 
     450             : #endif

Generated by: LCOV version 1.14