GDAL
gdalalg_vector_pipeline.h
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 <tuple>
24#include <vector>
25
27
28/************************************************************************/
29/* GDALVectorPipelineStepAlgorithm */
30/************************************************************************/
31
32class GDALRasterAlgorithmStepRegistry;
33
34class GDALVectorPipelineStepAlgorithm /* non final */
35 : public GDALPipelineStepAlgorithm
36{
37 public:
38 ~GDALVectorPipelineStepAlgorithm() override;
39
40 protected:
41 GDALVectorPipelineStepAlgorithm(const std::string &name,
42 const std::string &description,
43 const std::string &helpURL,
44 bool standaloneStep);
45
46 GDALVectorPipelineStepAlgorithm(const std::string &name,
47 const std::string &description,
48 const std::string &helpURL,
49 const ConstructorOptions &options);
50
51 friend class GDALVectorPipelineAlgorithm;
52 friend class GDALVectorConcatAlgorithm;
53
54 int GetInputType() const override
55 {
56 return GDAL_OF_VECTOR;
57 }
58
59 int GetOutputType() const override
60 {
61 return GDAL_OF_VECTOR;
62 }
63};
64
65/************************************************************************/
66/* GDALVectorAlgorithmStepRegistry */
67/************************************************************************/
68
69class GDALVectorAlgorithmStepRegistry : public virtual GDALAlgorithmRegistry
70{
71 public:
72 GDALVectorAlgorithmStepRegistry() = default;
73 ~GDALVectorAlgorithmStepRegistry() override;
74
77 template <class MyAlgorithm>
78 bool Register(const std::string &name = std::string())
79 {
80 static_assert(
81 std::is_base_of_v<GDALVectorPipelineStepAlgorithm, MyAlgorithm>,
82 "Algorithm is not a GDALVectorPipelineStepAlgorithm");
83
84 AlgInfo info;
85 info.m_name = name.empty() ? MyAlgorithm::NAME : name;
86 info.m_aliases = MyAlgorithm::GetAliasesStatic();
87 info.m_creationFunc = []() -> std::unique_ptr<GDALAlgorithm>
88 { return std::make_unique<MyAlgorithm>(); };
90 }
91};
92
93/************************************************************************/
94/* GDALVectorPipelineAlgorithm */
95/************************************************************************/
96
97class GDALVectorPipelineAlgorithm final : public GDALAbstractPipelineAlgorithm
98{
99 public:
100 static constexpr const char *NAME = "pipeline";
101 static constexpr const char *DESCRIPTION =
102 "Process a vector dataset applying several steps.";
103 static constexpr const char *HELP_URL =
104 "/programs/gdal_vector_pipeline.html";
105
106 static std::vector<std::string> GetAliasesStatic()
107 {
108 return {
109#ifdef GDAL_PIPELINE_PROJ_NOSTALGIA
111 "+pipeline",
112 "+gdal=pipeline",
113#endif
114 };
115 }
116
117 GDALVectorPipelineAlgorithm();
118
119 std::string GetUsageForCLI(bool shortUsage,
120 const UsageOptions &usageOptions) const override;
121
122 static void RegisterAlgorithms(GDALVectorAlgorithmStepRegistry &registry,
123 bool forMixedPipeline);
124
125 int GetInputType() const override
126 {
127 return GDAL_OF_VECTOR;
128 }
129
130 int GetOutputType() const override
131 {
132 return GDAL_OF_VECTOR;
133 }
134
135 protected:
136 GDALVectorAlgorithmStepRegistry m_stepRegistry{};
137
138 GDALAlgorithmRegistry &GetStepRegistry() override
139 {
140 return m_stepRegistry;
141 }
142
143 const GDALAlgorithmRegistry &GetStepRegistry() const override
144 {
145 return m_stepRegistry;
146 }
147
148 private:
149 std::unique_ptr<GDALAbstractPipelineAlgorithm>
150 CreateNestedPipeline() const override
151 {
152 auto pipeline = std::make_unique<GDALVectorPipelineAlgorithm>();
153 pipeline->m_bInnerPipeline = true;
154 return pipeline;
155 }
156};
157
158/************************************************************************/
159/* GDALVectorDecoratedDataset */
160/************************************************************************/
161
165class GDALVectorDecoratedDataset /* non final */
166 : public GDALDataset
167{
168 public:
169 ~GDALVectorDecoratedDataset() override;
170
171 CSLConstList GetMetadata(const char *pszDomain) override
172 {
173 return m_srcDS.GetMetadata(pszDomain);
174 }
175
176 const char *GetMetadataItem(const char *pszName,
177 const char *pszDomain) override
178 {
179 return m_srcDS.GetMetadataItem(pszName, pszDomain);
180 }
181
182 std::vector<std::string>
183 GetFieldDomainNames(CSLConstList papszOptions) const override
184 {
185 return m_srcDS.GetFieldDomainNames(papszOptions);
186 }
187
188 const OGRFieldDomain *GetFieldDomain(const std::string &name) const override
189 {
190 return m_srcDS.GetFieldDomain(name);
191 }
192
193 std::vector<std::string>
194 GetRelationshipNames(CSLConstList papszOptions) const override
195 {
196 return m_srcDS.GetRelationshipNames(papszOptions);
197 }
198
199 const GDALRelationship *
200 GetRelationship(const std::string &name) const override
201 {
202 return m_srcDS.GetRelationship(name);
203 }
204
205 private:
206 std::unique_ptr<GDALDataset> m_dummySrcDS{};
207
208 protected:
209 explicit GDALVectorDecoratedDataset(GDALDataset *poSrcDS);
210
211 GDALDataset &m_srcDS;
212};
213
214/************************************************************************/
215/* GDALVectorOutputDataset */
216/************************************************************************/
217
218class GDALVectorOutputDataset final : public GDALVectorDecoratedDataset
219{
220
221 public:
222 explicit GDALVectorOutputDataset(GDALDataset *poSrcDS);
223
224 int GetLayerCount() const override
225 {
226 return static_cast<int>(m_layers.size());
227 }
228
229 const OGRLayer *GetLayer(int idx) const override
230 {
231 return m_layers[idx].get();
232 }
233
234 int TestCapability(const char *) const override;
235
236 void AddLayer(std::unique_ptr<OGRLayer> layer)
237 {
238 m_layers.emplace_back(std::move(layer));
239 }
240
241 private:
242 std::vector<std::unique_ptr<OGRLayer>> m_layers{};
243};
244
245/************************************************************************/
246/* GDALVectorAlgorithmLayerProgressHelper */
247/************************************************************************/
248
253class GDALVectorAlgorithmLayerProgressHelper
254{
255 public:
257 GDALVectorAlgorithmLayerProgressHelper(GDALProgressFunc pfnProgress,
258 void *pProgressData);
260 explicit GDALVectorAlgorithmLayerProgressHelper(
261 const GDALPipelineStepRunContext &ctxt);
262
264 void AddProcessedLayer(OGRLayer &srcLayer);
265
268 void AddPassThroughLayer(OGRLayer &srcLayer);
269
271 class iterator
272 {
273 public:
274 explicit iterator(const GDALVectorAlgorithmLayerProgressHelper &helper,
275 bool start)
276 : m_helper(helper),
277 m_nLayerIdx(start ? 0 : m_helper.m_apoSrcLayers.size())
278 {
279 }
280
281 inline bool operator==(const iterator &other) const
282 {
283 return m_nLayerIdx == other.m_nLayerIdx;
284 }
285
286 inline bool operator!=(const iterator &other) const
287 {
288 return m_nLayerIdx != other.m_nLayerIdx;
289 }
290
291 inline iterator &operator++()
292 {
293 if (!m_helper.m_anFeatures.empty())
294 m_nFeatureIdx += m_helper.m_anFeatures[m_nProcessedLayerIdx];
295 if (m_helper.m_apoSrcLayers[m_nLayerIdx].second)
296 ++m_nProcessedLayerIdx;
297 ++m_nLayerIdx;
298 return *this;
299 }
300
301 using progress_data_unique_ptr =
302 std::unique_ptr<void, decltype(&GDALDestroyScaledProgress)>;
303 using value_type = std::tuple<OGRLayer *, bool, GDALProgressFunc,
304 progress_data_unique_ptr>;
305
306 value_type operator*() const;
307
308 private:
309 const GDALVectorAlgorithmLayerProgressHelper &m_helper;
310 size_t m_nLayerIdx = 0;
311 size_t m_nProcessedLayerIdx = 0;
312 GIntBig m_nFeatureIdx = 0;
313 };
314
316
319 iterator begin() const
320 {
321 return iterator(*this, true);
322 }
323
326 iterator end() const
327 {
328 return iterator(*this, false);
329 }
330
332 bool HasProcessedLayers() const
333 {
334 return !m_anFeatures.empty();
335 }
336
337 private:
338 GDALProgressFunc m_pfnProgress = nullptr;
339 void *m_pProgressData = nullptr;
340 int64_t m_nTotalFeatures = 0;
341 std::vector<std::pair<OGRLayer *, bool>> m_apoSrcLayers{};
342 std::vector<int64_t> m_anFeatures{};
343
344 CPL_DISALLOW_COPY_ASSIGN(GDALVectorAlgorithmLayerProgressHelper)
345};
346
347/************************************************************************/
348/* GDALVectorPipelineOutputLayer */
349/************************************************************************/
350
355class GDALVectorPipelineOutputLayer /* non final */
356 : public OGRLayerWithTranslateFeature,
357 public OGRGetNextFeatureThroughRaw<GDALVectorPipelineOutputLayer>
358{
359 protected:
360 explicit GDALVectorPipelineOutputLayer(OGRLayer &oSrcLayer);
361 ~GDALVectorPipelineOutputLayer() override;
362
363 DEFINE_GET_NEXT_FEATURE_THROUGH_RAW(GDALVectorPipelineOutputLayer)
364
365 OGRLayer &m_srcLayer;
366
367 void FailTranslation()
368 {
369 m_translateError = true;
370 }
371
372 public:
373 void ResetReading() override;
374 OGRFeature *GetNextRawFeature();
375
376 private:
377 std::vector<std::unique_ptr<OGRFeature>> m_pendingFeatures{};
378 size_t m_idxInPendingFeatures = 0;
379 bool m_translateError = false;
380};
381
382/************************************************************************/
383/* GDALVectorPipelinePassthroughLayer */
384/************************************************************************/
385
389class GDALVectorPipelinePassthroughLayer /* non final */
390 : public GDALVectorPipelineOutputLayer
391{
392 public:
393 explicit GDALVectorPipelinePassthroughLayer(OGRLayer &oSrcLayer)
394 : GDALVectorPipelineOutputLayer(oSrcLayer)
395 {
396 SetDescription(oSrcLayer.GetDescription());
397 }
398
399 const OGRFeatureDefn *GetLayerDefn() const override;
400
401 int TestCapability(const char *pszCap) const override
402 {
403 if (EQUAL(pszCap, OLCFastFeatureCount))
404 return false;
405 return m_srcLayer.TestCapability(pszCap);
406 }
407
408 OGRErr IGetExtent(int iGeomField, OGREnvelope *psExtent,
409 bool bForce) override
410 {
411 return m_srcLayer.GetExtent(iGeomField, psExtent, bForce);
412 }
413
414 OGRErr IGetExtent3D(int iGeomField, OGREnvelope3D *psExtent,
415 bool bForce) override
416 {
417 return m_srcLayer.GetExtent3D(iGeomField, psExtent, bForce);
418 }
419
420 void TranslateFeature(
421 std::unique_ptr<OGRFeature> poSrcFeature,
422 std::vector<std::unique_ptr<OGRFeature>> &apoOutFeatures) override;
423};
424
425/************************************************************************/
426/* GDALVectorNonStreamingAlgorithmLayer */
427/************************************************************************/
428
437class GDALVectorNonStreamingAlgorithmLayer
438 : public OGRLayer,
439 public OGRGetNextFeatureThroughRaw<GDALVectorNonStreamingAlgorithmLayer>
440{
441 public:
442 GDALVectorNonStreamingAlgorithmLayer(OGRLayer &srcLayer,
443 int geomFieldIndex);
444
445 ~GDALVectorNonStreamingAlgorithmLayer() override;
446
447 const char *GetDescription() const override
448 {
449 return GetName();
450 }
451
452 virtual bool Process(GDALProgressFunc pfnProgress, void *pProgressData) = 0;
453
454 virtual std::unique_ptr<OGRFeature> GetNextProcessedFeature() = 0;
455
456 OGRFeature *GetNextRawFeature();
457
458 DEFINE_GET_NEXT_FEATURE_THROUGH_RAW(GDALVectorNonStreamingAlgorithmLayer)
459
460 protected:
461 OGRLayer &m_srcLayer;
462 int m_geomFieldIndex{0};
463
464 private:
465 CPL_DISALLOW_COPY_ASSIGN(GDALVectorNonStreamingAlgorithmLayer)
466};
467
468/************************************************************************/
469/* GDALVectorNonStreamingAlgorithmDataset */
470/************************************************************************/
471
476class GDALVectorNonStreamingAlgorithmDataset /* non final */
477 : public GDALVectorDecoratedDataset
478{
479 public:
480 explicit GDALVectorNonStreamingAlgorithmDataset(GDALDataset &oSrcDS);
481 ~GDALVectorNonStreamingAlgorithmDataset() override;
482
484 bool AddProcessedLayer(
485 std::unique_ptr<GDALVectorNonStreamingAlgorithmLayer> srcLayer,
486 GDALProgressFunc progressFunc, void *progressData);
487
488 void AddPassThroughLayer(OGRLayer &oLayer);
489
490 int GetLayerCount() const final override;
491 OGRLayer *GetLayer(int idx) const final override;
492 int TestCapability(const char *pszCap) const override;
493
494 private:
495 std::vector<std::unique_ptr<OGRLayer>> m_owned_layers{};
496 std::vector<OGRLayer *> m_layers{};
497};
498
499/************************************************************************/
500/* GDALVectorPipelineOutputDataset */
501/************************************************************************/
502
506class GDALVectorPipelineOutputDataset /* non final */
507 : public GDALVectorDecoratedDataset
508{
509 std::map<OGRLayer *, OGRLayerWithTranslateFeature *>
510 m_mapSrcLayerToNewLayer{};
511 std::vector<std::unique_ptr<OGRLayerWithTranslateFeature>>
512 m_layersToDestroy{};
513 std::vector<OGRLayerWithTranslateFeature *> m_layers{};
514
515 OGRLayerWithTranslateFeature *m_belongingLayer = nullptr;
516 std::vector<std::unique_ptr<OGRFeature>> m_pendingFeatures{};
517 size_t m_idxInPendingFeatures = 0;
518
519 CPL_DISALLOW_COPY_ASSIGN(GDALVectorPipelineOutputDataset)
520
521 public:
522 explicit GDALVectorPipelineOutputDataset(GDALDataset &oSrcDS);
523
524 void AddLayer(OGRLayer &oSrcLayer,
525 std::unique_ptr<OGRLayerWithTranslateFeature> poNewLayer);
526
527 int GetLayerCount() const override;
528
529 OGRLayer *GetLayer(int idx) const override;
530
531 int TestCapability(const char *pszCap) const override;
532
533 void ResetReading() override;
534
535 OGRFeature *GetNextFeature(OGRLayer **ppoBelongingLayer,
536 double *pdfProgressPct,
537 GDALProgressFunc pfnProgress,
538 void *pProgressData) override;
539};
540
542
543#endif
Registry of GDAL algorithms.
Definition gdalalgorithm_cpp.h:2316
static constexpr const char * HIDDEN_ALIAS_SEPARATOR
Special value to put in m_aliases to separate public alias from hidden aliases.
Definition gdalalgorithm_cpp.h:2320
bool Register()
Register the algorithm of type MyAlgorithm.
Definition gdalalgorithm_cpp.h:2343
A set of associated raster bands, usually from one file.
Definition gdal_dataset.h:77
virtual const GDALRelationship * GetRelationship(const std::string &name) const
Get a relationship from its name.
Definition gdaldataset.cpp:10542
virtual const OGRFieldDomain * GetFieldDomain(const std::string &name) const
Get a field domain from its name.
Definition gdaldataset.cpp:10225
virtual std::vector< std::string > GetRelationshipNames(CSLConstList papszOptions=nullptr) const
Returns a list of the names of all relationships stored in the dataset.
Definition gdaldataset.cpp:10498
void static void CSLConstList GetMetadata(const char *pszDomain="") override
Fetch metadata.
Definition gdaldataset.cpp:5217
virtual std::vector< std::string > GetFieldDomainNames(CSLConstList papszOptions=nullptr) const
Returns a list of the names of all field domains stored in the dataset.
Definition gdaldataset.cpp:10175
virtual const char * GetMetadataItem(const char *pszName, const char *pszDomain="")
Fetch single metadata item.
Definition gdalmajorobject.cpp:322
virtual const char * GetDescription() const
Fetch object description.
Definition gdalmajorobject.cpp:61
Definition of a table relationship.
Definition gdal_relationship.h:38
Simple container for a bounding region in 3D.
Definition ogr_core.h:217
Simple container for a bounding region (rectangle)
Definition ogr_core.h:44
Definition of a feature class or feature layer.
Definition ogr_feature.h:521
A simple feature, including geometry and attributes.
Definition ogr_feature.h:1041
Definition of a field domain.
Definition ogr_feature.h:1780
Template class offering a GetNextFeature() implementation relying on GetNextRawFeature().
Definition ogrsf_frmts.h:509
This class represents a layer of simple features, with access methods.
Definition ogrsf_frmts.h:61
virtual const char * GetName() const
Return the layer name.
Definition ogrlayer.cpp:4807
#define EQUAL(a, b)
Alias for strcasecmp() == 0.
Definition cpl_port.h:532
#define CPL_DISALLOW_COPY_ASSIGN(ClassName)
Helper to remove the copy and assignment constructors so that the compiler will not generate the defa...
Definition cpl_port.h:1101
char ** CSLConstList
Type of a constant null-terminated list of nul terminated strings.
Definition cpl_port.h:1252
long long GIntBig
Large signed integer type (generally 64-bit integer type).
Definition cpl_port.h:195
#define GDAL_OF_VECTOR
Allow vector drivers to be used.
Definition gdal.h:1130
#define OLCFastFeatureCount
Layer capability for fast feature count retrieval .
Definition ogr_core.h:983
int OGRErr
Type for a OGR error.
Definition ogr_core.h:388
Classes related to registration of format support, and opening datasets.
OGRLayer::FeatureIterator begin(OGRLayer *poLayer)
Return begin of feature iterator.
Definition ogrsf_frmts.h:478
OGRLayer::FeatureIterator end(OGRLayer *poLayer)
Return end of feature iterator.
Definition ogrsf_frmts.h:486
#define DEFINE_GET_NEXT_FEATURE_THROUGH_RAW(BaseLayer)
Utility macro to define GetNextFeature() through GetNextRawFeature()
Definition ogrsf_frmts.h:539