Coverage Report

Created: 2026-02-14 09:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gdal/ogr/ogrsf_frmts/geojson/ogrgeojsonlayer.cpp
Line
Count
Source
1
/******************************************************************************
2
 *
3
 * Project:  OpenGIS Simple Features Reference Implementation
4
 * Purpose:  Implementation of OGRGeoJSONLayer class (OGR GeoJSON Driver).
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
#include <algorithm>
15
16
#if !DEBUG_JSON
17
#ifdef __clang__
18
#pragma clang diagnostic push
19
#pragma clang diagnostic ignored "-Wunknown-pragmas"
20
#pragma clang diagnostic ignored "-Wdocumentation"
21
#pragma clang diagnostic ignored "-Wold-style-cast"
22
#endif
23
#endif  // !DEBUG_VERBOSE
24
25
#include <json.h>
26
27
#if !DEBUG_JSON
28
#ifdef __clang
29
#pragma clang diagnostic pop
30
#endif
31
#endif  // !DEBUG_VERBOSE
32
33
#include "ogr_geojson.h"
34
#include "ogrgeojsonreader.h"
35
36
/************************************************************************/
37
/*                      STATIC MEMBERS DEFINITION                       */
38
/************************************************************************/
39
40
const char *const OGRGeoJSONLayer::DefaultName = "OGRGeoJSON";
41
const OGRwkbGeometryType OGRGeoJSONLayer::DefaultGeometryType = wkbUnknown;
42
43
/************************************************************************/
44
/*                           OGRGeoJSONLayer                            */
45
/************************************************************************/
46
47
OGRGeoJSONLayer::OGRGeoJSONLayer(const char *pszName,
48
                                 OGRSpatialReference *poSRSIn,
49
                                 OGRwkbGeometryType eGType,
50
                                 OGRGeoJSONDataSource *poDS,
51
                                 OGRGeoJSONReader *poReader)
52
3.35k
    : OGRMemLayer(pszName, poSRSIn, eGType), poDS_(poDS), poReader_(poReader),
53
3.35k
      bHasAppendedFeatures_(false), bOriginalIdModified_(false),
54
3.35k
      nTotalFeatureCount_(0)
