Coverage Report

Created: 2026-04-01 06:20

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gdal/apps/gdalalg_vector_pipeline.cpp
Line
Count
Source
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
#include "gdalalg_vector_pipeline.h"
14
#include "gdalalg_external.h"
15
#include "gdalalg_materialize.h"
16
#include "gdalalg_vector_read.h"
17
#include "gdalalg_vector_buffer.h"
18
#include "gdalalg_vector_check_coverage.h"
19
#include "gdalalg_vector_check_geometry.h"
20
#include "gdalalg_vector_clean_coverage.h"
21
#include "gdalalg_vector_clip.h"
22
#include "gdalalg_vector_combine.h"
23
#include "gdalalg_vector_concat.h"
24
#include "gdalalg_vector_concave_hull.h"
25
#include "gdalalg_vector_convex_hull.h"
26
#include "gdalalg_vector_create.h"
27
#include "gdalalg_vector_dissolve.h"
28
#include "gdalalg_vector_edit.h"
29
#include "gdalalg_vector_explode_collections.h"
30
#include "gdalalg_vector_export_schema.h"
31
#include "gdalalg_vector_filter.h"
32
#include "gdalalg_vector_info.h"
33
#include "gdalalg_vector_limit.h"
34
#include "gdalalg_vector_make_point.h"
35
#include "gdalalg_vector_make_valid.h"
36
#include "gdalalg_vector_partition.h"
37
#include "gdalalg_vector_rename_layer.h"
38
#include "gdalalg_vector_reproject.h"
39
#include "gdalalg_vector_segmentize.h"
40
#include "gdalalg_vector_select.h"
41
#include "gdalalg_vector_set_field_type.h"
42
#include "gdalalg_vector_set_geom_type.h"
43
#include "gdalalg_vector_simplify.h"
44
#include "gdalalg_vector_simplify_coverage.h"
45
#include "gdalalg_vector_sort.h"
46
#include "gdalalg_vector_sql.h"
47
#include "gdalalg_vector_swap_xy.h"
48
#include "gdalalg_vector_update.h"
49
#include "gdalalg_vector_write.h"
50
#include "gdalalg_tee.h"
51
52
#include "../frmts/mem/memdataset.h"
53
54
#include "cpl_conv.h"
55
#include "cpl_string.h"
56
57
#include <algorithm>
58
#include <cassert>
59
60
//! @cond Doxygen_Suppress
61
62
#ifndef _
63
#define _(x) (x)
64
#endif
65
66
0
GDALVectorAlgorithmStepRegistry::~GDALVectorAlgorithmStepRegistry() = default;
67
68
/************************************************************************/
69
/*  GDALVectorPipelineStepAlgorithm::GDALVectorPipelineStepAlgorithm()  */
70
/************************************************************************/
71
72
GDALVectorPipelineStepAlgorithm::GDALVectorPipelineStepAlgorithm(
73
    const std::string &name, const std::string &description,
74
    const std::string &helpURL, bool standaloneStep)
75
0
    : GDALVectorPipelineStepAlgorithm(
76
0
          name, description, helpURL,
77
0
          ConstructorOptions().SetStandaloneStep(standaloneStep))
78
0
{
79
0
}
80
81
/************************************************************************/
82
/*  GDALVectorPipelineStepAlgorithm::GDALVectorPipelineStepAlgorithm()  */
83
/************************************************************************/
84
85
GDALVectorPipelineStepAlgorithm::GDALVectorPipelineStepAlgorithm(
86
    const std::string &name, const std::string &description,
87
    const std::string &helpURL, const ConstructorOptions &options)
88
0
    : GDALPipelineStepAlgorithm(name, description, helpURL, options)
89
0
{
90
0
    if (m_standaloneStep)
91
0
    {
92
0
        m_supportsStreamedOutput = true;
93
94
0
        if (m_constructorOptions.addDefaultArguments)
95
0
        {
96
0
            AddVectorInputArgs(false);
97
0
            AddProgressArg();
98
0
            AddVectorOutputArgs(false, false);
99
0
        }
100
0
    }
101
0
    else
102
0
    {
103
0
        if (m_constructorOptions.addDefaultArguments)
104
0
        {
105
0
            AddVectorHiddenInputDatasetArg();
106
0
        }
107
0
    }
108
0
}
109
110
0
GDALVectorPipelineStepAlgorithm::~GDALVectorPipelineStepAlgorithm() = default;
111
112
/************************************************************************/
113
/*      GDALVectorPipelineAlgorithm::GDALVectorPipelineAlgorithm()      */
114
/************************************************************************/
115
116
GDALVectorPipelineAlgorithm::GDALVectorPipelineAlgorithm()
117
0
    : GDALAbstractPipelineAlgorithm(
118
0
          NAME, DESCRIPTION, HELP_URL,
119
0
          ConstructorOptions().SetInputDatasetMaxCount(INT_MAX))
