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 : 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 idx >= 0 && idx < GetLayerCount() ? m_layers[idx].get()
232 : nullptr;
233 }
234
235 int TestCapability(const char *) const override;
236
237 void AddLayer(std::unique_ptr<OGRLayer> layer)
238 {
239 m_layers.emplace_back(std::move(layer));
240 }
241
242 private:
243 std::vector<std::unique_ptr<OGRLayer>> m_layers{};
244};
245
246/************************************************************************/
247/* GDALVectorAlgorithmLayerProgressHelper */
248/************************************************************************/
249
254class GDALVectorAlgorithmLayerProgressHelper
255{
256 public:
258 GDALVectorAlgorithmLayerProgressHelper(GDALProgressFunc pfnProgress,
259 void *pProgressData);
261 explicit GDALVectorAlgorithmLayerProgressHelper(
262 const GDALPipelineStepRunContext &ctxt);
263
265 void AddProcessedLayer(OGRLayer &srcLayer);
266
269 void AddPassThroughLayer(OGRLayer &srcLayer);
270
272 class iterator
273 {
274 public:
275 explicit iterator(const GDALVectorAlgorithmLayerProgressHelper &helper,
276 bool start)
277 : m_helper(helper),
278 m_nLayerIdx(start ? 0 : m_helper.m_apoSrcLayers.size())
279 {
280 }
281
282 inline bool operator==(const iterator &other) const
283 {
284 return m_nLayerIdx == other.m_nLayerIdx;
285 }
286
287 inline bool operator!=(const iterator &other) const
288 {
289 return m_nLayerIdx != other.m_nLayerIdx;
290 }
291
292 inline iterator &operator++()
293 {
294 if (!m_helper.m_anFeatures.empty())
295 m_nFeatureIdx += m_helper.m_anFeatures[m_nProcessedLayerIdx];
296 if (m_helper.m_apoSrcLayers[m_nLayerIdx].second)
297 ++m_nProcessedLayerIdx;
298 ++m_nLayerIdx;
299 return *this;
300 }
301
302 using progress_data_unique_ptr =
303 std::unique_ptr<void, decltype(&GDALDestroyScaledProgress)>;
304 using value_type = std::tuple<OGRLayer *, bool, GDALProgressFunc,
305 progress_data_unique_ptr>;
306
307 value_type operator*() const;
308
309 private:
310 const GDALVectorAlgorithmLayerProgressHelper &m_helper;
311 size_t m_nLayerIdx = 0;
312 size_t m_nProcessedLayerIdx = 0;
313 GIntBig m_nFeatureIdx = 0;
314 };
315
317
320 iterator begin() const
321 {
322 return iterator(*this, true);
323 }
324
327 iterator end() const
328 {
329 return iterator(*this, false);
330 }
331
333 bool HasProcessedLayers() const
334 {
335 return !m_anFeatures.empty();
336 }
337
338 private:
339 GDALProgressFunc m_pfnProgress = nullptr;
340 void *m_pProgressData = nullptr;
341 int64_t m_nTotalFeatures = 0;
342 std::vector<std::pair<OGRLayer *, bool>> m_apoSrcLayers{};
343 std::vector<int64_t> m_anFeatures{};
344
345 CPL_DISALLOW_COPY_ASSIGN(GDALVectorAlgorithmLayerProgressHelper)
346};
347
348/************************************************************************/
349/* GDALVectorPipelineOutputLayer */
350/************************************************************************/
351
356class GDALVectorPipelineOutputLayer /* non final */
357 : public OGRLayerWithTranslateFeature
358{
359 protected:
360 explicit GDALVectorPipelineOutputLayer(OGRLayer &oSrcLayer);
361 ~GDALVectorPipelineOutputLayer() override;
362
363 OGRLayer &m_srcLayer;
364
365 void FailTranslation()
366 {
367 m_translateError = true;
368 }
369
370 bool PassesFilters(OGRFeature *poFeature);
371
372 public:
373 void ResetReading() override;
374
375 OGRFeature *GetNextFeature() override final;
376
377 private:
378 std::vector<std::unique_ptr<OGRFeature>> m_pendingFeatures{};
379 size_t m_idxInPendingFeatures = 0;
380 bool m_translateError = false;
381};
382
383/************************************************************************/
384/* GDALVectorPipelinePassthroughLayer */
385/************************************************************************/
386
390class GDALVectorPipelinePassthroughLayer /* non final */
391 : public GDALVectorPipelineOutputLayer
392{
393 public:
394 explicit GDALVectorPipelinePassthroughLayer(OGRLayer &oSrcLayer)
395 : GDALVectorPipelineOutputLayer(oSrcLayer)
396 {
397 SetDescription(oSrcLayer.GetDescription());
398 }
399
400 const OGRFeatureDefn *GetLayerDefn() const override;
401
402 int TestCapability(const char *pszCap) const override
403 {
404 if (EQUAL(pszCap, OLCFastFeatureCount))
405 return false;
406 return m_srcLayer.TestCapability(pszCap);
407 }
408
409 OGRErr IGetExtent(int iGeomField, OGREnvelope *psExtent,
410 bool bForce) override
411 {
412 return m_srcLayer.GetExtent(iGeomField, psExtent, bForce);
413 }
414
415 OGRErr IGetExtent3D(int iGeomField, OGREnvelope3D *psExtent,
416 bool bForce) override
417 {
418 return m_srcLayer.GetExtent3D(iGeomField, psExtent, bForce);
419 }
420
421 void TranslateFeature(
422 std::unique_ptr<OGRFeature> poSrcFeature,
423 std::vector<std::unique_ptr<OGRFeature>> &apoOutFeatures) override;
424};
425
426/************************************************************************/
427/* GDALVectorNonStreamingAlgorithmLayer */
428/************************************************************************/
429
438class GDALVectorNonStreamingAlgorithmLayer
439 : public OGRLayer,
440 public OGRGetNextFeatureThroughRaw<GDALVectorNonStreamingAlgorithmLayer>
441{
442 public:
443 GDALVectorNonStreamingAlgorithmLayer(OGRLayer &srcLayer,
444 int geomFieldIndex);
445
446 ~GDALVectorNonStreamingAlgorithmLayer() override;
447
448 const char *GetDescription() const override
449 {
450 return GetName();
451 }
452
453 virtual bool Process(GDALProgressFunc pfnProgress, void *pProgressData) = 0;
454
455 virtual std::unique_ptr<OGRFeature> GetNextProcessedFeature() = 0;
456
457 OGRFeature *GetNextRawFeature();
458
459 DEFINE_GET_NEXT_FEATURE_THROUGH_RAW(GDALVectorNonStreamingAlgorithmLayer)
460
461 protected:
462 OGRLayer &m_srcLayer;
463 int m_geomFieldIndex{0};
464
465 private:
466 CPL_DISALLOW_COPY_ASSIGN(GDALVectorNonStreamingAlgorithmLayer)
467};
468
469/************************************************************************/
470/* GDALVectorNonStreamingAlgorithmDataset */
471/************************************************************************/
472
477class GDALVectorNonStreamingAlgorithmDataset /* non final */
478 : public GDALVectorDecoratedDataset
479{
480 public:
481 explicit GDALVectorNonStreamingAlgorithmDataset(GDALDataset &oSrcDS);
482 ~GDALVectorNonStreamingAlgorithmDataset() override;
483
485 bool AddProcessedLayer(
486 std::unique_ptr<GDALVectorNonStreamingAlgorithmLayer> srcLayer,
487 GDALProgressFunc progressFunc, void *progressData);
488
489 void AddPassThroughLayer(OGRLayer &oLayer);
490
491 int GetLayerCount() const final override;
492 OGRLayer *GetLayer(int idx) const final override;
493 int TestCapability(const char *pszCap) const override;
494
495 private:
496 std::vector<std::unique_ptr<OGRLayer>> m_owned_layers{};
497 std::vector<OGRLayer *> m_layers{};
498};
499
500/************************************************************************/
501/* GDALVectorPipelineOutputDataset */
502/************************************************************************/
503
507class GDALVectorPipelineOutputDataset /* non final */
508 : public GDALVectorDecoratedDataset
509{
510 std::map<OGRLayer *, OGRLayerWithTranslateFeature *>
511 m_mapSrcLayerToNewLayer{};
512 std::vector<std::unique_ptr<OGRLayerWithTranslateFeature>>
513 m_layersToDestroy{};
514 std::vector<OGRLayerWithTranslateFeature *> m_layers{};
515
516 OGRLayerWithTranslateFeature *m_belongingLayer = nullptr;
517 std::vector<std::unique_ptr<OGRFeature>> m_pendingFeatures{};
518 size_t m_idxInPendingFeatures = 0;
519
520 CPL_DISALLOW_COPY_ASSIGN(GDALVectorPipelineOutputDataset)
521
522 public:
523 explicit GDALVectorPipelineOutputDataset(GDALDataset &oSrcDS);
524
525 void AddLayer(OGRLayer &oSrcLayer,
526 std::unique_ptr<OGRLayerWithTranslateFeature> poNewLayer);
527
528 int GetLayerCount() const override;
529
530 OGRLayer *GetLayer(int idx) const override;
531
532 int TestCapability(const char *pszCap) const override;
533
534 void ResetReading() override;
535
536 OGRFeature *GetNextFeature(OGRLayer **ppoBelongingLayer,
537 double *pdfProgressPct,
538 GDALProgressFunc pfnProgress,
539 void *pProgressData) override;
540};
541
543
544#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