Coverage Report

Created: 2026-02-14 06:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gdal/ogr/ogrsf_frmts/generic/ogrunionlayer.h
Line
Count
Source
1
/******************************************************************************
2
 *
3
 * Project:  OpenGIS Simple Features Reference Implementation
4
 * Purpose:  Defines OGRUnionLayer class
5
 * Author:   Even Rouault, even dot rouault at spatialys.com
6
 *
7
 ******************************************************************************
8
 * Copyright (c) 2012-2014, Even Rouault <even dot rouault at spatialys.com>
9
 *
10
 * SPDX-License-Identifier: MIT
11
 ****************************************************************************/
12
13
#ifndef OGRUNIONLAYER_H_INCLUDED
14
#define OGRUNIONLAYER_H_INCLUDED
15
16
#ifndef DOXYGEN_SKIP
17
18
#include "ogrsf_frmts.h"
19
20
#include <algorithm>
21
#include <mutex>
22
#include <utility>
23
24
/************************************************************************/
25
/*                      OGRUnionLayerGeomFieldDefn                      */
26
/************************************************************************/
27
28
class CPL_DLL OGRUnionLayerGeomFieldDefn final : public OGRGeomFieldDefn
29
{
30
  public:
31
    int bGeomTypeSet = false;
32
    int bSRSSet = false;
33
    OGREnvelope sStaticEnvelope{};
34
35
    OGRUnionLayerGeomFieldDefn(const char *pszName, OGRwkbGeometryType eType);
36
    explicit OGRUnionLayerGeomFieldDefn(const OGRGeomFieldDefn &oSrc);
37
    OGRUnionLayerGeomFieldDefn(const OGRUnionLayerGeomFieldDefn &oSrc);
38
    OGRUnionLayerGeomFieldDefn(OGRUnionLayerGeomFieldDefn &&) = default;
39
    ~OGRUnionLayerGeomFieldDefn() override;
40
41
    OGRUnionLayerGeomFieldDefn &
42
    operator=(const OGRUnionLayerGeomFieldDefn &) = delete;
43
    OGRUnionLayerGeomFieldDefn &
44
    operator=(OGRUnionLayerGeomFieldDefn &&) = delete;
45
};
46
47
/************************************************************************/
48
/*                            OGRUnionLayer                             */
49
/************************************************************************/
50
51
typedef enum
52
{
53
    FIELD_FROM_FIRST_LAYER,
54
    FIELD_UNION_ALL_LAYERS,
55
    FIELD_INTERSECTION_ALL_LAYERS,
56
    FIELD_SPECIFIED,
57
} FieldUnionStrategy;
58
59
class CPL_DLL OGRUnionLayer final : public OGRLayer
60
{
61
  private:
62
    CPL_DISALLOW_COPY_ASSIGN(OGRUnionLayer)
63
64
    struct Layer
65
    {
66
        std::unique_ptr<OGRLayer> poLayerKeeper{};
67
        OGRLayer *poLayer = nullptr;
68
        bool bModified = false;
69
        bool bCheckIfAutoWrap = false;
70
71
        CPL_DISALLOW_COPY_ASSIGN(Layer)
72
73
        Layer(OGRLayer *poLayerIn, bool bOwnedIn)
74
0
            : poLayerKeeper(bOwnedIn ? poLayerIn : nullptr),
75
0
              poLayer(bOwnedIn ? poLayerKeeper.get() : poLayerIn)
76
0
        {
77
0
        }
78
79
0
        Layer(Layer &&) = default;
80
        Layer &operator=(Layer &&) = default;
81
82
        OGRLayer *operator->()
83
0
        {
84
0
            return poLayer;
85
0
        }
86
87
        const OGRLayer *operator->() const
88
0
        {
89
0
            return poLayer;
90
0
        }
91
92
        std::pair<OGRLayer *, bool> release()
93
0
        {
94
0
            const bool bOwnedBackup = poLayerKeeper != nullptr;
95
0
            OGRLayer *poLayerBackup =
96
0
                poLayerKeeper ? poLayerKeeper.release() : poLayer;
97
0
            poLayerKeeper.reset();
98
0
            return std::make_pair(poLayerBackup, bOwnedBackup);
99
0
        }
100
101
        void reset(std::unique_ptr<OGRLayer> poLayerIn)
102
0
        {
103
0
            poLayerKeeper = std::move(poLayerIn);
104
0
            poLayer = poLayerKeeper.get();
105
0
        }
106
    };
107
108
    CPLString osName{};
109
110
    std::vector<Layer> m_apoSrcLayers{};
111
112
    mutable OGRFeatureDefn *poFeatureDefn = nullptr;
113
    std::vector<std::unique_ptr<OGRFieldDefn>> apoFields{};
114
    std::vector<std::unique_ptr<OGRUnionLayerGeomFieldDefn>> apoGeomFields{};
115
    bool bUseGeomFields = true;
116
    FieldUnionStrategy eFieldStrategy = FIELD_UNION_ALL_LAYERS;
117
    CPLString osSourceLayerFieldName{};
118
119
    int bPreserveSrcFID = false;
120
121
    GIntBig nFeatureCount = -1;
122
123
    int iCurLayer = -1;
124
    bool m_bHasAlreadyIteratedOverFeatures = false;
125
    char *pszAttributeFilter = nullptr;
126
    int nNextFID = 0;
127
    int *panMap = nullptr;
128
    CPLStringList m_aosIgnoredFields{};
129
    mutable int bAttrFilterPassThroughValue = -1;
130
    mutable const OGRSpatialReference *poGlobalSRS = nullptr;
131
132
    std::mutex m_oMutex{};
133
134
    /* Map from target FID to (source layer, source FID) */
135
    struct FIDRange
136
    {
137
        GIntBig nDstFIDStart = 0;
138
        GIntBig nFIDCount = 0;
139
        GIntBig nSrcFIDStart = 0;
140
        int nLayerIdx = 0;
141
    };
142
143
    std::vector<FIDRange> m_fidRanges{};
144
    bool m_fidRangesInvalid = false;
145
    bool m_fidRangesComplete = false;
146
147
    void AutoWarpLayerIfNecessary(int iSubLayer);
148
    std::unique_ptr<OGRFeature> TranslateFromSrcLayer(OGRFeature *poSrcFeature,
149
                                                      GIntBig nFID);
150
    void ApplyAttributeFilterToSrcLayer(int iSubLayer);
151
    int GetAttrFilterPassThroughValue() const;
152
    void ConfigureActiveLayer();
153
    void SetSpatialFilterToSourceLayer(OGRLayer *poSrcLayer);
154
155
  public:
156
    OGRUnionLayer(
157
        const char *pszName, int nSrcLayers, /* must be >= 1 */
158
        OGRLayer *
159
            *papoSrcLayers, /* array itself ownership always transferred, layer
160
                               ownership depending on bTakeLayerOwnership */
161
        int bTakeLayerOwnership);
162
163
    ~OGRUnionLayer() override;
164
165
    /* All the following non virtual methods must be called just after the
166
     * constructor */
167
    /* and before any virtual method */
168
    void SetFields(
169
        FieldUnionStrategy eFieldStrategy, int nFields,
170
        const OGRFieldDefn *paoFields, /* duplicated by the method */
171
        int nGeomFields, /* maybe -1 to explicitly disable geometry fields */
172
        const OGRUnionLayerGeomFieldDefn
173
            *paoGeomFields /* duplicated by the method */);
174
    void SetFields(FieldUnionStrategy eFieldStrategy,
175
                   const OGRFeatureDefn *poFeatureDefnIn);
176
177
    void SetSourceLayerFieldName(const char *pszSourceLayerFieldName);
178
    void SetPreserveSrcFID(int bPreserveSrcFID);
179
    void SetFeatureCount(int nFeatureCount);
180
181
    const char *GetName() const override
182
0
    {
183
0
        return osName.c_str();
184
0
    }
185
186
    OGRwkbGeometryType GetGeomType() const override;
187
188
    void ResetReading() override;
189
    OGRFeature *GetNextFeature() override;
190
191
    OGRFeature *GetFeature(GIntBig nFeatureId) override;
192
193
    OGRErr ICreateFeature(OGRFeature *poFeature) override;
194
195
    OGRErr ISetFeature(OGRFeature *poFeature) override;
196
197
    OGRErr IUpsertFeature(OGRFeature *poFeature) override;
198
199
    OGRErr IUpdateFeature(OGRFeature *poFeature, int nUpdatedFieldsCount,
200
                          const int *panUpdatedFieldsIdx,
201
                          int nUpdatedGeomFieldsCount,
202
                          const int *panUpdatedGeomFieldsIdx,
203
                          bool bUpdateStyleString) override;
204
205
    const OGRFeatureDefn *GetLayerDefn() const override;
206
207
    const OGRSpatialReference *GetSpatialRef() const override;
208
209
    GIntBig GetFeatureCount(int) override;
210
211
    OGRErr SetAttributeFilter(const char *) override;
212
213
    int TestCapability(const char *) const override;
214
215
    OGRErr IGetExtent(int iGeomField, OGREnvelope *psExtent,
216
                      bool bForce) override;
217
218
    virtual OGRErr ISetSpatialFilter(int iGeomField,
219
                                     const OGRGeometry *) override;
220
221
    OGRErr SetIgnoredFields(CSLConstList papszFields) override;
222
223
    OGRErr SyncToDisk() override;
224
};
225
226
#endif /* #ifndef DOXYGEN_SKIP */
227
228
#endif  // OGRUNIONLAYER_H_INCLUDED