120
0
{
121
0
    m_supportsStreamedOutput = true;
122
123
0
    AddVectorInputArgs(/* hiddenForCLI = */ true);
124
0
    AddProgressArg();
125
0
    AddArg("pipeline", 0, _("Pipeline string"), &m_pipeline)
126
0
        .SetHiddenForCLI()
127
0
        .SetPositional();
128
0
    AddVectorOutputArgs(/* hiddenForCLI = */ true,
129
0
                        /* shortNameOutputLayerAllowed=*/false);
130
131
0
    AddOutputStringArg(&m_output).SetHiddenForCLI();
132
0
    AddStdoutArg(&m_stdout);
133
134
0
    RegisterAlgorithms(m_stepRegistry, false);
135
0
}
136
137
/************************************************************************/
138
/*          GDALVectorPipelineAlgorithm::RegisterAlgorithms()           */
139
/************************************************************************/
140
141
/* static */
142
void GDALVectorPipelineAlgorithm::RegisterAlgorithms(
143
    GDALVectorAlgorithmStepRegistry &registry, bool forMixedPipeline)
144
0
{
145
0
    GDALAlgorithmRegistry::AlgInfo algInfo;
146
147
0
    const auto addSuffixIfNeeded =
148
0
        [forMixedPipeline](const char *name) -> std::string
149
0
    {
150
0
        return forMixedPipeline ? std::string(name).append(VECTOR_SUFFIX)
151
0
                                : std::string(name);
152
0
    };
153
154
0
    registry.Register<GDALVectorReadAlgorithm>(
155
0
        addSuffixIfNeeded(GDALVectorReadAlgorithm::NAME));
156
157
0
    registry.Register<GDALVectorWriteAlgorithm>(
158
0
        addSuffixIfNeeded(GDALVectorWriteAlgorithm::NAME));
159
160
0
    registry.Register<GDALVectorInfoAlgorithm>(
161
0
        addSuffixIfNeeded(GDALVectorInfoAlgorithm::NAME));
162
163
0
    registry.Register<GDALVectorBufferAlgorithm>();
164
0
    registry.Register<GDALVectorCheckCoverageAlgorithm>();
165
0
    registry.Register<GDALVectorCheckGeometryAlgorithm>();
166
0
    registry.Register<GDALVectorCombineAlgorithm>();
167
0
    registry.Register<GDALVectorConcatAlgorithm>();
168
0
    registry.Register<GDALVectorConcaveHullAlgorithm>();
169
0
    registry.Register<GDALVectorConvexHullAlgorithm>();
170
0
    registry.Register<GDALVectorCleanCoverageAlgorithm>();
171
172
0
    registry.Register<GDALVectorClipAlgorithm>(
173
0
        addSuffixIfNeeded(GDALVectorClipAlgorithm::NAME));
174
0
    registry.Register<GDALVectorDissolveAlgorithm>();
175
176
0
    registry.Register<GDALVectorCreateAlgorithm>(
177
0
        addSuffixIfNeeded(GDALVectorCreateAlgorithm::NAME));
178
179
0
    registry.Register<GDALVectorEditAlgorithm>(
180
0
        addSuffixIfNeeded(GDALVectorEditAlgorithm::NAME));
181
182
0
    registry.Register<GDALVectorExplodeCollectionsAlgorithm>();
183
0
    registry.Register<GDALVectorExportSchemaAlgorithm>();
184
185
0
    registry.Register<GDALMaterializeVectorAlgorithm>(
186
0
        addSuffixIfNeeded(GDALMaterializeVectorAlgorithm::NAME));
187
188
0
    registry.Register<GDALVectorReprojectAlgorithm>(
189
0
        addSuffixIfNeeded(GDALVectorReprojectAlgorithm::NAME));
190
191
0
    registry.Register<GDALVectorFilterAlgorithm>();
192
0
    registry.Register<GDALVectorLimitAlgorithm>();
193
0
    registry.Register<GDALVectorMakePointAlgorithm>();
194
0
    registry.Register<GDALVectorMakeValidAlgorithm>();
195
0
    registry.Register<GDALVectorPartitionAlgorithm>();
196
0
    registry.Register<GDALVectorRenameLayerAlgorithm>();
197
0
    registry.Register<GDALVectorSegmentizeAlgorithm>();
198
199
0
    registry.Register<GDALVectorSelectAlgorithm>(
200
0
        addSuffixIfNeeded(GDALVectorSelectAlgorithm::NAME));
201
202
0
    registry.Register<GDALVectorSetFieldTypeAlgorithm>();
203
0
    registry.Register<GDALVectorSetGeomTypeAlgorithm>();
204
0
    registry.Register<GDALVectorSimplifyAlgorithm>();
205
0
    registry.Register<GDALVectorSimplifyCoverageAlgorithm>();
206
0
    registry.Register<GDALVectorSortAlgorithm>();
207
0
    registry.Register<GDALVectorSQLAlgorithm>();
208
0
    registry.Register<GDALVectorUpdateAlgorithm>(
209
0
        addSuffixIfNeeded(GDALVectorUpdateAlgorithm::NAME));
210
0
    registry.Register<GDALVectorSwapXYAlgorithm>();
211
212
0
    registry.Register<GDALTeeVectorAlgorithm>(
213
0
        addSuffixIfNeeded(GDALTeeVectorAlgorithm::NAME));
214
215
0
    if (!forMixedPipeline)
216
0
    {
217
0
        registry.Register<GDALExternalVectorAlgorithm>();
218
0
    }
219
0
}
220
221
/************************************************************************/
222
/*            GDALVectorPipelineAlgorithm::GetUsageForCLI()             */
223
/************************************************************************/
224
225
std::string GDALVectorPipelineAlgorithm::GetUsageForCLI(
226
    bool shortUsage, const UsageOptions &usageOptions) const
