LCOV - code coverage report
Current view: top level - apps - gdalvectorpipelinestepalgorithm.h (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 65 66 98.5 %
Date: 2026-06-03 12:46:18 Functions: 31 35 88.6 %

          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        4908 : 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         602 :     int GetInputType() const override
      53             :     {
      54         602 :         return GDAL_OF_VECTOR;
      55             :     }
      56             : 
      57         531 :     int GetOutputType() const override
      58             :     {
      59         531 :         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          17 :     CSLConstList GetMetadata(const char *pszDomain) override
      77             :     {
      78          17 :         return m_srcDS.GetMetadata(pszDomain);
      79             :     }
      80             : 
      81          13 :     const char *GetMetadataItem(const char *pszName,
      82             :                                 const char *pszDomain) override
      83             :     {
      84          13 :         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         115 :     GetRelationshipNames(CSLConstList papszOptions) const override
     100             :     {
     101         115 :         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 final : public GDALVectorDecoratedDataset
     124             : {
     125             : 
     126             :   public:
     127             :     explicit GDALVectorOutputDataset(GDALDataset *poSrcDS);
     128             : 
     129          38 :     int GetLayerCount() const override
     130             :     {
     131          38 :         return static_cast<int>(m_layers.size());
     132             :     }
     133             : 
     134          18 :     const OGRLayer *GetLayer(int idx) const override
     135             :     {
     136          18 :         return m_layers[idx].get();
     137             :     }
     138             : 
     139             :     int TestCapability(const char *) const override;
     140             : 
     141          18 :     void AddLayer(std::unique_ptr<OGRLayer> layer)
     142             :     {
     143          18 :         m_layers.emplace_back(std::move(layer));
     144          18 :     }
     145             : 
     146             :   private:
     147             :     std::vector<std::unique_ptr<OGRLayer>> m_layers{};
     148             : };
     149             : 
     150             : /************************************************************************/
     151             : /*                GDALVectorAlgorithmLayerProgressHelper                */
     152             : /************************************************************************/
     153             : 
     154             : /**
     155             :  * This class helps doing progress report for algorithm iterating over layers
     156             :  * of the source dataset.
     157             :  */
     158             : class GDALVectorAlgorithmLayerProgressHelper
     159             : {
     160             :   public:
     161             :     /** Constructor */
     162             :     GDALVectorAlgorithmLayerProgressHelper(GDALProgressFunc pfnProgress,
     163             :                                            void *pProgressData);
     164             :     /** Constructor */
     165             :     explicit GDALVectorAlgorithmLayerProgressHelper(
     166             :         const GDALPipelineStepRunContext &ctxt);
     167             : 
     168             :     /** Register the passed layer as a layer that will be processed. */
     169             :     void AddProcessedLayer(OGRLayer &srcLayer);
     170             : 
     171             :     /** Register the passed layer as a layer that will be forwarded without
     172             :      * processing. */
     173             :     void AddPassThroughLayer(OGRLayer &srcLayer);
     174             : 
     175             :     //! @cond Doxygen_Suppress
     176             :     class iterator
     177             :     {
     178             :       public:
     179         150 :         explicit iterator(const GDALVectorAlgorithmLayerProgressHelper &helper,
     180             :                           bool start)
     181         150 :             : m_helper(helper),
     182         150 :               m_nLayerIdx(start ? 0 : m_helper.m_apoSrcLayers.size())
     183             :         {
     184         150 :         }
     185             : 
     186             :         inline bool operator==(const iterator &other) const
     187             :         {
     188             :             return m_nLayerIdx == other.m_nLayerIdx;
     189             :         }
     190             : 
     191         148 :         inline bool operator!=(const iterator &other) const
     192             :         {
     193         148 :             return m_nLayerIdx != other.m_nLayerIdx;
     194             :         }
     195             : 
     196          73 :         inline iterator &operator++()
     197             :         {
     198          73 :             if (!m_helper.m_anFeatures.empty())
     199          67 :                 m_nFeatureIdx += m_helper.m_anFeatures[m_nProcessedLayerIdx];
     200          73 :             if (m_helper.m_apoSrcLayers[m_nLayerIdx].second)
     201          65 :                 ++m_nProcessedLayerIdx;
     202          73 :             ++m_nLayerIdx;
     203          73 :             return *this;
     204             :         }
     205             : 
     206             :         using progress_data_unique_ptr =
     207             :             std::unique_ptr<void, decltype(&GDALDestroyScaledProgress)>;
     208             :         using value_type = std::tuple<OGRLayer *, bool, GDALProgressFunc,
     209             :                                       progress_data_unique_ptr>;
     210             : 
     211             :         value_type operator*() const;
     212             : 
     213             :       private:
     214             :         const GDALVectorAlgorithmLayerProgressHelper &m_helper;
     215             :         size_t m_nLayerIdx = 0;
     216             :         size_t m_nProcessedLayerIdx = 0;
     217             :         GIntBig m_nFeatureIdx = 0;
     218             :     };
     219             : 
     220             :     //! @endcond
     221             : 
     222             :     /** Start of an iterator over layers registered with AddProcessedLayer()
     223             :      * and AddUnprocessedLayer() */
     224          75 :     iterator begin() const
     225             :     {
     226          75 :         return iterator(*this, true);
     227             :     }
     228             : 
     229             :     /** End of an iterator over layers registered with AddProcessedLayer()
     230             :      * and AddUnprocessedLayer() */
     231          75 :     iterator end() const
     232             :     {
     233          75 :         return iterator(*this, false);
     234             :     }
     235             : 
     236             :     /** Return if AddProcessedLayer() has been called at least once. */
     237           4 :     bool HasProcessedLayers() const
     238             :     {
     239           4 :         return !m_anFeatures.empty();
     240             :     }
     241             : 
     242             :   private:
     243             :     GDALProgressFunc m_pfnProgress = nullptr;
     244             :     void *m_pProgressData = nullptr;
     245             :     int64_t m_nTotalFeatures = 0;
     246             :     std::vector<std::pair<OGRLayer *, bool>> m_apoSrcLayers{};
     247             :     std::vector<int64_t> m_anFeatures{};
     248             : 
     249             :     CPL_DISALLOW_COPY_ASSIGN(GDALVectorAlgorithmLayerProgressHelper)
     250             : };
     251             : 
     252             : /************************************************************************/
     253             : /*                    GDALVectorPipelineOutputLayer                     */
     254             : /************************************************************************/
     255             : 
     256             : /** Class that implements GetNextFeature() by forwarding to
     257             :  * OGRLayerWithTranslateFeature::TranslateFeature() implementation, which
     258             :  * might return several features.
     259             :  */
     260         306 : class GDALVectorPipelineOutputLayer /* non final */
     261             :     : public OGRLayerWithTranslateFeature,
     262             :       public OGRGetNextFeatureThroughRaw<GDALVectorPipelineOutputLayer>
     263             : {
     264             :   protected:
     265             :     explicit GDALVectorPipelineOutputLayer(OGRLayer &oSrcLayer);
     266             :     ~GDALVectorPipelineOutputLayer() override;
     267             : 
     268        4801 :     DEFINE_GET_NEXT_FEATURE_THROUGH_RAW(GDALVectorPipelineOutputLayer)
     269             : 
     270             :     OGRLayer &m_srcLayer;
     271             : 
     272           7 :     void FailTranslation()
     273             :     {
     274           7 :         m_translateError = true;
     275           7 :     }
     276             : 
     277             :   public:
     278             :     void ResetReading() override;
     279             :     OGRFeature *GetNextRawFeature();
     280             : 
     281             :   private:
     282             :     std::vector<std::unique_ptr<OGRFeature>> m_pendingFeatures{};
     283             :     size_t m_idxInPendingFeatures = 0;
     284             :     bool m_translateError = false;
     285             : };
     286             : 
     287             : /************************************************************************/
     288             : /*                  GDALVectorPipelinePassthroughLayer                  */
     289             : /************************************************************************/
     290             : 
     291             : /** Class that forwards GetNextFeature() calls to the source layer and
     292             :  * can be added to GDALVectorPipelineOutputDataset::AddLayer()
     293             :  */
     294             : class GDALVectorPipelinePassthroughLayer /* non final */
     295             :     : public GDALVectorPipelineOutputLayer
     296             : {
     297             :   public:
     298          68 :     explicit GDALVectorPipelinePassthroughLayer(OGRLayer &oSrcLayer)
     299          68 :         : GDALVectorPipelineOutputLayer(oSrcLayer)
     300             :     {
     301          68 :         GDALVectorPipelinePassthroughLayer::SetDescription(
     302          68 :             oSrcLayer.GetDescription());
     303          68 :     }
     304             : 
     305             :     const OGRFeatureDefn *GetLayerDefn() const override;
     306             : 
     307         278 :     int TestCapability(const char *pszCap) const override
     308             :     {
     309         278 :         if (EQUAL(pszCap, OLCFastFeatureCount))
     310           0 :             return false;
     311         278 :         return m_srcLayer.TestCapability(pszCap);
     312             :     }
     313             : 
     314          19 :     OGRErr IGetExtent(int iGeomField, OGREnvelope *psExtent,
     315             :                       bool bForce) override
     316             :     {
     317          19 :         return m_srcLayer.GetExtent(iGeomField, psExtent, bForce);
     318             :     }
     319             : 
     320           1 :     OGRErr IGetExtent3D(int iGeomField, OGREnvelope3D *psExtent,
     321             :                         bool bForce) override
     322             :     {
     323           1 :         return m_srcLayer.GetExtent3D(iGeomField, psExtent, bForce);
     324             :     }
     325             : 
     326             :     void TranslateFeature(
     327             :         std::unique_ptr<OGRFeature> poSrcFeature,
     328             :         std::vector<std::unique_ptr<OGRFeature>> &apoOutFeatures) override;
     329             : };
     330             : 
     331             : /************************************************************************/
     332             : /*                 GDALVectorNonStreamingAlgorithmLayer                 */
     333             : /************************************************************************/
     334             : 
     335             : /**
     336             :  * This class represents a layer for algorithms that process vector data
     337             :  * in a non-streaming manner.
     338             :  *
     339             :  * Implementations must override the following methods:
     340             :  * - Process(), which is called when the first feature is read
     341             :  * - GetNextProcessedFeature() method which provides features in sequential order
     342             :  */
     343          71 : class GDALVectorNonStreamingAlgorithmLayer
     344             :     : public OGRLayer,
     345             :       public OGRGetNextFeatureThroughRaw<GDALVectorNonStreamingAlgorithmLayer>
     346             : {
     347             :   public:
     348             :     GDALVectorNonStreamingAlgorithmLayer(OGRLayer &srcLayer,
     349             :                                          int geomFieldIndex);
     350             : 
     351             :     ~GDALVectorNonStreamingAlgorithmLayer() override;
     352             : 
     353           5 :     const char *GetDescription() const override
     354             :     {
     355           5 :         return GetName();
     356             :     }
     357             : 
     358             :     virtual bool Process(GDALProgressFunc pfnProgress, void *pProgressData) = 0;
     359             : 
     360             :     virtual std::unique_ptr<OGRFeature> GetNextProcessedFeature() = 0;
     361             : 
     362             :     OGRFeature *GetNextRawFeature();
     363             : 
     364        2141 :     DEFINE_GET_NEXT_FEATURE_THROUGH_RAW(GDALVectorNonStreamingAlgorithmLayer)
     365             : 
     366             :   protected:
     367             :     OGRLayer &m_srcLayer;
     368             :     int m_geomFieldIndex{0};
     369             : 
     370             :   private:
     371             :     CPL_DISALLOW_COPY_ASSIGN(GDALVectorNonStreamingAlgorithmLayer)
     372             : };
     373             : 
     374             : /************************************************************************/
     375             : /*                GDALVectorNonStreamingAlgorithmDataset                */
     376             : /************************************************************************/
     377             : 
     378             : /**
     379             :  * Dataset used to read all input features into memory and perform some
     380             :  * processing.
     381             :  */
     382         158 : class GDALVectorNonStreamingAlgorithmDataset /* non final */
     383             :     : public GDALVectorDecoratedDataset
     384             : {
     385             :   public:
     386             :     explicit GDALVectorNonStreamingAlgorithmDataset(GDALDataset &oSrcDS);
     387             :     ~GDALVectorNonStreamingAlgorithmDataset() override;
     388             : 
     389             :     /** Add a layer to the dataset and perform the associated processing. */
     390             :     bool AddProcessedLayer(
     391             :         std::unique_ptr<GDALVectorNonStreamingAlgorithmLayer> srcLayer,
     392             :         GDALProgressFunc progressFunc, void *progressData);
     393             : 
     394             :     void AddPassThroughLayer(OGRLayer &oLayer);
     395             : 
     396             :     int GetLayerCount() const final override;
     397             :     OGRLayer *GetLayer(int idx) const final override;
     398             :     int TestCapability(const char *pszCap) const override;
     399             : 
     400             :   private:
     401             :     std::vector<std::unique_ptr<OGRLayer>> m_owned_layers{};
     402             :     std::vector<OGRLayer *> m_layers{};
     403             : };
     404             : 
     405             : /************************************************************************/
     406             : /*                   GDALVectorPipelineOutputDataset                    */
     407             : /************************************************************************/
     408             : 
     409             : /** Class used by vector pipeline steps to create an output on-the-fly
     410             :  * dataset where they can store on-the-fly layers.
     411             :  */
     412             : class GDALVectorPipelineOutputDataset /* non final */
     413             :     : public GDALVectorDecoratedDataset
     414             : {
     415             :     std::map<OGRLayer *, OGRLayerWithTranslateFeature *>
     416             :         m_mapSrcLayerToNewLayer{};
     417             :     std::vector<std::unique_ptr<OGRLayerWithTranslateFeature>>
     418             :         m_layersToDestroy{};
     419             :     std::vector<OGRLayerWithTranslateFeature *> m_layers{};
     420             : 
     421             :     OGRLayerWithTranslateFeature *m_belongingLayer = nullptr;
     422             :     std::vector<std::unique_ptr<OGRFeature>> m_pendingFeatures{};
     423             :     size_t m_idxInPendingFeatures = 0;
     424             : 
     425             :     CPL_DISALLOW_COPY_ASSIGN(GDALVectorPipelineOutputDataset)
     426             : 
     427             :   public:
     428             :     explicit GDALVectorPipelineOutputDataset(GDALDataset &oSrcDS);
     429             : 
     430             :     void AddLayer(OGRLayer &oSrcLayer,
     431             :                   std::unique_ptr<OGRLayerWithTranslateFeature> poNewLayer);
     432             : 
     433             :     int GetLayerCount() const override;
     434             : 
     435             :     OGRLayer *GetLayer(int idx) const override;
     436             : 
     437             :     int TestCapability(const char *pszCap) const override;
     438             : 
     439             :     void ResetReading() override;
     440             : 
     441             :     OGRFeature *GetNextFeature(OGRLayer **ppoBelongingLayer,
     442             :                                double *pdfProgressPct,
     443             :                                GDALProgressFunc pfnProgress,
     444             :                                void *pProgressData) override;
     445             : };
     446             : 
     447             : //! @endcond
     448             : 
     449             : #endif

Generated by: LCOV version 1.14