Coverage Report

Created: 2026-07-25 06:50

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gdal/apps/gdalalg_vector_limit.cpp
Line
Count
Source
1
/******************************************************************************
2
 *
3
 * Project:  GDAL
4
 * Purpose:  "limit" step of "vector pipeline"
5
 * Author:   Dan Baston
6
 *
7
 ******************************************************************************
8
 * Copyright (c) 2025, ISciences LLC
9
 *
10
 * SPDX-License-Identifier: MIT
11
 ****************************************************************************/
12
13
#include "gdalalg_vector_limit.h"
14
#include "gdalalg_vector_pipeline.h"
15
16
#include "gdal_priv.h"
17
#include "ogrsf_frmts.h"
18
#include "ogr_p.h"
19
20
#include <algorithm>
21
#include <set>
22
23
//! @cond Doxygen_Suppress
24
25
#ifndef _
26
0
#define _(x) (x)
27
#endif
28
29
/************************************************************************/
30
/*         GDALVectorLimitAlgorithm::GDALVectorLimitAlgorithm()         */
31
/************************************************************************/
32
33
GDALVectorLimitAlgorithm::GDALVectorLimitAlgorithm(bool standaloneStep)
34
0
    : GDALVectorPipelineStepAlgorithm(NAME, DESCRIPTION, HELP_URL,
35
0
                                      standaloneStep)
36
0
{
37
0
    AddArg("limit", 0, _("Limit the number of features to read per layer"),
38
0
           &m_featureLimit)
39
0
        .SetPositional()
40
0
        .SetRequired();
41
0
    AddActiveLayerArg(&m_activeLayer);
42
0
}
43
44
namespace
45
{
46
47
/************************************************************************/
48
/*                      GDALVectorReadLimitedLayer                      */
49
/************************************************************************/
50
51
class GDALVectorReadLimitedLayer final
52
    : public OGRLayer,
53
      public OGRGetNextFeatureThroughRaw<GDALVectorReadLimitedLayer>
54
{
55
  public:
56
    GDALVectorReadLimitedLayer(OGRLayer &layer, int featureLimit)
57
0
        : m_srcLayer(layer), m_featureLimit(featureLimit), m_featuresRead(0)
58
0
    {
59
0
        SetDescription(layer.GetDescription());
60
0
    }
61
62
    ~GDALVectorReadLimitedLayer() override;
63
64
    OGRFeature *GetNextRawFeature()
65
0
    {
66
0
        if (m_featuresRead < m_featureLimit)
67
0
        {
68
0
            m_featuresRead++;
69
0
            return m_srcLayer.GetNextFeature();
70
0
        }
71
0
        return nullptr;
72
0
    }
73
74
    DEFINE_GET_NEXT_FEATURE_THROUGH_RAW(GDALVectorReadLimitedLayer)
75
76
    const OGRFeatureDefn *GetLayerDefn() const override
77
0
    {
78
0
        return m_srcLayer.GetLayerDefn();
79
0
    }
80
81
    GIntBig GetFeatureCount(int bForce) override
82
0
    {
83
0
        if (m_poFilterGeom || m_poAttrQuery)
84
0
            return OGRLayer::GetFeatureCount(bForce);
85
0
        else
86
0
            return std::min(m_featureLimit, m_srcLayer.GetFeatureCount(bForce));
87
0
    }
88
89
    void ResetReading() override
90
0
    {
91
0
        m_featuresRead = 0;
92
0
        m_srcLayer.ResetReading();
93
0
    }
94
95
    int TestCapability(const char *pszCap) const override
96
0
    {
97
0
        return m_srcLayer.TestCapability(pszCap);
98
0
    }
99
100
  private:
101
    OGRLayer &m_srcLayer;
102
    GIntBig m_featureLimit;
103
    GIntBig m_featuresRead;
104
};
105
106
GDALVectorReadLimitedLayer::~GDALVectorReadLimitedLayer() = default;
107
108
/************************************************************************/
109
/*                     GDALVectorReadLimitedDataset                     */
110
/************************************************************************/
111
112
class GDALVectorReadLimitedDataset final : public GDALVectorOutputDataset
113
{
114
  public:
115
    explicit GDALVectorReadLimitedDataset(GDALDataset *poSrcDS)
116
0
        : GDALVectorOutputDataset(poSrcDS)
117
0
    {
118
0
    }
119
120
    int TestCapability(const char *pszCap) const override
121
0
    {
122
0
        if (EQUAL(pszCap, ODsCMeasuredGeometries) ||
123
0
            EQUAL(pszCap, ODsCZGeometries))
124
0
        {
125
0
            return m_srcDS.TestCapability(pszCap);
126
0
        }
127
0
        return false;
128
0
    }
129
};
130
131
}  // namespace
132
133
/************************************************************************/
134
/*                 GDALVectorLimitAlgorithm::RunStep()                  */
135
/************************************************************************/
136
137
bool GDALVectorLimitAlgorithm::RunStep(GDALPipelineStepRunContext &)
138
0
{
139
0
    auto poSrcDS = m_inputDataset[0].GetDatasetRef();
140
0
    CPLAssert(poSrcDS);
141
142
0
    CPLAssert(m_outputDataset.GetName().empty());
143
0
    CPLAssert(!m_outputDataset.GetDatasetRef());
144
145
0
    auto outDS = std::make_unique<GDALVectorReadLimitedDataset>(poSrcDS);
146
147
0
    for (auto &&poSrcLayer : poSrcDS->GetLayers())
148
0
    {
149
0
        if (m_activeLayer.empty() ||
150
0
            m_activeLayer == poSrcLayer->GetDescription())
151
0
        {
152
0
            outDS->AddLayer(std::make_unique<GDALVectorReadLimitedLayer>(
153
0
                *poSrcLayer, m_featureLimit));
154
0
        }
155
0
        else
156
0
        {
157
0
            outDS->AddLayer(
158
0
                std::make_unique<GDALVectorPipelinePassthroughLayer>(
159
0
                    *poSrcLayer));
160
0
        }
161
0
    }
162
163
0
    m_outputDataset.Set(std::move(outDS));
164
165
0
    return true;
166
0
}
167
168
//! @endcond