Coverage Report

Created: 2025-12-03 08:24

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gdal/ogr/ogrsf_frmts/flatgeobuf/ogr_flatgeobuf.h
Line
Count
Source
1
/******************************************************************************
2
 *
3
 * Project:  FlatGeobuf driver
4
 * Purpose:  Declaration of classes for OGR FlatGeobuf driver.
5
 * Author:   Björn Harrtell <bjorn at wololo dot org>
6
 *
7
 ******************************************************************************
8
 * Copyright (c) 2018-2020, Björn Harrtell <bjorn at wololo dot org>
9
 *
10
 * SPDX-License-Identifier: MIT
11
 ****************************************************************************/
12
13
#ifndef OGR_FLATGEOBUF_H_INCLUDED
14
#define OGR_FLATGEOBUF_H_INCLUDED
15
16
#include "ogrsf_frmts.h"
17
#include "ogr_p.h"
18
#include "ogreditablelayer.h"
19
20
#if defined(__clang__)
21
#pragma clang diagnostic push
22
#pragma clang diagnostic ignored "-Wweak-vtables"
23
#endif
24
25
#include "header_generated.h"
26
#include "feature_generated.h"
27
#include "packedrtree.h"
28
29
#if defined(__clang__)
30
#pragma clang diagnostic pop
31
#endif
32
33
#include <deque>
34
#include <limits>
35
36
class OGRFlatGeobufDataset;
37
38
static constexpr uint8_t magicbytes[8] = {0x66, 0x67, 0x62, 0x03,
39
                                          0x66, 0x67, 0x62, 0x01};
40
41
static constexpr uint32_t header_max_buffer_size = 1048576 * 10;
42
43
// Cannot be larger than that, due to a x2 logic done in ensureFeatureBuf()
44
static constexpr uint32_t feature_max_buffer_size =
45
    static_cast<uint32_t>(std::numeric_limits<int32_t>::max());
46
47
// holds feature meta needed to build spatial index
48
struct FeatureItem : FlatGeobuf::Item
49
{
50
    uint32_t size;
51
    uint64_t offset;
52
};
53
54
class OGRFlatGeobufBaseLayerInterface CPL_NON_FINAL
55
{
56
  public:
57
    virtual ~OGRFlatGeobufBaseLayerInterface();
58
59
    virtual const std::string &GetFilename() const = 0;
60
    virtual OGRLayer *GetLayer() = 0;
61
    virtual CPLErr Close() = 0;
62
};
63
64
class OGRFlatGeobufLayer final : public OGRLayer,
65
                                 public OGRFlatGeobufBaseLayerInterface
