Coverage Report

Created: 2026-02-14 06:52

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