55
3.35k
{
56
3.35k
    SetAdvertizeUTF8(true);
57
3.35k
    SetUpdatable(poDS->IsUpdatable());
58
3.35k
}
59
60
/************************************************************************/
61
/*                           ~OGRGeoJSONLayer                           */
62
/************************************************************************/
63
64
OGRGeoJSONLayer::~OGRGeoJSONLayer()
65
3.35k
{
66
3.35k
    TerminateAppendSession();
67
3.35k
    delete poReader_;
68
3.35k
}
69
70
/************************************************************************/
71
/*                       TerminateAppendSession()                       */
72
/************************************************************************/
73
74
void OGRGeoJSONLayer::TerminateAppendSession()
75
3.79k
{
76
3.79k
    if (bHasAppendedFeatures_)
77
0
    {
78
0
#if defined(__GNUC__)
79
0
#pragma GCC diagnostic push
80
0
#pragma GCC diagnostic ignored "-Wnull-dereference"
81
0
#endif
82
0
        VSILFILE *fp = poReader_->GetFP();
83
0
#if defined(__GNUC__)
84
0
#pragma GCC diagnostic pop
85
0
#endif
86
0
        VSIFPrintfL(fp, "\n]\n}\n");
87
0
        VSIFFlushL(fp);
88
0
        bHasAppendedFeatures_ = false;
89
0
    }
90
3.79k
}
91
92
/************************************************************************/
93
/*                             GetFIDColumn                             */
94
/************************************************************************/
95
96
const char *OGRGeoJSONLayer::GetFIDColumn() const
97
10.5k
{
98
10.5k
    return sFIDColumn_.c_str();
99
10.5k
}
100
101
/************************************************************************/
102
/*                             SetFIDColumn                             */
103
/************************************************************************/
104
105
void OGRGeoJSONLayer::SetFIDColumn(const char *pszFIDColumn)
106
7
{
107
7
    sFIDColumn_ = pszFIDColumn;
108
7
}
109
110
/************************************************************************/
111
/*                            ResetReading()                            */
112
/************************************************************************/
113
114
void OGRGeoJSONLayer::ResetReading()
115
2.24k
{
116
2.24k
    nFeatureReadSinceReset_ = 0;
117
2.24k
    if (poReader_)
118
438
    {
119
438
        TerminateAppendSession();
120
438
        poReader_->ResetReading();
121
438
    }
122
1.80k
    else
123
1.80k
        OGRMemLayer::ResetReading();
124
2.24k
}
125
126
/************************************************************************/
127
/*                           GetNextFeature()                           */
128
/************************************************************************/
129
130
OGRFeature *OGRGeoJSONLayer::GetNextFeature()
131
14.2k
{
132
14.2k
    if (poReader_)
133
6.60k
    {
134
6.60k
        if (bHasAppendedFeatures_)
135
0
        {
136
0
            ResetReading();
137
0
        }
138
6.60k
        while (true)
139
6.60k
        {
140
6.60k
            OGRFeature *poFeature = poReader_->GetNextFeature(this);
141
6.60k
            if (poFeature == nullptr)
142
156
                return nullptr;
143
6.44k
            if ((m_poFilterGeom == nullptr ||
144
0
                 FilterGeometry(
145
0
                     poFeature->GetGeomFieldRef(m_iGeomFieldFilter))) &&
146
6.44k
                (m_poAttrQuery == nullptr ||
147
0
                 m_poAttrQuery->Evaluate(poFeature)))
148
6.44k
            {
149
6.44k
                nFeatureReadSinceReset_++;
150
6.44k
                return poFeature;
151
6.44k
            }
152
0
            delete poFeature;
153
0
        }
154
6.60k
    }
155
7.61k
    else
156
7.61k
    {
157
7.61k
        auto ret = OGRMemLayer::GetNextFeature();
158
7.61k
        if (ret)
159
6.73k
        {
160
6.73k
            nFeatureReadSinceReset_++;
161
6.73k
        }
162
7.61k
        return ret;
163
7.61k
    }
164
14.2k
}
165
166
/************************************************************************/
167
/*                          GetFeatureCount()                           */
168
/************************************************************************/
169
170
GIntBig OGRGeoJSONLayer::GetFeatureCount(int bForce)
171
4.11k
{
172
4.11k
    if (poReader_)
173
438
    {
174
438
        if (m_poFilterGeom == nullptr && m_poAttrQuery == nullptr &&
175
438
            nTotalFeatureCount_ >= 0)
176
438
        {
177
438
            return nTotalFeatureCount_;
178
438
        }
179
0
        return OGRLayer::GetFeatureCount(bForce);
180
438
    }
181
3.67k
    else
182
3.67k
    {
183
3.67k
        return OGRMemLayer::GetFeatureCount(bForce);
184
3.67k
    }
185
4.11k
}
186
187
/************************************************************************/
188
/*                             GetFeature()                             */
189
/************************************************************************/
190
191
OGRFeature *OGRGeoJSONLayer::GetFeature(GIntBig nFID)
192
4.50k
{
193
4.50k
    if (poReader_)
194
0
    {
195
0
        if (!IsUpdatable())
196
0
        {
197
0
            return poReader_->GetFeature(this, nFID);
198
0
        }
199
0
        return OGRLayer::GetFeature(nFID);
200
0
    }
201
4.50k
    else
202
4.50k
    {
203
4.50k
        return OGRMemLayer::GetFeature(nFID);
204
4.50k
    }
205
4.50k
}
206
207
/************************************************************************/
208
/*                             IngestAll()                              */
209
/************************************************************************/
210
211
bool OGRGeoJSONLayer::IngestAll()
212
0
{
213
0
    if (poReader_)
214
0
    {
215
0
        TerminateAppendSession();
216
217
0
        OGRGeoJSONReader *poReader = poReader_;
218
0
        poReader_ = nullptr;
219
220
0
        nTotalFeatureCount_ = -1;
221
0
        bool bRet = poReader->IngestAll(this);
222
0
        delete poReader;
223
0
        return bRet;
224
0
    }
225
0
    else
226
0
    {
227
0
        return true;
228
0
    }
229
0
}
230
231
/************************************************************************/
232
/*                   SetOrUpdateFeaturePreparation()                    */
233
/************************************************************************/
234
235
bool OGRGeoJSONLayer::SetOrUpdateFeaturePreparation()
236
0
{
237
0
    if (!IsUpdatable())
238
0
        return false;
239
0
    if (poReader_)
240
0
    {
241
0
        auto nNextIndex = nFeatureReadSinceReset_;
242
0
        if (!IngestAll())
243
0
            return false;
244
0
        SetNextByIndex(nNextIndex);
245
0
    }
246
0
    return true;
247
0
}
248
249
/************************************************************************/
250
/*                            ISetFeature()                             */
251
/************************************************************************/
252
253
OGRErr OGRGeoJSONLayer::ISetFeature(OGRFeature *poFeature)
254
0
{
255
0
    if (!SetOrUpdateFeaturePreparation())
256
0
        return OGRERR_FAILURE;
257
0
    return OGRMemLayer::ISetFeature(poFeature);
258
0
}
259
260
/************************************************************************/
261
/*                           IUpdateFeature()                           */
262
/************************************************************************/
263
264
OGRErr OGRGeoJSONLayer::IUpdateFeature(OGRFeature *poFeature,
265
                                       int nUpdatedFieldsCount,
266
                                       const int *panUpdatedFieldsIdx,
267
                                       int nUpdatedGeomFieldsCount,
268
                                       const int *panUpdatedGeomFieldsIdx,
269
                                       bool bUpdateStyleString)