66
{
67
  private:
68
    std::string m_osFilename;
69
    std::string m_osLayerName;
70
71
    VSILFILE *m_poFp = nullptr;
72
    vsi_l_offset m_nFileSize = 0;
73
74
    const FlatGeobuf::Header *m_poHeader = nullptr;
75
    GByte *m_headerBuf = nullptr;
76
    OGRwkbGeometryType m_eGType;
77
    FlatGeobuf::GeometryType m_geometryType;
78
    bool m_hasM = false;
79
    bool m_hasZ = false;
80
    bool m_hasT = false;
81
    bool m_hasTM = false;
82
    uint64_t m_featuresCount = 0;
83
    OGREnvelope m_sExtent;
84
    OGRFeatureDefn *m_poFeatureDefn = nullptr;
85
    OGRSpatialReference *m_poSRS = nullptr;
86
87
    // iteration
88
    bool m_bEOF = false;
89
    size_t m_featuresPos = 0;       // current iteration position
90
    uint64_t m_offset = 0;          // current read offset
91
    uint64_t m_offsetFeatures = 0;  // offset of feature data
92
    std::vector<FlatGeobuf::SearchResultItem>
93
        m_foundItems;  // found node items in spatial index search
94
    bool m_queriedSpatialIndex = false;
95
    bool m_ignoreSpatialFilter = false;
96
    bool m_ignoreAttributeFilter = false;
97
98
    // creation
99
    GDALDataset *m_poDS = nullptr;  // parent dataset to get metadata from it
100
    bool m_create = false;
101
    std::deque<FeatureItem> m_featureItems;  // feature item description used to
102
                                             // create spatial index
103
    bool m_bCreateSpatialIndexAtClose = true;
104
    bool m_bVerifyBuffers = true;
105
    VSILFILE *m_poFpWrite = nullptr;
106
    CPLStringList m_aosCreationOption{};  // layer creation options
107
    uint64_t m_writeOffset = 0;           // current write offset
108
    uint64_t m_offsetAfterHeader =
109
        0;  // offset after dummy header writing (when creating a file without
110
            // spatial index)
111
    uint16_t m_indexNodeSize = 0;
112
    std::string
113
        m_osTempFile;  // holds generated temp file name for two pass writing
114
    uint32_t m_maxFeatureSize = 0;
115
    std::vector<uint8_t> m_writeProperties{};
116
117
    // shared
118
    GByte *m_featureBuf = nullptr;  // reusable/resizable feature data buffer
119
    uint32_t m_featureBufSize = 0;  // current feature buffer size
120
121
    // deserialize
122
    void ensurePadfBuffers(size_t count);
123
    OGRErr ensureFeatureBuf(uint32_t featureSize);
124
    OGRErr parseFeature(OGRFeature *poFeature);
125
    const std::vector<flatbuffers::Offset<FlatGeobuf::Column>>
126
    writeColumns(flatbuffers::FlatBufferBuilder &fbb);
127
    void readColumns();
128
    OGRErr readIndex();
129
    OGRErr readFeatureOffset(uint64_t index, uint64_t &featureOffset);
130
131
    // serialize
132
    bool CreateFinalFile();
133
    void writeHeader(VSILFILE *poFp, uint64_t featuresCount,
134
                     std::vector<double> *extentVector);
135
136
    // construction
137
    OGRFlatGeobufLayer(const FlatGeobuf::Header *, GByte *headerBuf,
138
                       const char *pszFilename, VSILFILE *poFp,
139
                       uint64_t offset);
140
    OGRFlatGeobufLayer(GDALDataset *poDS, const char *pszLayerName,
141
                       const char *pszFilename,
142
                       const OGRSpatialReference *poSpatialRef,
143
                       OGRwkbGeometryType eGType,
144
                       bool bCreateSpatialIndexAtClose, VSILFILE *poFpWrite,
145
                       std::string &osTempFile, CSLConstList papszOptions);
146
147
  protected:
148
    virtual int GetNextArrowArray(struct ArrowArrayStream *,
149
                                  struct ArrowArray *out_array) override;
150
151
    CPLErr Close() override;
152
153
  public:
154
    ~OGRFlatGeobufLayer() override;
155
156
    static OGRFlatGeobufLayer *Open(const FlatGeobuf::Header *,
157
                                    GByte *headerBuf, const char *pszFilename,
158
                                    VSILFILE *poFp, uint64_t offset);
159
    static OGRFlatGeobufLayer *Open(const char *pszFilename, VSILFILE *fp,
160
                                    bool bVerifyBuffers);
161
    static OGRFlatGeobufLayer *
162
    Create(GDALDataset *poDS, const char *pszLayerName, const char *pszFilename,
163
           const OGRSpatialReference *poSpatialRef, OGRwkbGeometryType eGType,
164
           bool bCreateSpatialIndexAtClose, CSLConstList papszOptions);
165
166
    OGRFeature *GetFeature(GIntBig nFeatureId) override;
167
    OGRFeature *GetNextFeature() override;
168
    virtual OGRErr CreateField(const OGRFieldDefn *poField,
169
                               int bApproxOK = true) override;
170
    OGRErr ICreateFeature(OGRFeature *poFeature) override;
171
    int TestCapability(const char *) const override;
172
173
    void ResetReading() override;
174
175
    const OGRFeatureDefn *GetLayerDefn() const override
176
38.1k
    {
177
38.1k
        return m_poFeatureDefn;
178
38.1k
    }
179
180
    GIntBig GetFeatureCount(int bForce) override;
181
    OGRErr IGetExtent(int iGeomField, OGREnvelope *psExtent,
182
                      bool bForce) override;
183
184
    void VerifyBuffers(int bFlag)
185
12.2k
    {
186
12.2k
        m_bVerifyBuffers = CPL_TO_BOOL(bFlag);
187
12.2k
    }
188
189
    GDALDataset *GetDataset() override
190
0
    {
191
0
        return m_poDS;
192
0
    }
193
194
    const std::string &GetFilename() const override
195
0
    {
196
0
        return m_osFilename;
197
0
    }
198
199
    OGRLayer *GetLayer() override
200
25.5k
    {
201
25.5k
        return this;
202
25.5k
    }
203
204
    static std::string GetTempFilePath(const CPLString &fileName,
205
                                       CSLConstList papszOptions);
206
    static VSILFILE *CreateOutputFile(const CPLString &pszFilename,
207
                                      CSLConstList papszOptions, bool isTemp);
208
209
    uint16_t GetIndexNodeSize() const
210
0
    {
211
0
        return m_indexNodeSize;
212
0
    }
213
214
    OGRwkbGeometryType getOGRwkbGeometryType();
215
};
216
217
class OGRFlatGeobufEditableLayer final : public OGREditableLayer,
218
                                         public OGRFlatGeobufBaseLayerInterface