227
0
{
228
0
    UsageOptions stepUsageOptions;
229
0
    stepUsageOptions.isPipelineStep = true;
230
231
0
    if (!m_helpDocCategory.empty() && m_helpDocCategory != "main")
232
0
    {
233
0
        auto alg = GetStepAlg(m_helpDocCategory);
234
0
        if (alg)
235
0
        {
236
0
            alg->SetCallPath({m_helpDocCategory});
237
0
            alg->GetArg("help-doc")->Set(true);
238
0
            return alg->GetUsageForCLI(shortUsage, stepUsageOptions);
239
0
        }
240
0
        else
241
0
        {
242
0
            fprintf(stderr, "ERROR: unknown pipeline step '%s'\n",
243
0
                    m_helpDocCategory.c_str());
244
0
            return CPLSPrintf("ERROR: unknown pipeline step '%s'\n",
245
0
                              m_helpDocCategory.c_str());
246
0
        }
247
0
    }
248
249
0
    UsageOptions usageOptionsMain(usageOptions);
250
0
    usageOptionsMain.isPipelineMain = true;
251
0
    std::string ret =
252
0
        GDALAlgorithm::GetUsageForCLI(shortUsage, usageOptionsMain);
253
0
    if (shortUsage)
254
0
        return ret;
255
256
0
    ret += "\n<PIPELINE> is of the form: read|concat [READ-OPTIONS] "
257
0
           "( ! <STEP-NAME> [STEP-OPTIONS] )* ! write|info [WRITE-OPTIONS]\n";
258
259
0
    if (m_helpDocCategory == "main")
260
0
    {
261
0
        return ret;
262
0
    }
263
264
0
    ret += '\n';
265
0
    ret += "Example: 'gdal vector pipeline --progress ! read in.gpkg ! \\\n";
266
0
    ret += "               reproject --dst-crs=EPSG:32632 ! ";
267
0
    ret += "write out.gpkg --overwrite'\n";
268
0
    ret += '\n';
269
0
    ret += "Potential steps are:\n";
270
271
0
    for (const std::string &name : m_stepRegistry.GetNames())
272
0
    {
273
0
        auto alg = GetStepAlg(name);
274
0
        assert(alg);
275
0
        auto [options, maxOptLen] = alg->GetArgNamesForCLI();
276
0
        stepUsageOptions.maxOptLen =
277
0
            std::max(stepUsageOptions.maxOptLen, maxOptLen);
278
0
    }
279
280
0
    {
281
0
        const auto name = GDALVectorReadAlgorithm::NAME;
282
0
        ret += '\n';
283
0
        auto alg = GetStepAlg(name);
284
0
        alg->SetCallPath({name});
285
0
        ret += alg->GetUsageForCLI(shortUsage, stepUsageOptions);
286
0
    }
287
0
    for (const std::string &name : m_stepRegistry.GetNames())
288
0
    {
289
0
        auto alg = GetStepAlg(name);
290
0
        assert(alg);
291
0
        if (alg->CanBeFirstStep() && !alg->CanBeMiddleStep() &&
292
0
            !alg->IsHidden() && name != GDALVectorReadAlgorithm::NAME)
293
0
        {
294
0
            ret += '\n';
295
0
            alg->SetCallPath({name});
296
0
            ret += alg->GetUsageForCLI(shortUsage, stepUsageOptions);
297
0
        }
298
0
    }
299
0
    for (const std::string &name : m_stepRegistry.GetNames())
300
0
    {
301
0
        auto alg = GetStepAlg(name);
302
0
        assert(alg);
303
0
        if (alg->CanBeMiddleStep() && !alg->IsHidden())
304
0
        {
305
0
            ret += '\n';
306
0
            alg->SetCallPath({name});
307
0
            ret += alg->GetUsageForCLI(shortUsage, stepUsageOptions);
308
0
        }
309
0
    }
310
0
    for (const std::string &name : m_stepRegistry.GetNames())
311
0
    {
312
0
        auto alg = GetStepAlg(name);
313
0
        assert(alg);
314
0
        if (alg->CanBeLastStep() && !alg->CanBeMiddleStep() &&
315
0
            !alg->IsHidden() && name != GDALVectorWriteAlgorithm::NAME)
316
0
        {
317
0
            ret += '\n';
318
0
            alg->SetCallPath({name});
319
0
            ret += alg->GetUsageForCLI(shortUsage, stepUsageOptions);
320
0
        }
321
0
    }
322
0
    {
323
0
        const auto name = GDALVectorWriteAlgorithm::NAME;
324
0
        ret += '\n';
325
0
        auto alg = GetStepAlg(name);
326
0
        alg->SetCallPath({name});
327
0
        ret += alg->GetUsageForCLI(shortUsage, stepUsageOptions);
328
0
    }
329
330
0
    ret += GetUsageForCLIEnd();
331
332
0
    return ret;
333
0
}
334
335
/************************************************************************/
336
/*                      GDALVectorDecoratedDataset                      */
337
/************************************************************************/
338
339
namespace
340
{
341
class DummyDataset final : public GDALDataset
342
{
343
  public:
344
0
    DummyDataset() = default;
345
};
346
}  // namespace
347
348
/************************************************************************/
349
/*                     GDALVectorDecoratedDataset()                     */
350
/************************************************************************/
351
352
GDALVectorDecoratedDataset::GDALVectorDecoratedDataset(GDALDataset *poSrcDS)
353
0
    : m_dummySrcDS(poSrcDS ? nullptr : std::make_unique<DummyDataset>()),