270
0
{
271
0
    if (!SetOrUpdateFeaturePreparation())
272
0
        return OGRERR_FAILURE;
273
0
    return OGRMemLayer::IUpdateFeature(
274
0
        poFeature, nUpdatedFieldsCount, panUpdatedFieldsIdx,
275
0
        nUpdatedGeomFieldsCount, panUpdatedGeomFieldsIdx, bUpdateStyleString);
276
0
}
277
278
/************************************************************************/
279
/*                           ICreateFeature()                           */
280
/************************************************************************/
281
282
OGRErr OGRGeoJSONLayer::ICreateFeature(OGRFeature *poFeature)
283
0
{
284
0
    if (!IsUpdatable())
285
0
        return OGRERR_FAILURE;
286
0
    if (poReader_)
287
0
    {
288
0
        bool bTryEasyAppend = true;
289
0
        while (true)
290
0
        {
291
            // We can trivially append to end of existing file, provided the
292
            // following conditions are met:
293
            // * the "features" array member is the last one of the main
294
            //   object (poReader_->CanEasilyAppend())
295
            // * there is no "bbox" at feature collection level (could possibly
296
            //   be supported)
297
            // * the features have no explicit FID field, so it is trivial to
298
            //   derive the FID of newly created features without collision
299
            // * we know the total number of existing features
300
0
            if (bTryEasyAppend && poReader_->CanEasilyAppend() &&
301
0
                !poReader_->FCHasBBOX() && sFIDColumn_.empty() &&
302
0
                GetLayerDefn()->GetFieldIndex("id") < 0 &&
303
0
                nTotalFeatureCount_ >= 0)
304
0
            {
305
0
                VSILFILE *fp = poReader_->GetFP();
306
0
                if (!bHasAppendedFeatures_)
307
0
                {
308
                    // Locate "} ] }" (or "[ ] }") pattern at end of file
309
0
                    VSIFSeekL(fp, 0, SEEK_END);
310
0
                    vsi_l_offset nOffset = VSIFTellL(fp);
311
0
                    nOffset -= 10;
312
0
                    VSIFSeekL(fp, nOffset, SEEK_SET);
313
0
                    char szBuffer[11];
314
0
                    VSIFReadL(szBuffer, 10, 1, fp);
315
0
                    szBuffer[10] = 0;
316
0
                    int i = 9;
317
                    // Locate final }
318
0
                    while (isspace(static_cast<unsigned char>(szBuffer[i])) &&
319
0
                           i > 0)
320
0
                        i--;
321
0
                    if (szBuffer[i] != '}')
322
0
                    {
323
0
                        bTryEasyAppend = false;
324
0
                        continue;
325
0
                    }
326
0
                    if (i > 0)
327
0
                        i--;
328
                    // Locate ']' ending features array
329
0
                    while (isspace(static_cast<unsigned char>(szBuffer[i])) &&
330
0
                           i > 0)
331
0
                        i--;
332
0
                    if (szBuffer[i] != ']')
333
0
                    {
334
0
                        bTryEasyAppend = false;
335
0
                        continue;
336
0
                    }
337
0
                    if (i > 0)
338
0
                        i--;
339
0
                    while (isspace(static_cast<unsigned char>(szBuffer[i])) &&
340
0
                           i > 0)
341
0
                        i--;
342
                    // Locate '}' ending last feature, or '[' starting features
343
                    // array
344
0
                    if (szBuffer[i] != '}' && szBuffer[i] != '[')
345
0
                    {
346
0
                        bTryEasyAppend = false;
347
0
                        continue;
348
0
                    }
349
0
                    bool bExistingFeature = szBuffer[i] == '}';
350
0
                    nOffset += i + 1;
351
0
                    VSIFSeekL(fp, nOffset, SEEK_SET);
352
0
                    if (bExistingFeature)
353
0
                    {
354
0
                        VSIFPrintfL(fp, ",");
355
0
                    }
356
0
                    VSIFPrintfL(fp, "\n");
357
0
                    bHasAppendedFeatures_ = true;
358
0
                }
359
0
                else
360
0
                {
361
0
                    VSIFPrintfL(fp, ",\n");
362
0
                }
363
0
                json_object *poObj =
364
0
                    OGRGeoJSONWriteFeature(poFeature, oWriteOptions_);
365
366
0
                const char *pszJson = json_object_to_json_string_ext(
367
0
                    poObj, JSON_C_TO_STRING_PLAIN
368
0
#ifdef JSON_C_TO_STRING_NOSLASHESCAPE
369
0
                               | JSON_C_TO_STRING_NOSLASHESCAPE
370
0
#endif
371
0
                );
372
373
0
                VSIFPrintfL(fp, "%s", pszJson);
374
0
                json_object_put(poObj);
375
376
0
                if (poFeature->GetFID() == OGRNullFID)
377
0
                {
378
0
                    poFeature->SetFID(nTotalFeatureCount_);
379
0
                }
380
0
                nTotalFeatureCount_++;
381
382
0
                return OGRERR_NONE;
383
0
            }
384
0
            else if (IngestAll())
385
0
            {
386
0
                break;
387
0
            }
388
0
            else
389
0
            {
390
0
                return OGRERR_FAILURE;
391
0
            }
392
0
        }
393
0
    }
394
0
    return OGRMemLayer::ICreateFeature(poFeature);
395
0
}
396
397
/************************************************************************/
398
/*                           DeleteFeature()                            */
399
/************************************************************************/
400
401
OGRErr OGRGeoJSONLayer::DeleteFeature(GIntBig nFID)
402
0
{
403
0
    if (!IsUpdatable() || !IngestAll())
404
0
        return OGRERR_FAILURE;
405
0
    return OGRMemLayer::DeleteFeature(nFID);
406
0
}
407
408
/************************************************************************/
409
/*                            CreateField()                             */
410
/************************************************************************/
411
412
OGRErr OGRGeoJSONLayer::CreateField(const OGRFieldDefn *poField, int bApproxOK)
413
0
{
414
0
    if (!IsUpdatable() || !IngestAll())
415
0
        return OGRERR_FAILURE;
416
0
    return OGRMemLayer::CreateField(poField, bApproxOK);
417
0
}
418
419
/************************************************************************/
420
/*                            DeleteField()                             */
421
/************************************************************************/
422
423
OGRErr OGRGeoJSONLayer::DeleteField(int iField)
424
0
{
425
0
    if (!IsUpdatable() || !IngestAll())
426
0
        return OGRERR_FAILURE;
427
0
    return OGRMemLayer::DeleteField(iField);
428
0
}
429
430
/************************************************************************/
431
/*                           ReorderFields()                            */
432
/************************************************************************/
433
434
OGRErr OGRGeoJSONLayer::ReorderFields(int *panMap)
435
0
{
436
0
    if (!IsUpdatable() || !IngestAll())
437
0
        return OGRERR_FAILURE;
438
0
    return OGRMemLayer::ReorderFields(panMap);
439
0
}
440
441
/************************************************************************/
442
/*                           AlterFieldDefn()                           */
443
/************************************************************************/
444
445
OGRErr OGRGeoJSONLayer::AlterFieldDefn(int iField, OGRFieldDefn *poNewFieldDefn,
446
                                       int nFlagsIn)
