Coverage Report

Created: 2025-06-13 06:29

/src/gdal/ogr/ogrsf_frmts/geojson/ogrgeojsonlayer.cpp
Line
Count
Source (jump to first uncovered line)
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
0
    : OGRMemLayer(pszName, poSRSIn, eGType), poDS_(poDS), poReader_(poReader),
53
0
      bHasAppendedFeatures_(false), bOriginalIdModified_(false),
54
0
      nTotalFeatureCount_(0)
55
0
{
56
0
    SetAdvertizeUTF8(true);
57
0
    SetUpdatable(poDS->IsUpdatable());
58
0
}
59
60
/************************************************************************/
61
/*                          ~OGRGeoJSONLayer                            */
62
/************************************************************************/
63
64
OGRGeoJSONLayer::~OGRGeoJSONLayer()
65
0
{
66
0
    TerminateAppendSession();
67
0
    delete poReader_;
68
0
}
69
70
/************************************************************************/
71
/*                      TerminateAppendSession()                        */
72
/************************************************************************/
73
74
void OGRGeoJSONLayer::TerminateAppendSession()
75
0
{
76
0
    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
0
}
91
92
/************************************************************************/
93
/*                           GetFIDColumn                               */
94
/************************************************************************/
95
96
const char *OGRGeoJSONLayer::GetFIDColumn()
97
0
{
98
0
    return sFIDColumn_.c_str();
99
0
}
100
101
/************************************************************************/
102
/*                           SetFIDColumn                               */
103
/************************************************************************/
104
105
void OGRGeoJSONLayer::SetFIDColumn(const char *pszFIDColumn)
106
0
{
107
0
    sFIDColumn_ = pszFIDColumn;
108
0
}
109
110
/************************************************************************/
111
/*                            ResetReading()                            */
112
/************************************************************************/
113
114
void OGRGeoJSONLayer::ResetReading()
115
0
{
116
0
    nFeatureReadSinceReset_ = 0;
117
0
    if (poReader_)
118
0
    {
119
0
        TerminateAppendSession();
120
0
        poReader_->ResetReading();
121
0
    }
122
0
    else
123
0
        OGRMemLayer::ResetReading();
124
0
}
125
126
/************************************************************************/
127
/*                           GetNextFeature()                           */
128
/************************************************************************/
129
130
OGRFeature *OGRGeoJSONLayer::GetNextFeature()
131
0
{
132
0
    if (poReader_)
133
0
    {
134
0
        if (bHasAppendedFeatures_)
135
0
        {
136
0
            ResetReading();
137
0
        }
138
0
        while (true)
139
0
        {
140
0
            OGRFeature *poFeature = poReader_->GetNextFeature(this);
141
0
            if (poFeature == nullptr)
142
0
                return nullptr;
143
0
            if ((m_poFilterGeom == nullptr ||
144
0
                 FilterGeometry(
145
0
                     poFeature->GetGeomFieldRef(m_iGeomFieldFilter))) &&
146
0
                (m_poAttrQuery == nullptr ||
147
0
                 m_poAttrQuery->Evaluate(poFeature)))
148
0
            {
149
0
                nFeatureReadSinceReset_++;
150
0
                return poFeature;
151
0
            }
152
0
            delete poFeature;
153
0
        }
154
0
    }
155
0
    else
156
0
    {
157
0
        auto ret = OGRMemLayer::GetNextFeature();
158
0
        if (ret)
159
0
        {
160
0
            nFeatureReadSinceReset_++;
161
0
        }
162
0
        return ret;
163
0
    }
164
0
}
165
166
/************************************************************************/
167
/*                          GetFeatureCount()                           */
168
/************************************************************************/
169
170
GIntBig OGRGeoJSONLayer::GetFeatureCount(int bForce)
171
0
{
172
0
    if (poReader_)
173
0
    {
174
0
        if (m_poFilterGeom == nullptr && m_poAttrQuery == nullptr &&
175
0
            nTotalFeatureCount_ >= 0)
176
0
        {
177
0
            return nTotalFeatureCount_;
178
0
        }
179
0
        return OGRLayer::GetFeatureCount(bForce);
180
0
    }
181
0
    else
182
0
    {
183
0
        return OGRMemLayer::GetFeatureCount(bForce);
184
0
    }
185
0
}
186
187
/************************************************************************/
188
/*                            GetFeature()                              */
189
/************************************************************************/
190
191
OGRFeature *OGRGeoJSONLayer::GetFeature(GIntBig nFID)
192
0
{
193
0
    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
0
    else
202
0
    {
203
0
        return OGRMemLayer::GetFeature(nFID);
204
0
    }
205
0
}
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
0
                VSIFPrintfL(fp, "%s", json_object_to_json_string(poObj));
366
0
                json_object_put(poObj);
367
368
0
                if (poFeature->GetFID() == OGRNullFID)
369
0
                {
370
0
                    poFeature->SetFID(nTotalFeatureCount_);
371
0
                }