354
0
      m_srcDS(poSrcDS ? *poSrcDS : *(m_dummySrcDS.get()))
355
0
{
356
0
    SetDescription(m_srcDS.GetDescription());
357
0
}
358
359
/************************************************************************/
360
/*                    ~GDALVectorDecoratedDataset()                     */
361
/************************************************************************/
362
363
0
GDALVectorDecoratedDataset::~GDALVectorDecoratedDataset() = default;
364
365
/************************************************************************/
366
/*                    GDALVectorPipelineOutputLayer                     */
367
/************************************************************************/
368
369
/************************************************************************/
370
/*                   GDALVectorPipelineOutputLayer()                    */
371
/************************************************************************/
372
373
GDALVectorPipelineOutputLayer::GDALVectorPipelineOutputLayer(OGRLayer &srcLayer)
374
0
    : m_srcLayer(srcLayer)
375
0
{
376
0
}
377
378
/************************************************************************/
379
/*                   ~GDALVectorPipelineOutputLayer()                   */
380
/************************************************************************/
381
382
0
GDALVectorPipelineOutputLayer::~GDALVectorPipelineOutputLayer() = default;
383
384
/************************************************************************/
385
/*            GDALVectorPipelineOutputLayer::ResetReading()             */
386
/************************************************************************/
387
388
void GDALVectorPipelineOutputLayer::ResetReading()
389
0
{
390
0
    m_srcLayer.ResetReading();
391
0
    m_pendingFeatures.clear();
392
0
    m_idxInPendingFeatures = 0;
393
0
}
394
395
/************************************************************************/
396
/*          GDALVectorPipelineOutputLayer::GetNextRawFeature()          */
397
/************************************************************************/
398
399
OGRFeature *GDALVectorPipelineOutputLayer::GetNextRawFeature()
400
0
{
401
0
    if (m_idxInPendingFeatures < m_pendingFeatures.size())
402
0
    {
403
0
        OGRFeature *poFeature =
404
0
            m_pendingFeatures[m_idxInPendingFeatures].release();
405
0
        ++m_idxInPendingFeatures;
406
0
        return poFeature;
407
0
    }
408
0
    m_pendingFeatures.clear();
409
0
    m_idxInPendingFeatures = 0;
410
0
    while (true)
411
0
    {
412
0
        auto poSrcFeature =
413
0
            std::unique_ptr<OGRFeature>(m_srcLayer.GetNextFeature());
414
0
        if (!poSrcFeature)
415
0
            return nullptr;
416
0
        TranslateFeature(std::move(poSrcFeature), m_pendingFeatures);
417
0
        if (m_translateError)
418
0
        {
419
0
            return nullptr;
420
0
        }
421
0
        if (!m_pendingFeatures.empty())
422
0
            break;
423
0
    }
424
0
    OGRFeature *poFeature = m_pendingFeatures[0].release();
425
0
    m_idxInPendingFeatures = 1;
426
0
    return poFeature;
427
0
}
428
429
/************************************************************************/
430
/*                       GDALVectorOutputDataset                        */
431
/************************************************************************/
432
433
/************************************************************************/
434
/*                      GDALVectorOutputDataset()                       */
435
/************************************************************************/
436
437
GDALVectorOutputDataset::GDALVectorOutputDataset(GDALDataset *poSrcDS)
438
0
    : GDALVectorDecoratedDataset(poSrcDS)
