Coverage Report

Created: 2025-06-13 06:29

/src/gdal/ogr/ogrsf_frmts/geojson/ogr_geojson.h
Line
Count
Source (jump to first uncovered line)
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
    virtual ~OGRGeoJSONLayer();
65
66
    //
67
    // OGRLayer Interface
68
    //
69
    virtual const char *GetFIDColumn() override;
70
    virtual int TestCapability(const char *pszCap) override;
71
72
    virtual OGRErr SyncToDisk() override;
73
74
    virtual void ResetReading() override;
75
    virtual OGRFeature *GetNextFeature() override;
76
    virtual OGRFeature *GetFeature(GIntBig nFID) override;
77
    virtual 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
    virtual OGRErr DeleteFeature(GIntBig nFID) override;
87
    virtual OGRErr CreateField(const OGRFieldDefn *poField,
88
                               int bApproxOK = TRUE) override;
89
    virtual OGRErr DeleteField(int iField) override;
90
    virtual 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
    virtual OGRErr IGetExtent(int iGeomField, OGREnvelope *psExtent,
97
                              bool bForce = true) override;
98
    virtual 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();
173
174
    //
175
    // OGRLayer Interface
176
    //
177
    OGRFeatureDefn *GetLayerDefn() override
178
0
    {
179
0
        return poFeatureDefn_;
180
0
    }
181
182
    OGRSpatialReference *GetSpatialRef() override
183
0
    {
184
0
        return nullptr;
185
0
    }
186
187
    void ResetReading() override
188
0
    {
189
0
    }
190
191
    OGRFeature *GetNextFeature() override
192
0
    {
193
0
        return nullptr;
194
0
    }
195
196
    OGRErr ICreateFeature(OGRFeature *poFeature) override;
197
    OGRErr CreateField(const OGRFieldDefn *poField, int bApproxOK) override;
198
    int TestCapability(const char *pszCap) override;
199
200
    OGRErr IGetExtent(int iGeomField, OGREnvelope *psExtent,
201
                      bool bForce) override;
202
203
    OGRErr SyncToDisk() override;
204
205
    GDALDataset *GetDataset() override;
206
207
  private:
208
    OGRGeoJSONDataSource *poDS_;
209
    OGRFeatureDefn *poFeatureDefn_;
210
    int nOutCounter_;
211
    /** Offset at which the '] }' terminating sequence has already been
212
     * written by SyncToDisk(). 0 if it has not been written.
213
     */
214
    vsi_l_offset m_nPositionBeforeFCClosed = 0;
215
216
    bool bWriteBBOX;
217
    bool bBBOX3D;
218
    bool bWriteFC_BBOX;
219
    OGREnvelope3D sEnvelopeLayer;
220
221
    int nSignificantFigures_;
222
223
    bool bRFC7946_;
224
    bool bWrapDateLine_ = false;
225
    std::string osForeignMembers_{};
226
    OGRCoordinateTransformation *poCT_;
227
    OGRGeometryFactory::TransformWithOptionsCache oTransformCache_;
228
    OGRGeoJSONWriteOptions oWriteOptions_;
229
230
    CPL_DISALLOW_COPY_ASSIGN(OGRGeoJSONWriteLayer)
231
232
    void FinishWriting();