372
0
                nTotalFeatureCount_++;
373
374
0
                return OGRERR_NONE;
375
0
            }
376
0
            else if (IngestAll())
377
0
            {
378
0
                break;
379
0
            }
380
0
            else
381
0
            {
382
0
                return OGRERR_FAILURE;
383
0
            }
384
0
        }
385
0
    }
386
0
    return OGRMemLayer::ICreateFeature(poFeature);
387
0
}
388
389
/************************************************************************/
390
/*                          DeleteFeature()                             */
391
/************************************************************************/
392
393
OGRErr OGRGeoJSONLayer::DeleteFeature(GIntBig nFID)
394
0
{
395
0
    if (!IsUpdatable() || !IngestAll())
396
0
        return OGRERR_FAILURE;
397
0
    return OGRMemLayer::DeleteFeature(nFID);
398
0
}
399
400
/************************************************************************/
401
/*                           CreateField()                              */
402
/************************************************************************/
403
404
OGRErr OGRGeoJSONLayer::CreateField(const OGRFieldDefn *poField, int bApproxOK)
405
0
{
406
0
    if (!IsUpdatable() || !IngestAll())
407
0
        return OGRERR_FAILURE;
408
0
    return OGRMemLayer::CreateField(poField, bApproxOK);
409
0
}
410
411
/************************************************************************/
412
/*                          DeleteField()                               */
413
/************************************************************************/
414
415
OGRErr OGRGeoJSONLayer::DeleteField(int iField)
416
0
{
417
0
    if (!IsUpdatable() || !IngestAll())
418
0
        return OGRERR_FAILURE;
419
0
    return OGRMemLayer::DeleteField(iField);
420
0
}
421
422
/************************************************************************/
423
/*                          ReorderFields()                             */
424
/************************************************************************/
425
426
OGRErr OGRGeoJSONLayer::ReorderFields(int *panMap)
427
0
{
428
0
    if (!IsUpdatable() || !IngestAll())
429
0
        return OGRERR_FAILURE;
430
0
    return OGRMemLayer::ReorderFields(panMap);
431
0
}
432
433
/************************************************************************/
434
/*                         AlterFieldDefn()                             */
435
/************************************************************************/
436
437
OGRErr OGRGeoJSONLayer::AlterFieldDefn(int iField, OGRFieldDefn *poNewFieldDefn,
438
                                       int nFlagsIn)
439
0
{
440
0
    if (!IsUpdatable() || !IngestAll())
441
0
        return OGRERR_FAILURE;
442
0
    return OGRMemLayer::AlterFieldDefn(iField, poNewFieldDefn, nFlagsIn);
443
0
}
444
445
/************************************************************************/
446
/*                         CreateGeomField()                            */
447
/************************************************************************/
448
449
OGRErr OGRGeoJSONLayer::CreateGeomField(const OGRGeomFieldDefn *poGeomField,
450
                                        int bApproxOK)
451
0
{
452
0
    if (!IsUpdatable() || !IngestAll())
453
0
        return OGRERR_FAILURE;
454
0
    return OGRMemLayer::CreateGeomField(poGeomField, bApproxOK);
455
0
}
456
457
OGRErr OGRGeoJSONLayer::IGetExtent(int iGeomField, OGREnvelope *psExtent,
458
                                   bool bForce)
459
0
{
460
0
    if (iGeomField != 0)
461
0
    {
462
0
        return OGRERR_FAILURE;
463
0
    }
464
465
0
    if (poReader_ && poReader_->ExtentRead() &&
466
0
        TestCapability(OLCFastGetExtent))
467
0
    {
468
0
        *psExtent = poReader_->GetExtent3D();
469
0
        return OGRERR_NONE;
470
0
    }
471
0
    else
472
0
    {
473
0
        return OGRMemLayer::IGetExtent(iGeomField, psExtent, bForce);
474
0
    }
475
0
}
476
477
OGRErr OGRGeoJSONLayer::IGetExtent3D(int iGeomField, OGREnvelope3D *psExtent3D,
478
                                     bool bForce)