439
0
{
440
0
}
441
442
/************************************************************************/
443
/*                           TestCapability()                           */
444
/************************************************************************/
445
446
int GDALVectorOutputDataset::TestCapability(const char *) const
447
0
{
448
0
    return 0;
449
0
}
450
451
/************************************************************************/
452
/*                   GDALVectorPipelineOutputDataset                    */
453
/************************************************************************/
454
455
/************************************************************************/
456
/*                  GDALVectorPipelineOutputDataset()                   */
457
/************************************************************************/
458
459
GDALVectorPipelineOutputDataset::GDALVectorPipelineOutputDataset(
460
    GDALDataset &srcDS)
461
0
    : GDALVectorDecoratedDataset(&srcDS)
462
0
{
463
0
}
464
465
/************************************************************************/
466
/*             GDALVectorPipelineOutputDataset::AddLayer()              */
467
/************************************************************************/
468
469
void GDALVectorPipelineOutputDataset::AddLayer(
470
    OGRLayer &oSrcLayer,
471
    std::unique_ptr<OGRLayerWithTranslateFeature> poNewLayer)
472
0
{
473
0
    m_layersToDestroy.push_back(std::move(poNewLayer));
474
0
    OGRLayerWithTranslateFeature *poNewLayerRaw =
475
0
        m_layersToDestroy.back().get();
476
0
    m_layers.push_back(poNewLayerRaw);
477
0
    m_mapSrcLayerToNewLayer[&oSrcLayer] = poNewLayerRaw;
478
0
}
479
480
/************************************************************************/
481
/*           GDALVectorPipelineOutputDataset::GetLayerCount()           */
482
/************************************************************************/
483
484
int GDALVectorPipelineOutputDataset::GetLayerCount() const
485
0
{
486
0
    return static_cast<int>(m_layers.size());
487
0
}
488
489
/************************************************************************/
490
/*             GDALVectorPipelineOutputDataset::GetLayer()              */
491
/************************************************************************/
492
493
OGRLayer *GDALVectorPipelineOutputDataset::GetLayer(int idx) const
494
0
{
495
0
    return idx >= 0 && idx < GetLayerCount() ? m_layers[idx] : nullptr;
496
0
}
497
498
/************************************************************************/
499
/*          GDALVectorPipelineOutputDataset::TestCapability()           */
500
/************************************************************************/
501
502
int GDALVectorPipelineOutputDataset::TestCapability(const char *pszCap) const
503
0
{
504
0
    if (EQUAL(pszCap, ODsCRandomLayerRead) ||
505
0
        EQUAL(pszCap, ODsCMeasuredGeometries) || EQUAL(pszCap, ODsCZGeometries))
506
0
    {
507
0
        return m_srcDS.TestCapability(pszCap);
508
0
    }
509
0
    return false;
510
0
}
511
512
/************************************************************************/
513
/*           GDALVectorPipelineOutputDataset::ResetReading()            */
514
/************************************************************************/
515
516
void GDALVectorPipelineOutputDataset::ResetReading()
517
0
{
518
0
    m_srcDS.ResetReading();
519
0
    m_pendingFeatures.clear();
520
0
    m_idxInPendingFeatures = 0;
521
0
}
522
523
/************************************************************************/
524
/*          GDALVectorPipelineOutputDataset::GetNextFeature()           */
525
/************************************************************************/
526
527
OGRFeature *GDALVectorPipelineOutputDataset::GetNextFeature(
528
    OGRLayer **ppoBelongingLayer, double *pdfProgressPct,
529
    GDALProgressFunc pfnProgress, void *pProgressData)
