Coverage Report

Created: 2025-11-16 06:25

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gdal/ogr/ogrsf_frmts/geojson/ogr_geojson.h
Line
Count
Source
1
/******************************************************************************
2
 *
3
 * Project:  OpenGIS Simple Features Reference Implementation
4
 * Purpose:  Definitions of OGR OGRGeoJSON driver types.
5
 * Author:   Mateusz Loskot, mateusz@loskot.net
6
 *
7
 ******************************************************************************
8
 * Copyright (c) 2007, Mateusz Loskot
9
 * Copyright (c) 2010-2013, Even Rouault <even dot rouault at spatialys.com>
10
 *
11
 * SPDX-License-Identifier: MIT
12
 ****************************************************************************/
13
14
#ifndef OGR_GEOJSON_H_INCLUDED
15
#define OGR_GEOJSON_H_INCLUDED
16
17
#include "cpl_port.h"
18
#include "ogrsf_frmts.h"
19
#include "memdataset.h"
20
21
#include <cstdio>
22
#include <vector>  // Used by OGRGeoJSONLayer.
23
#include "ogrgeojsonutils.h"
24
#include "ogrgeojsonwriter.h"
25
26
constexpr const char *INVALID_CONTENT_FOR_JSON_LIKE =
27
    "__INVALID_CONTENT_FOR_JSON_LIKE__";
28
29
class OGRGeoJSONDataSource;
30
31
GDALDataset *OGRGeoJSONDriverOpenInternal(GDALOpenInfo *poOpenInfo,
32
                                          GeoJSONSourceType nSrcType,
33
                                          const char *pszJSonFlavor);