233
};
234
235
/************************************************************************/
236
/*                           OGRGeoJSONDataSource                       */
237
/************************************************************************/
238
239
class OGRGeoJSONDataSource final : public GDALDataset
240
{
241
  public:
242
    OGRGeoJSONDataSource();
243
    virtual ~OGRGeoJSONDataSource();
244
245
    int Open(GDALOpenInfo *poOpenInfo, GeoJSONSourceType nSrcType,
246
             const char *pszJSonFlavor);
247
    int GetLayerCount() override;
248
    OGRLayer *GetLayer(int nLayer) override;
249
    OGRLayer *ICreateLayer(const char *pszName,
250
                           const OGRGeomFieldDefn *poGeomFieldDefn,
251
                           CSLConstList papszOptions) override;
252
    int TestCapability(const char *pszCap) override;
253
254
    void AddLayer(OGRGeoJSONLayer *poLayer);
255
256
    //
257
    // OGRGeoJSONDataSource Interface
258
    //
259
    int Create(const char *pszName, char **papszOptions);
260
261
    VSILFILE *GetOutputFile() const
262
0
    {
263
0
        return fpOut_;
264
0
    }
265
266
    enum GeometryTranslation
267
    {
268
        eGeometryPreserve,
269
        eGeometryAsCollection,
270
    };
271
272
    void SetGeometryTranslation(GeometryTranslation type);
273
274
    enum AttributesTranslation
275
    {
276
        eAttributesPreserve,
277
        eAttributesSkip
278
    };
279
280
    void SetAttributesTranslation(AttributesTranslation type);
281
282
    int GetFpOutputIsSeekable() const
283
0
    {
284
0
        return bFpOutputIsSeekable_;
285
0
    }
286
287
    int GetBBOXInsertLocation() const
288
0
    {
289
0
        return nBBOXInsertLocation_;
290
0
    }
291
292
    int HasOtherPages() const
293
0
    {
294
0
        return bOtherPages_;
295
0
    }
296
297
    bool IsUpdatable() const
298
0
    {
299
0
        return bUpdatable_;
300
0
    }
301
302
    const CPLString &GetJSonFlavor() const
303
0
    {
304
0
        return osJSonFlavor_;
305
0
    }
306
307
    void SetSupportsMGeometries(bool bSupportsMGeometries)
308
0
    {
309
0
        m_bSupportsMGeometries = bSupportsMGeometries;
310
0
    }
311
312
    void SetSupportsZGeometries(bool bSupportsZGeometries)
313
0
    {
314
0
        m_bSupportsZGeometries = bSupportsZGeometries;
315
0
    }
316
317
    virtual CPLErr FlushCache(bool bAtClosing) override;
318
319
    CPLErr Close() override;
320
321
    // Analyze the OGR_SCHEMA open options and apply changes to the feature definition, return false in case of a critical error
322
    bool DealWithOgrSchemaOpenOption(const GDALOpenInfo *poOpenInfo);
323
324
    static const size_t SPACE_FOR_BBOX = 130;
325
326
  private:
327
    //
328
    // Private data members
329
    //
330
    char *pszName_;
331
    char *pszGeoData_;
332
    vsi_l_offset nGeoDataLen_;
333
    OGRGeoJSONLayer **papoLayers_;
334
    OGRGeoJSONWriteLayer **papoLayersWriter_;
335
    int nLayers_;
336
    VSILFILE *fpOut_;
337
338
    //
339
    // Translation/Creation control flags
340
    //
341
    GeometryTranslation flTransGeom_;
342
    AttributesTranslation flTransAttrs_;
343
    bool bOtherPages_;  // ESRI Feature Service specific.
344
345
    bool bFpOutputIsSeekable_;
346
    int nBBOXInsertLocation_;
347
348
    bool bUpdatable_;
349
350
    CPLString osJSonFlavor_;
351
352
    bool m_bSupportsMGeometries = false;
353
    bool m_bSupportsZGeometries = true;
354
355
    //
356
    // Private utility functions
357
    //
358
    bool Clear();
359
    int ReadFromFile(GDALOpenInfo *poOpenInfo, const char *pszUnprefixed);
360
    int ReadFromService(GDALOpenInfo *poOpenInfo, const char *pszSource);
361
    void LoadLayers(GDALOpenInfo *poOpenInfo, GeoJSONSourceType nSrcType,
362
                    const char *pszUnprefixed, const char *pszJSonFlavor);
363
    void SetOptionsOnReader(GDALOpenInfo *poOpenInfo,
364
                            OGRGeoJSONReader *poReader);
365
    void CheckExceededTransferLimit(json_object *poObj);
366
    void RemoveJSonPStuff();
367
368
    CPL_DISALLOW_COPY_ASSIGN(OGRGeoJSONDataSource)
369
};
370
371
#endif  // OGR_GEOJSON_H_INCLUDED