530
0
{
531
0
    if (m_idxInPendingFeatures < m_pendingFeatures.size())
532
0
    {
533
0
        OGRFeature *poFeature =
534
0
            m_pendingFeatures[m_idxInPendingFeatures].release();
535
0
        if (ppoBelongingLayer)
536
0
            *ppoBelongingLayer = m_belongingLayer;
537
0
        ++m_idxInPendingFeatures;
538
0
        return poFeature;
539
0
    }
540
541
0
    m_pendingFeatures.clear();
542
0
    m_idxInPendingFeatures = 0;
543
544
0
    while (true)
545
0
    {
546
0
        OGRLayer *poSrcBelongingLayer = nullptr;
547
0
        auto poSrcFeature = std::unique_ptr<OGRFeature>(m_srcDS.GetNextFeature(
548
0
            &poSrcBelongingLayer, pdfProgressPct, pfnProgress, pProgressData));
549
0
        if (!poSrcFeature)
550
0
            return nullptr;
551
0
        auto iterToDstLayer = m_mapSrcLayerToNewLayer.find(poSrcBelongingLayer);
552
0
        if (iterToDstLayer != m_mapSrcLayerToNewLayer.end())
553
0
        {
554
0
            m_belongingLayer = iterToDstLayer->second;
555
0
            m_belongingLayer->TranslateFeature(std::move(poSrcFeature),
556
0
                                               m_pendingFeatures);
557
558
0
            if (!m_pendingFeatures.empty())
559
0
                break;
560
0
        }
561
0
    }
562
0
    OGRFeature *poFeature = m_pendingFeatures[0].release();
563
0
    if (ppoBelongingLayer)
564
0
        *ppoBelongingLayer = m_belongingLayer;
565
0
    m_idxInPendingFeatures = 1;
566
0
    return poFeature;
567
0
}
568
569
/************************************************************************/
570
/*          GDALVectorPipelinePassthroughLayer::GetLayerDefn()          */
571
/************************************************************************/
572
573
const OGRFeatureDefn *GDALVectorPipelinePassthroughLayer::GetLayerDefn() const
574
0
{
575
0
    return m_srcLayer.GetLayerDefn();
576
0
}
577
578
/************************************************************************/
579
/*               GDALVectorNonStreamingAlgorithmDataset()               */
580
/************************************************************************/
581
582
GDALVectorNonStreamingAlgorithmDataset::GDALVectorNonStreamingAlgorithmDataset(
583
    GDALDataset &oSrcDS)
584
0
    : GDALVectorDecoratedDataset(&oSrcDS)
585
0
{
586
0
}
587
588
/************************************************************************/
589
/*              ~GDALVectorNonStreamingAlgorithmDataset()               */
590
/************************************************************************/
591
592
GDALVectorNonStreamingAlgorithmDataset::
593
0
    ~GDALVectorNonStreamingAlgorithmDataset() = default;