447
0
{
448
0
    if (!IsUpdatable() || !IngestAll())
449
0
        return OGRERR_FAILURE;
450
0
    return OGRMemLayer::AlterFieldDefn(iField, poNewFieldDefn, nFlagsIn);
451
0
}
452
453
/************************************************************************/
454
/*                          CreateGeomField()                           */
455
/************************************************************************/
456
457
OGRErr OGRGeoJSONLayer::CreateGeomField(const OGRGeomFieldDefn *poGeomField,
458
                                        int bApproxOK)
459
0
{
460
0
    if (!IsUpdatable() || !IngestAll())
461
0
        return OGRERR_FAILURE;
462
0
    return OGRMemLayer::CreateGeomField(poGeomField, bApproxOK);
463
0
}
464
465
OGRErr OGRGeoJSONLayer::IGetExtent(int iGeomField, OGREnvelope *psExtent,
466
                                   bool bForce)
467
0
{
468
0
    if (iGeomField != 0)
469
0
    {
470
0
        return OGRERR_FAILURE;
471
0
    }
472
473
0
    if (poReader_ && poReader_->ExtentRead() &&
474
0
        TestCapability(OLCFastGetExtent))
475
0
    {
476
0
        *psExtent = poReader_->GetExtent3D();
477
0
        return OGRERR_NONE;
478
0
    }
479
0
    else
480
0
    {
481
0
        return OGRMemLayer::IGetExtent(iGeomField, psExtent, bForce);
482
0
    }
483
0
}
484
485
OGRErr OGRGeoJSONLayer::IGetExtent3D(int iGeomField, OGREnvelope3D *psExtent3D,
486
                                     bool bForce)