219
{
220
  public:
221
    OGRFlatGeobufEditableLayer(OGRFlatGeobufLayer *poFlatGeobufLayer,
222
                               char **papszOpenOptions);
223
224
    GIntBig GetFeatureCount(int bForce = TRUE) override;
225
226
    const std::string &GetFilename() const override
227
0
    {
228
0
        return static_cast<OGRFlatGeobufLayer *>(m_poDecoratedLayer)
229
0
            ->GetFilename();
230
0
    }
231
232
    OGRLayer *GetLayer() override
233
0
    {
234
0
        return this;
235
0
    }
236
237
    int TestCapability(const char *pszCap) const override;
238
239
    CPLErr Close() override
240
0
    {
241
0
        return CE_None;
242
0
    }
243
};
244
245
class OGRFlatGeobufDataset final : public GDALDataset
246
{
247
  private:
248
    std::vector<std::unique_ptr<OGRFlatGeobufBaseLayerInterface>> m_apoLayers;
249
    bool m_bCreate = false;
250
    bool m_bUpdate = false;
251
    bool m_bIsDir = false;
252
253
    bool OpenFile(const char *pszFilename, VSILFILE *fp, bool bVerifyBuffers);
254
255
    CPLErr Close() override;
256
257
  public:
258
    OGRFlatGeobufDataset(const char *pszName, bool bIsDir, bool bCreate,
259
                         bool bUpdate);
260
    ~OGRFlatGeobufDataset() override;
261
262
    static GDALDataset *Open(GDALOpenInfo *);
263
    static GDALDataset *Create(const char *pszName, CPL_UNUSED int nBands,
264
                               CPL_UNUSED int nXSize, CPL_UNUSED int nYSize,
265
                               CPL_UNUSED GDALDataType eDT,
266
                               char **papszOptions);
267
    using GDALDataset::GetLayer;
268
    const OGRLayer *GetLayer(int) const override;
269
    int TestCapability(const char *pszCap) const override;
270
271
    OGRLayer *ICreateLayer(const char *pszName,
272
                           const OGRGeomFieldDefn *poGeomFieldDefn,
273
                           CSLConstList papszOptions) override;
274
275
    int GetLayerCount() const override
276
55.9k
    {
277
55.9k
        return static_cast<int>(m_apoLayers.size());
278
55.9k
    }
279
280
    char **GetFileList() override;
281
};
282
283
#endif /* ndef OGR_FLATGEOBUF_H_INCLUDED */