594
595
/************************************************************************/
596
/*     GDALVectorNonStreamingAlgorithmDataset::AddProcessedLayer()      */
597
/************************************************************************/
598
599
bool GDALVectorNonStreamingAlgorithmDataset::AddProcessedLayer(
600
    std::unique_ptr<GDALVectorNonStreamingAlgorithmLayer> layer,
601
    GDALProgressFunc progressFn, void *progressData)
602
0
{
603
0
    if (!layer->Process(progressFn, progressData))
604
0
    {
605
0
        return false;
606
0
    }
607
608
0
    m_owned_layers.emplace_back(std::move(layer));
609
0
    m_layers.push_back(m_owned_layers.back().get());
610
611
0
    return true;
612
0
}
613
614
/************************************************************************/
615
/*    GDALVectorNonStreamingAlgorithmDataset::AddPassThroughLayer()     */
616
/************************************************************************/
617
618
void GDALVectorNonStreamingAlgorithmDataset::AddPassThroughLayer(
619
    OGRLayer &oLayer)
620
0
{
621
0
    m_owned_layers.push_back(
622
0
        std::make_unique<GDALVectorPipelinePassthroughLayer>(oLayer));
623
0
    m_layers.push_back(m_owned_layers.back().get());
624
0
}
625
626
/************************************************************************/
627
/*       GDALVectorNonStreamingAlgorithmDataset::GetLayerCount()        */
628
/************************************************************************/
629
630
int GDALVectorNonStreamingAlgorithmDataset::GetLayerCount() const
631
0
{
632
0
    return static_cast<int>(m_layers.size());
633
0
}
634
635
/************************************************************************/
636
/*          GDALVectorNonStreamingAlgorithmDataset::GetLayer()          */
637
/************************************************************************/
638
639
OGRLayer *GDALVectorNonStreamingAlgorithmDataset::GetLayer(int idx) const
640
0
{
641
0
    if (idx < 0 || idx >= static_cast<int>(m_layers.size()))
642
0
    {
643
0
        return nullptr;
644
0
    }
645
0
    return m_layers[idx];
646
0
}
647
648
/************************************************************************/
649
/*       GDALVectorNonStreamingAlgorithmDataset::TestCapability()       */
650
/************************************************************************/
651
652
int GDALVectorNonStreamingAlgorithmDataset::TestCapability(
653
    const char *pszCap) const
654
0
{
655
0
    if (EQUAL(pszCap, ODsCCurveGeometries) ||
656
0
        EQUAL(pszCap, ODsCMeasuredGeometries) || EQUAL(pszCap, ODsCZGeometries))
657
0
    {
658
0
        return true;
659
0
    }
660
661
0
    return false;
662
0
}
663
664
/************************************************************************/
665
/*               GDALVectorAlgorithmLayerProgressHelper()               */
666
/************************************************************************/
667
668
GDALVectorAlgorithmLayerProgressHelper::GDALVectorAlgorithmLayerProgressHelper(
669
    GDALProgressFunc pfnProgress, void *pProgressData)
670
0
    : m_pfnProgress(pfnProgress), m_pProgressData(pProgressData)
671
0
{
672
0
}
673
674
/************************************************************************/
675
/*               GDALVectorAlgorithmLayerProgressHelper()               */
676
/************************************************************************/
677
678
GDALVectorAlgorithmLayerProgressHelper::GDALVectorAlgorithmLayerProgressHelper(
679
    const GDALPipelineStepRunContext &ctxt)
680
0
    : GDALVectorAlgorithmLayerProgressHelper(ctxt.m_pfnProgress,
681
0
                                             ctxt.m_pProgressData)
682
0
{
683
0
}
684
685
/************************************************************************/
686
/*     GDALVectorAlgorithmLayerProgressHelper::AddProcessedLayer()      */
687
/************************************************************************/
688
689
void GDALVectorAlgorithmLayerProgressHelper::AddProcessedLayer(
690
    OGRLayer &srcLayer)