34
void OGRGeoJSONDriverStoreContent(const char *pszSource, char *pszText);
35
char *OGRGeoJSONDriverStealStoredContent(const char *pszSource);
36
37
/************************************************************************/
38
/*                           OGRGeoJSONLayer                            */
39
/************************************************************************/
40
41
class OGRGeoJSONReader;
42
43
class OGRGeoJSONLayer final : public OGRMemLayer
44
{
45
    friend class OGRGeoJSONDataSource;
46
47
  public:
48
    static const char *const DefaultName;
49
    static const OGRwkbGeometryType DefaultGeometryType;
50
51
    static const char *GetValidLayerName(const char *pszName)
52
0
    {
53
0
        if (pszName == nullptr || pszName[0] == 0)
54
0
        {
55
            // Can happen for example if reading from /vsistdin/
56
0
            pszName = OGRGeoJSONLayer::DefaultName;
57
0
        }
58
0
        return pszName;
59
0
    }
60
61
    OGRGeoJSONLayer(const char *pszName, OGRSpatialReference *poSRS,
62
                    OGRwkbGeometryType eGType, OGRGeoJSONDataSource *poDS,
63
                    OGRGeoJSONReader *poReader);
64
    ~OGRGeoJSONLayer() override;
65
66
    //
67
    // OGRLayer Interface
68
    //
69
    const char *GetFIDColumn() const override;
70
    int TestCapability(const char *pszCap) const override;
71
72
    OGRErr SyncToDisk() override;
73
74
    void ResetReading() override;
75
    OGRFeature *GetNextFeature() override;
76
    OGRFeature *GetFeature(GIntBig nFID) override;
77
    GIntBig GetFeatureCount(int bForce) override;
78
79
    OGRErr ISetFeature(OGRFeature *poFeature) override;
80
    OGRErr ICreateFeature(OGRFeature *poFeature) override;
81
    OGRErr IUpdateFeature(OGRFeature *poFeature, int nUpdatedFieldsCount,
82
                          const int *panUpdatedFieldsIdx,
83
                          int nUpdatedGeomFieldsCount,
84
                          const int *panUpdatedGeomFieldsIdx,
85
                          bool bUpdateStyleString) override;
86
    OGRErr DeleteFeature(GIntBig nFID) override;
87
    virtual OGRErr CreateField(const OGRFieldDefn *poField,
88
                               int bApproxOK = TRUE) override;
89
    OGRErr DeleteField(int iField) override;
90
    OGRErr ReorderFields(int *panMap) override;
91
    virtual OGRErr AlterFieldDefn(int iField, OGRFieldDefn *poNewFieldDefn,
92
                                  int nFlags) override;
93
    virtual OGRErr CreateGeomField(const OGRGeomFieldDefn *poGeomField,
94
                                   int bApproxOK = TRUE) override;
95
96
    OGRErr IGetExtent(int iGeomField, OGREnvelope *psExtent,
97
                      bool bForce = true) override;
98
    OGRErr IGetExtent3D(int iGeomField, OGREnvelope3D *psExtent3D,
99
                        bool bForce = true) override;
100
101
    GDALDataset *GetDataset() override;
102
103
    //
104
    // OGRGeoJSONLayer Interface
105
    //
106
    void SetFIDColumn(const char *pszFIDColumn);
107
    void AddFeature(OGRFeature *poFeature);
108
    void DetectGeometryType();
109
110
    void IncFeatureCount()
111
0
    {
112
0
        nTotalFeatureCount_++;
113
0
    }
114
115
    void UnsetReader()
116
0
    {
117
0
        poReader_ = nullptr;
118
0
    }
119
120
    void InvalidateFeatureCount()
121
0
    {
122
0
        nTotalFeatureCount_ = -1;
123
0
    }
124
125
    void SetWriteOptions(const OGRGeoJSONWriteOptions &options)
126
0
    {
127
0
        oWriteOptions_ = options;
128
0
    }
129
130
    void SetSupportsMGeometries(bool bSupportsMGeometries)
131
0
    {
132
0
        m_bSupportsMGeometries = bSupportsMGeometries;
133
0
    }
134
135
    void SetSupportsZGeometries(bool bSupportsZGeometries)
136
0
    {
137
0
        m_bSupportsZGeometries = bSupportsZGeometries;
138
0
    }
139
140
  private:
141
    OGRGeoJSONDataSource *poDS_;
142
    OGRGeoJSONReader *poReader_;
143
    bool bHasAppendedFeatures_;
144
    CPLString sFIDColumn_;
145
    bool bOriginalIdModified_;
146
    GIntBig nTotalFeatureCount_;
147
    GIntBig nFeatureReadSinceReset_ = 0;
148
    bool m_bSupportsMGeometries = false;
149
    bool m_bSupportsZGeometries = true;
150
151
    //! Write options used by ICreateFeature() in append scenarios
152
    OGRGeoJSONWriteOptions oWriteOptions_;
153
154
    bool IngestAll();
155
    void TerminateAppendSession();
156
    bool SetOrUpdateFeaturePreparation();
157
158
    CPL_DISALLOW_COPY_ASSIGN(OGRGeoJSONLayer)
159
};
160
161
/************************************************************************/
162
/*                         OGRGeoJSONWriteLayer                         */
163
/************************************************************************/
164
165
class OGRGeoJSONWriteLayer final : public OGRLayer
166
{
167
  public:
168
    OGRGeoJSONWriteLayer(const char *pszName, OGRwkbGeometryType eGType,
169
                         CSLConstList papszOptions, bool bWriteFC_BBOXIn,
170
                         OGRCoordinateTransformation *poCT,
171
                         OGRGeoJSONDataSource *poDS);
172
    ~OGRGeoJSONWriteLayer() override;
173
174
    //
175
    // OGRLayer Interface
176
    //
177
    using OGRLayer::GetLayerDefn;
178
179
    const OGRFeatureDefn *GetLayerDefn() const override
180
0
    {
181
0
        return poFeatureDefn_;
182
0
    }
183
184
    const OGRSpatialReference *GetSpatialRef() const override
185
0
    {
186
0
        return nullptr;
187
0
    }
188
189
    void ResetReading() override
190
0
    {
191
0
    }
192
193
    OGRFeature *GetNextFeature() override
194
0
    {
195
0
        return nullptr;
196
0
    }
197
198
    OGRErr ICreateFeature(OGRFeature *poFeature) override;
199
    OGRErr CreateField(const OGRFieldDefn *poField, int bApproxOK) override;
200
    int TestCapability(const char *pszCap) const override;
201
202
    OGRErr IGetExtent(int iGeomField, OGREnvelope *psExtent,
203
                      bool bForce) override;
204
205
    OGRErr SyncToDisk() override;
206
207
    GDALDataset *GetDataset() override;
208
209
  private:
210
    OGRGeoJSONDataSource *poDS_;
211
    OGRFeatureDefn *poFeatureDefn_;
212
    int nOutCounter_;
213
    /** Offset at which the '] }' terminating sequence has already been
214
     * written by SyncToDisk(). 0 if it has not been written.
215
     */
216
    vsi_l_offset m_nPositionBeforeFCClosed = 0;
217
218
    bool bWriteBBOX;
219
    bool bBBOX3D;
220
    bool bWriteFC_BBOX;
221
    OGREnvelope3D sEnvelopeLayer;
222
223
    int nSignificantFigures_;
224
225
    bool bRFC7946_;
226
    bool bWrapDateLine_ = false;
227
    std::string osForeignMembers_{};
228
    OGRCoordinateTransformation *poCT_;
229
    OGRGeometryFactory::TransformWithOptionsCache oTransformCache_;
230
    OGRGeoJSONWriteOptions oWriteOptions_;
231
232
    CPL_DISALLOW_COPY_ASSIGN(OGRGeoJSONWriteLayer)
233
234
    void FinishWriting();
235
};
236
237
/************************************************************************/
238
/*                           OGRGeoJSONDataSource                       */
239
/************************************************************************/
240
241
class OGRGeoJSONDataSource final : public GDALDataset
242
{
243
  public:
244
    OGRGeoJSONDataSource();
245
    ~OGRGeoJSONDataSource() override;
246
247
    int Open(GDALOpenInfo *poOpenInfo, GeoJSONSourceType nSrcType,
248
             const char *pszJSonFlavor);
249
    int GetLayerCount() const override;
250
251
    using GDALDataset::GetLayer;
252
    const OGRLayer *GetLayer(int nLayer) const override;
253
    OGRLayer *ICreateLayer(const char *pszName,
254
                           const OGRGeomFieldDefn *poGeomFieldDefn,
255
                           CSLConstList papszOptions) override;
256
    int TestCapability(const char *pszCap) const override;
257
258
    void AddLayer(OGRGeoJSONLayer *poLayer);
259
260
    //
261
    // OGRGeoJSONDataSource Interface
262
    //
263
    int Create(const char *pszName, char **papszOptions);
264
265
    VSILFILE *GetOutputFile() const
266
0
    {
267
0
        return fpOut_;
268
0
    }
269
270
    enum GeometryTranslation
271
    {
272
        eGeometryPreserve,
273
        eGeometryAsCollection,
274
    };
275
276
    void SetGeometryTranslation(GeometryTranslation type);
277
278
    enum AttributesTranslation
279
    {
280
        eAttributesPreserve,
281
        eAttributesSkip
282
    };
283
284
    void SetAttributesTranslation(AttributesTranslation type);
285
286
    int GetFpOutputIsSeekable() const
287
0
    {
288
0
        return bFpOutputIsSeekable_;
289
0
    }
290
291
    int GetBBOXInsertLocation() const
292
0
    {
293
0
        return nBBOXInsertLocation_;
294
0
    }
295
296
    int HasOtherPages() const
297
0
    {
298
0
        return bOtherPages_;
299
0
    }
300
301
    bool IsUpdatable() const
302
0
    {
303
0
        return bUpdatable_;
304
0
    }
305
306
    const CPLString &GetJSonFlavor() const
307
0
    {
308
0
        return osJSonFlavor_;
309
0
    }
310
311
    void SetSupportsMGeometries(bool bSupportsMGeometries)
312
0
    {
313
0
        m_bSupportsMGeometries = bSupportsMGeometries;
314
0
    }
315
316
    void SetSupportsZGeometries(bool bSupportsZGeometries)
317
0
    {
318
0
        m_bSupportsZGeometries = bSupportsZGeometries;
319
0
    }
320
321
    CPLErr FlushCache(bool bAtClosing) override;
322
323
    CPLErr Close() override;
324
325
    // Analyze the OGR_SCHEMA open options and apply changes to the feature definition, return false in case of a critical error
326
    bool DealWithOgrSchemaOpenOption(const GDALOpenInfo *poOpenInfo);
327
328
    static const size_t SPACE_FOR_BBOX = 130;
329
330
  private:
331
    //
332
    // Private data members
333
    //
334
    char *pszName_;
335
    char *pszGeoData_;
336
    vsi_l_offset nGeoDataLen_;
337
    OGRGeoJSONLayer **papoLayers_;
338
    OGRGeoJSONWriteLayer **papoLayersWriter_;
339
    int nLayers_;
340
    VSILFILE *fpOut_;
341
342
    //
343
    // Translation/Creation control flags
344
    //
345
    GeometryTranslation flTransGeom_;
346
    AttributesTranslation flTransAttrs_;
347
    bool bOtherPages_;  // ESRI Feature Service specific.
348
349
    bool bFpOutputIsSeekable_;
350
    int nBBOXInsertLocation_;
351
352
    bool bUpdatable_;
353
354
    CPLString osJSonFlavor_;
355
356
    bool m_bSupportsMGeometries = false;
357
    bool m_bSupportsZGeometries = true;
358
359
    //
360
    // Private utility functions
361
    //
362
    bool Clear();
363
    int ReadFromFile(GDALOpenInfo *poOpenInfo, const char *pszUnprefixed);
364
    int ReadFromService(GDALOpenInfo *poOpenInfo, const char *pszSource);
365
    void LoadLayers(GDALOpenInfo *poOpenInfo, GeoJSONSourceType nSrcType,
366
                    const char *pszUnprefixed, const char *pszJSonFlavor);
367
    void SetOptionsOnReader(GDALOpenInfo *poOpenInfo,
368
                            OGRGeoJSONReader *poReader);
369
    void CheckExceededTransferLimit(json_object *poObj);
370
    void RemoveJSonPStuff();
371
372
    CPL_DISALLOW_COPY_ASSIGN(OGRGeoJSONDataSource)
373
};
374
375
#endif  // OGR_GEOJSON_H_INCLUDED