479
0
{
480
481
0
    if (iGeomField != 0)
482
0
    {
483
0
        return OGRERR_FAILURE;
484
0
    }
485
486
0
    if (poReader_ && poReader_->ExtentRead() &&
487
0
        TestCapability(OLCFastGetExtent3D))
488
0
    {
489
0
        *psExtent3D = poReader_->GetExtent3D();
490
0
        return OGRERR_NONE;
491
0
    }
492
0
    else
493
0
    {
494
0
        return OGRMemLayer::IGetExtent3D(iGeomField, psExtent3D, bForce);
495
0
    }
496
0
}
497
498
/************************************************************************/
499
/*                           TestCapability()                           */
500
/************************************************************************/
501
502
int OGRGeoJSONLayer::TestCapability(const char *pszCap)
503
504
0
{
505
0
    if (EQUAL(pszCap, OLCCurveGeometries))
506
0
        return FALSE;
507
0
    else if (EQUAL(pszCap, OLCMeasuredGeometries))
508
0
        return m_bSupportsMGeometries;
509
0
    else if (EQUAL(pszCap, OLCZGeometries))
510
0
        return m_bSupportsZGeometries;
511
0
    else if (EQUAL(pszCap, OLCStringsAsUTF8))
512
0
        return TRUE;
513
0
    else if (EQUAL(pszCap, OLCFastGetExtent) ||
514
0
             EQUAL(pszCap, OLCFastGetExtent3D))
515
0
        return m_poFilterGeom == nullptr && m_poAttrQuery == nullptr;
516
0
    return OGRMemLayer::TestCapability(pszCap);
517
0
}
518
519
/************************************************************************/
520
/*                           SyncToDisk()                               */
521
/************************************************************************/
522
523
OGRErr OGRGeoJSONLayer::SyncToDisk()
524
0
{
525
0
    TerminateAppendSession();
526
527
0
    poDS_->FlushCache(false);
528
0
    return OGRERR_NONE;
529
0
}
530
531
/************************************************************************/
532
/*                           AddFeature                                 */
533
/************************************************************************/
534
535
void OGRGeoJSONLayer::AddFeature(OGRFeature *poFeature)
536
0
{
537
0
    GIntBig nFID = poFeature->GetFID();
538
539
    // Detect potential FID duplicates and make sure they are eventually
540
    // unique.
541
0
    if (-1 == nFID)
542
0
    {
543
0
        nFID = GetFeatureCount(FALSE);
544
0
        OGRFeature *poTryFeature = nullptr;
545
0
        while ((poTryFeature = GetFeature(nFID)) != nullptr)
546
0
        {
547
0
            nFID++;
548
0
            delete poTryFeature;
549
0
        }
550
0
    }
551
0
    else
552
0
    {
553
0
        OGRFeature *poTryFeature = nullptr;
554
0
        if ((poTryFeature = GetFeature(nFID)) != nullptr)
555
0
        {
556
0
            if (!bOriginalIdModified_)
557
0
            {
558
0
                CPLError(
559
0
                    CE_Warning, CPLE_AppDefined,
560
0
                    "Several features with id = " CPL_FRMT_GIB " have been "
561
0
                    "found. Altering it to be unique. This warning will not "
562
0
                    "be emitted anymore for this layer",
563
0
                    nFID);
564
0
                bOriginalIdModified_ = true;
565
0
            }
566
0
            delete poTryFeature;
567
0
            nFID = GetFeatureCount(FALSE);
568
0
            while ((poTryFeature = GetFeature(nFID)) != nullptr)
569
0
            {
570
0
                nFID++;
571
0
                delete poTryFeature;
572
0
            }
573
0
        }
574
0
    }
575
0
    poFeature->SetFID(nFID);
576
577
0
    if (!CPL_INT64_FITS_ON_INT32(nFID))
578
0
        SetMetadataItem(OLMD_FID64, "YES");
579
580
0
    const bool bIsUpdatable = IsUpdatable();
581
0
    SetUpdatable(true);  // Temporary toggle on updatable flag.
582
0
    CPL_IGNORE_RET_VAL(OGRMemLayer::SetFeature(poFeature));
583
0
    SetUpdatable(bIsUpdatable);
584
0
    SetUpdated(false);
585
0
}
586
587
/************************************************************************/
588
/*                           DetectGeometryType                         */
589
/************************************************************************/
590
591
void OGRGeoJSONLayer::DetectGeometryType()
592
0
{
593
0
    if (GetLayerDefn()->GetGeomType() != wkbUnknown)
594
0
        return;
595
596
0
    ResetReading();
597
0
    bool bFirstGeometry = true;
598
0
    OGRwkbGeometryType eLayerGeomType = wkbUnknown;
599
0
    for (const auto &poFeature : *this)
600
0
    {
601
0
        const OGRGeometry *poGeometry = poFeature->GetGeometryRef();
602
0
        if (nullptr != poGeometry)
603
0
        {
604
0
            OGRwkbGeometryType eGeomType = poGeometry->getGeometryType();
605
0
            if (!OGRGeoJSONUpdateLayerGeomType(bFirstGeometry, eGeomType,
606
0
                                               eLayerGeomType))
607
0
            {
608
0
                break;
609
0
            }
610
0
        }
611
0
    }
612
613
0
    {
614
0
        auto poFDefn = GetLayerDefn();
615
0
        auto oTemporaryUnsealer(poFDefn->GetTemporaryUnsealer());
616
0
        poFDefn->SetGeomType(eLayerGeomType);
617
0
    }
618
619
0
    ResetReading();
620
0
}
621
622
/************************************************************************/
623
/*                             GetDataset()                             */
624
/************************************************************************/
625
626
GDALDataset *OGRGeoJSONLayer::GetDataset()
627
0
{
628
0
    return poDS_;
629
0
}