691
0
{
692
0
    m_apoSrcLayers.emplace_back(&srcLayer, true);
693
0
    if (m_pfnProgress && m_nTotalFeatures >= 0 &&
694
0
        srcLayer.TestCapability(OLCFastFeatureCount))
695
0
    {
696
0
        const auto nLayerFeatures = srcLayer.GetFeatureCount(false);
697
0
        if (nLayerFeatures < 0)
698
0
            m_nTotalFeatures = -1;
699
0
        else
700
0
            m_nTotalFeatures += nLayerFeatures;
701
0
        m_anFeatures.push_back(nLayerFeatures);
702
0
    }
703
0
    else
704
0
    {
705
0
        m_anFeatures.push_back(-1);
706
0
        m_nTotalFeatures = -1;
707
0
    }
708
0
}
709
710
/************************************************************************/
711
/*    GDALVectorAlgorithmLayerProgressHelper::AddPassThroughLayer()     */
712
/************************************************************************/
713
714
void GDALVectorAlgorithmLayerProgressHelper::AddPassThroughLayer(
715
    OGRLayer &srcLayer)
716
0
{
717
0
    m_apoSrcLayers.emplace_back(&srcLayer, false);
718
0
}
719
720
/************************************************************************/
721
/*                GDALVectorNonStreamingAlgorithmLayer()                */
722
/************************************************************************/
723
724
GDALVectorNonStreamingAlgorithmLayer::GDALVectorNonStreamingAlgorithmLayer(
725
    OGRLayer &srcLayer, int geomFieldIndex)
726
0
    : m_srcLayer(srcLayer), m_geomFieldIndex(geomFieldIndex)
727
0
{
728
0
}
729
730
/************************************************************************/
731
/*               ~GDALVectorNonStreamingAlgorithmLayer()                */
732
/************************************************************************/
733
734
0
GDALVectorNonStreamingAlgorithmLayer::~GDALVectorNonStreamingAlgorithmLayer() =
735
    default;
736
737
/************************************************************************/
738
/*      GDALVectorNonStreamingAlgorithmLayer::GetNextRawFeature()       */
739
/************************************************************************/
740
741
OGRFeature *GDALVectorNonStreamingAlgorithmLayer::GetNextRawFeature()
742
0
{
743
0
    return GetNextProcessedFeature().release();
744
0
}
745
746
/************************************************************************/
747
/*    GDALVectorAlgorithmLayerProgressHelper::iterator::operator*()     */
748
/************************************************************************/
749
750
GDALVectorAlgorithmLayerProgressHelper::iterator::value_type
751
GDALVectorAlgorithmLayerProgressHelper::iterator::operator*() const
752
0
{
753
0
    const double dfProgressStart =
754
0
        m_helper.m_anFeatures.empty() ? 0
755
0
        : m_helper.m_nTotalFeatures > 0
756
0
            ? static_cast<double>(m_nFeatureIdx) /
757
0
                  static_cast<double>(m_helper.m_nTotalFeatures)
758
0
            : static_cast<double>(m_nProcessedLayerIdx) /
759
0
                  std::max(1.0,
760
0
                           static_cast<double>(m_helper.m_anFeatures.size()));
761
0
    const double dfProgressEnd =
762
0
        m_helper.m_anFeatures.empty() ? 0
763
0
        : m_helper.m_nTotalFeatures > 0
764
0
            ? static_cast<double>(m_nFeatureIdx +
765
0
                                  m_helper.m_anFeatures[m_nProcessedLayerIdx]) /
766
0
                  static_cast<double>(m_helper.m_nTotalFeatures)
767
0
            : static_cast<double>(m_nProcessedLayerIdx + 1) /
768
0
                  std::max(1.0,
769
0
                           static_cast<double>(m_helper.m_anFeatures.size()));
770
771
0
    progress_data_unique_ptr pScaledProgressData(nullptr,
772
0
                                                 GDALDestroyScaledProgress);
773
0
    if (m_helper.m_pfnProgress && m_helper.m_apoSrcLayers[m_nLayerIdx].second)
774
0
    {
775
0
        pScaledProgressData.reset(GDALCreateScaledProgress(
776
0
            dfProgressStart, dfProgressEnd, m_helper.m_pfnProgress,
777
0
            m_helper.m_pProgressData));
778
0
    }
779
780
0
    return value_type(m_helper.m_apoSrcLayers[m_nLayerIdx].first,
781
0
                      m_helper.m_apoSrcLayers[m_nLayerIdx].second,
782
0
                      m_helper.m_pfnProgress ? GDALScaledProgress : nullptr,
783
0
                      std::move(pScaledProgressData));
784
0
}
785
786
//! @endcond