487
0
{
488
489
0
    if (iGeomField != 0)
490
0
    {
491
0
        return OGRERR_FAILURE;
492
0
    }
493
494
0
    if (poReader_ && poReader_->ExtentRead() &&
495
0
        TestCapability(OLCFastGetExtent3D))
496
0
    {
497
0
        *psExtent3D = poReader_->GetExtent3D();
498
0
        return OGRERR_NONE;
499
0
    }
500
0
    else
501
0
    {
502
0
        return OGRMemLayer::IGetExtent3D(iGeomField, psExtent3D, bForce);
503
0
    }
504
0
}
505
506
/************************************************************************/
507
/*                           TestCapability()                           */
508
/************************************************************************/
509
510
int OGRGeoJSONLayer::TestCapability(const char *pszCap) const
511
512
928
{
513
928
    if (EQUAL(pszCap, OLCCurveGeometries))
514
464
        return FALSE;
515
464
    else if (EQUAL(pszCap, OLCMeasuredGeometries))
516
464
        return m_bSupportsMGeometries;
517
0
    else if (EQUAL(pszCap, OLCZGeometries))
518
0
        return m_bSupportsZGeometries;
519
0
    else if (EQUAL(pszCap, OLCStringsAsUTF8))
520
0
        return TRUE;
521
0
    else if (EQUAL(pszCap, OLCFastGetExtent) ||
522
0
             EQUAL(pszCap, OLCFastGetExtent3D))
523
0
        return m_poFilterGeom == nullptr && m_poAttrQuery == nullptr;
524
0
    return OGRMemLayer::TestCapability(pszCap);
525
928
}
526
527
/************************************************************************/
528
/*                             SyncToDisk()                             */
529
/************************************************************************/
530
531
OGRErr OGRGeoJSONLayer::SyncToDisk()
532
0
{
533
0
    TerminateAppendSession();
534
535
0
    poDS_->FlushCache(false);
536
0
    return OGRERR_NONE;
537
0
}
538
539
/************************************************************************/
540
/*                              AddFeature                              */
541
/************************************************************************/
542
543
void OGRGeoJSONLayer::AddFeature(std::unique_ptr<OGRFeature> poFeature)
544
3.74k
{
545
3.74k
    GIntBig nFID = poFeature->GetFID();
546
547
    // Detect potential FID duplicates and make sure they are eventually
548
    // unique.
549
3.74k
    if (-1 == nFID)
550
3.53k
    {
551
3.53k
        nFID = GetFeatureCount(FALSE);
552
3.53k
        OGRFeature *poTryFeature = nullptr;
553
4.08k
        while ((poTryFeature = GetFeature(nFID)) != nullptr)
554
554
        {
555
554
            nFID++;
556
554
            delete poTryFeature;
557
554
        }
558
3.53k
    }
559
210
    else
560
210
    {
561
210
        OGRFeature *poTryFeature = nullptr;
562
210
        if ((poTryFeature = GetFeature(nFID)) != nullptr)
563
144
        {
564
144
            if (!bOriginalIdModified_)
565
26
            {
566
26
                CPLError(
567
26
                    CE_Warning, CPLE_AppDefined,
568
26
                    "Several features with id = " CPL_FRMT_GIB " have been "
569
26
                    "found. Altering it to be unique. This warning will not "
570
26
                    "be emitted anymore for this layer",
571
26
                    nFID);
572
26
                bOriginalIdModified_ = true;
573
26
            }
574
144
            delete poTryFeature;
575
144
            nFID = GetFeatureCount(FALSE);
576
207
            while ((poTryFeature = GetFeature(nFID)) != nullptr)
577
63
            {
578
63
                nFID++;
579
63
                delete poTryFeature;
580
63
            }
581
144
        }
582
210
    }
583
3.74k
    poFeature->SetFID(nFID);
584
585
3.74k
    if (!CPL_INT64_FITS_ON_INT32(nFID))
586
14
        SetMetadataItem(OLMD_FID64, "YES");
587
588
3.74k
    const bool bIsUpdatable = IsUpdatable();
589
3.74k
    SetUpdatable(true);  // Temporary toggle on updatable flag.
590
3.74k
    CPL_IGNORE_RET_VAL(OGRMemLayer::SetFeature(std::move(poFeature)));
591
3.74k
    SetUpdatable(bIsUpdatable);
592
3.74k
    SetUpdated(false);
593
3.74k
}
594
595
/************************************************************************/
596
/*                          DetectGeometryType                          */
597
/************************************************************************/
598
599
void OGRGeoJSONLayer::DetectGeometryType()
600
466
{
601
466
    auto poFDefn = GetLayerDefn();
602
466
    if (poFDefn->GetGeomType() != wkbUnknown)
603
19
        return;
604
605
447
    ResetReading();
606
447
    bool bFirstGeometry = true;
607
447
    OGRwkbGeometryType eLayerGeomType = wkbUnknown;
608
447
    for (const auto &poFeature : *this)
609
2.98k
    {
610
2.98k
        const OGRGeometry *poGeometry = poFeature->GetGeometryRef();
611
2.98k
        if (nullptr != poGeometry)
612
116
        {
613
116
            OGRwkbGeometryType eGeomType = poGeometry->getGeometryType();
614
116
            if (!OGRGeoJSONUpdateLayerGeomType(bFirstGeometry, eGeomType,
615
116
                                               eLayerGeomType))
616
25
            {
617
25
                break;
618
25
            }
619
116
        }
620
2.98k
    }
621
622
447
    {
623
447
        auto oTemporaryUnsealer(poFDefn->GetTemporaryUnsealer());
624
447
        poFDefn->SetGeomType(eLayerGeomType);
625
447
    }
626
627
447
    ResetReading();
628
447
}
629
630
/************************************************************************/
631
/*                             GetDataset()                             */
632
/************************************************************************/
633
634
GDALDataset *OGRGeoJSONLayer::GetDataset()
635
0
{
636
0
    return poDS_;
637
0
}