Coverage Report

Created: 2026-08-14 09:29

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gdal/frmts/mem/ogrmemlayer.cpp
Line
Count
Source
1
/******************************************************************************
2
 *
3
 * Project:  OpenGIS Simple Features Reference Implementation
4
 * Purpose:  Implements OGRMemLayer class.
5
 * Author:   Frank Warmerdam, warmerdam@pobox.com
6
 *
7
 ******************************************************************************
8
 * Copyright (c) 2003, Frank Warmerdam <warmerdam@pobox.com>
9
 * Copyright (c) 2009-2013, Even Rouault <even dot rouault at spatialys.com>
10
 *
11
 * SPDX-License-Identifier: MIT
12
 ****************************************************************************/
13
14
#include "cpl_port.h"
15
#include "memdataset.h"
16
17
#include <cstddef>
18
#include <cstring>
19
#include <algorithm>
20
#include <map>
21
#include <new>
22
#include <utility>
23
24
#include "cpl_conv.h"
25
#include "cpl_error.h"
26
#include "cpl_vsi.h"
27
#include "ogr_api.h"
28
#include "ogr_core.h"
29
#include "ogr_feature.h"
30
#include "ogr_geometry.h"
31
#include "ogr_p.h"
32
#include "ogr_spatialref.h"
33
#include "ogrsf_frmts.h"
34
35
/************************************************************************/
36
/*                     IOGRMemLayerFeatureIterator                      */
37
/************************************************************************/
38
39
class IOGRMemLayerFeatureIterator
40
{
41
  public:
42
    virtual ~IOGRMemLayerFeatureIterator();
43
44
    virtual OGRFeature *Next() = 0;
45
};
46
47
609k
IOGRMemLayerFeatureIterator::~IOGRMemLayerFeatureIterator() = default;
48
49
/************************************************************************/
50
/*                            OGRMemLayer()                             */
51
/************************************************************************/
52
53
OGRMemLayer::OGRMemLayer(const char *pszName,
54
                         const OGRSpatialReference *poSRSIn,
55
                         OGRwkbGeometryType eReqType)
56
290k
    : m_poFeatureDefn(OGRFeatureDefnRefCountedPtr::makeInstance(pszName))
57
290k
{
58
290k
    OGRMemLayer::SetDescription(m_poFeatureDefn->GetName());
59
290k
    m_poFeatureDefn->SetGeomType(eReqType);
60
61
290k
    if (eReqType != wkbNone && poSRSIn != nullptr)
62
60.5k
    {
63
60.5k
        OGRSpatialReference *poSRS = poSRSIn->Clone();
64
60.5k
        m_poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
65
60.5k
        poSRS->Release();
66
60.5k
    }
67
68
290k
    m_oMapFeaturesIter = m_oMapFeatures.begin();
69
290k
    m_poFeatureDefn->Seal(/* bSealFields = */ true);
70
290k
}
71
72
OGRMemLayer::OGRMemLayer(const OGRFeatureDefn &oFeatureDefn)
73
0
    : m_poFeatureDefn(oFeatureDefn.Clone())
74
0
{
75
0
    OGRMemLayer::SetDescription(m_poFeatureDefn->GetName());
76
77
0
    m_oMapFeaturesIter = m_oMapFeatures.begin();
78
0
    m_poFeatureDefn->Seal(/* bSealFields = */ true);
79
0
}
80
81
/************************************************************************/
82
/*                            ~OGRMemLayer()                            */
83
/************************************************************************/
84
85
OGRMemLayer::~OGRMemLayer()
86
87
290k
{
88
290k
    if (m_nFeaturesRead > 0 && m_poFeatureDefn != nullptr)
89
25.4k
    {
90
25.4k
        CPLDebug("Mem", CPL_FRMT_GIB " features read on layer '%s'.",
91
25.4k
                 m_nFeaturesRead, m_poFeatureDefn->GetName());
92
25.4k
    }
93
94
290k
    if (m_papoFeatures != nullptr)
95
210k
    {
96
7.16M
        for (GIntBig i = 0; i < m_nMaxFeatureCount; i++)
97
6.95M
        {
98
6.95M
            if (m_papoFeatures[i] != nullptr)
99
4.44M
                delete m_papoFeatures[i];
100
6.95M
        }
101
210k
        CPLFree(m_papoFeatures);
102
210k
    }
103
290k
}
104
105
/************************************************************************/
106
/*                            ResetReading()                            */
107
/************************************************************************/
108
109
void OGRMemLayer::ResetReading()
110
111
14.4k
{
112
14.4k
    m_iNextReadFID = 0;
113
14.4k
    m_oMapFeaturesIter = m_oMapFeatures.begin();
114
14.4k
}
115
116
/************************************************************************/
117
/*                           GetNextFeature()                           */
118
/************************************************************************/
119
120
OGRFeature *OGRMemLayer::GetNextFeature()
121
122
3.07M
{
123
3.07M
    if (m_iNextReadFID < 0)
124
0
        return nullptr;
125
126
5.87M
    while (true)
127
5.87M
    {
128
5.87M
        OGRFeature *poFeature = nullptr;
129
5.87M
        if (m_papoFeatures)
130
5.86M
        {
131
5.86M
            if (m_iNextReadFID >= m_nMaxFeatureCount)
132
28.3k
                return nullptr;
133
5.83M
            poFeature = m_papoFeatures[m_iNextReadFID++];
134
5.83M
            if (poFeature == nullptr)
135
923k
                continue;
136
5.83M
        }
137
10.2k
        else if (m_oMapFeaturesIter != m_oMapFeatures.end())
138
4.86k
        {
139
4.86k
            poFeature = m_oMapFeaturesIter->second.get();
140
4.86k
            ++m_oMapFeaturesIter;
141
4.86k
        }
142
5.34k
        else
143
5.34k
        {
144
5.34k
            break;
145
5.34k
        }
146
147
4.91M
        if ((m_poFilterGeom == nullptr ||
148
1.89M
             FilterGeometry(poFeature->GetGeomFieldRef(m_iGeomFieldFilter))) &&
149
3.04M
            (m_poAttrQuery == nullptr || m_poAttrQuery->Evaluate(poFeature)))
150
3.04M
        {
151
3.04M
            m_nFeaturesRead++;
152
3.04M
            return poFeature->Clone();
153
3.04M
        }
154
4.91M
    }
155
156
5.34k
    return nullptr;
157
3.07M
}
158
159
/************************************************************************/
160
/*                           SetNextByIndex()                           */
161
/************************************************************************/
162
163
OGRErr OGRMemLayer::SetNextByIndex(GIntBig nIndex)
164
165
0
{
166
0
    if (m_poFilterGeom != nullptr || m_poAttrQuery != nullptr ||
167
0
        m_papoFeatures == nullptr || m_bHasHoles)
168
0
        return OGRLayer::SetNextByIndex(nIndex);
169
170
0
    if (nIndex < 0 || nIndex >= m_nMaxFeatureCount)
171
0
    {
172
0
        m_iNextReadFID = -1;
173
0
        return OGRERR_NON_EXISTING_FEATURE;
174
0
    }
175
176
0
    m_iNextReadFID = nIndex;
177
178
0
    return OGRERR_NONE;
179
0
}
180
181
/************************************************************************/
182
/*                           GetFeatureRef()                            */
183
/************************************************************************/
184
185
OGRFeature *OGRMemLayer::GetFeatureRef(GIntBig nFeatureId)
186
187
216k
{
188
216k
    if (nFeatureId < 0)
189
6
        return nullptr;
190
191
216k
    OGRFeature *poFeature = nullptr;
192
216k
    if (m_papoFeatures != nullptr)
193
214k
    {
194
214k
        if (nFeatureId >= m_nMaxFeatureCount)
195
215
            return nullptr;
196
214k
        poFeature = m_papoFeatures[nFeatureId];
197
214k
    }
198
2.29k
    else
199
2.29k
    {
200
2.29k
        FeatureIterator oIter = m_oMapFeatures.find(nFeatureId);
201
2.29k
        if (oIter != m_oMapFeatures.end())
202
493
            poFeature = oIter->second.get();
203
2.29k
    }
204
205
216k
    return poFeature;
206
216k
}
207
208
/************************************************************************/
209
/*                             GetFeature()                             */
210
/************************************************************************/
211
212
OGRFeature *OGRMemLayer::GetFeature(GIntBig nFeatureId)
213
214
215k
{
215
215k
    const OGRFeature *poFeature = GetFeatureRef(nFeatureId);
216
215k
    return poFeature ? poFeature->Clone() : nullptr;
217
215k
}
218
219
/************************************************************************/
220
/*                            ISetFeature()                             */
221
/************************************************************************/
222
223
OGRErr OGRMemLayer::ISetFeature(OGRFeature *poFeature)
224
225
661
{
226
661
    if (!m_bUpdatable)
227
0
        return OGRERR_FAILURE;
228
229
661
    if (poFeature == nullptr)
230
0
        return OGRERR_FAILURE;
231
232
661
    GIntBig nFID = poFeature->GetFID();
233
661
    OGRErr eErr = SetFeatureInternal(
234
661
        std::unique_ptr<OGRFeature>(poFeature->Clone()), &nFID);
235
661
    poFeature->SetFID(nFID);
236
661
    return eErr;
237
661
}
238
239
/************************************************************************/
240
/*                         ISetFeatureUniqPtr()                         */
241
/************************************************************************/
242
243
OGRErr OGRMemLayer::ISetFeatureUniqPtr(std::unique_ptr<OGRFeature> poFeature)
244
245
5.66k
{
246
5.66k
    if (!m_bUpdatable)
247
0
        return OGRERR_FAILURE;
248
249
5.66k
    if (poFeature == nullptr)
250
0
        return OGRERR_FAILURE;
251
252
5.66k
    return SetFeatureInternal(std::move(poFeature));
253
5.66k
}
254
255
/************************************************************************/
256
/*                         SetFeatureInternal()                         */
257
/************************************************************************/
258
259
OGRErr OGRMemLayer::SetFeatureInternal(std::unique_ptr<OGRFeature> poFeature,
260
                                       GIntBig *pnFID)
261
4.45M
{
262
    // If we don't have a FID, find one available
263
4.45M
    GIntBig nFID = poFeature->GetFID();
264
4.45M
    if (nFID == OGRNullFID)
265
4.23M
    {
266
4.23M
        if (m_papoFeatures != nullptr)
267
4.02M
        {
268
4.02M
            while (m_iNextCreateFID < m_nMaxFeatureCount &&
269
3.97M
                   m_papoFeatures[m_iNextCreateFID] != nullptr)
270
0
            {
271
0
                m_iNextCreateFID++;
272
0
            }
273
4.02M
        }
274
209k
        else
275
209k
        {
276
209k
            FeatureIterator oIter;
277
209k
            while ((oIter = m_oMapFeatures.find(m_iNextCreateFID)) !=
278
209k
                   m_oMapFeatures.end())
279
0
                ++m_iNextCreateFID;
280
209k
        }
281
4.23M
        nFID = m_iNextCreateFID++;
282
4.23M
        poFeature->SetFID(nFID);
283
4.23M
    }
284
215k
    else if (nFID < OGRNullFID)
285
6
    {
286
6
        CPLError(CE_Failure, CPLE_NotSupported,
287
6
                 "negative FID are not supported");
288
6
        return OGRERR_FAILURE;
289
6
    }
290
215k
    else if (!m_bHasHoles)
291
1.24k
    {
292
        // If the feature does not exist, set m_bHasHoles
293
1.24k
        if (m_papoFeatures != nullptr)
294
661
        {
295
661
            if (nFID >= m_nMaxFeatureCount || m_papoFeatures[nFID] == nullptr)
296
0
            {
297
0
                m_bHasHoles = true;
298
0
            }
299
661
        }
300
583
        else
301
583
        {
302
583
            FeatureIterator oIter = m_oMapFeatures.find(nFID);
303
583
            if (oIter == m_oMapFeatures.end())
304
583
                m_bHasHoles = true;
305
583
        }
306
1.24k
    }
307
4.45M
    if (pnFID)
308
4.39M
        *pnFID = nFID;
309
310
4.45M
    if (m_papoFeatures != nullptr && nFID > 100000 &&
311
49
        nFID > m_nMaxFeatureCount + 1000)
312
49
    {
313
        // Convert to map if gap from current max size is too big.
314
49
        auto poIter =
315
49
            std::unique_ptr<IOGRMemLayerFeatureIterator>(GetIterator());
316
49
        try
317
49
        {
318
49
            OGRFeature *poFeatureIter = nullptr;
319
1.23k
            while ((poFeatureIter = poIter->Next()) != nullptr)
320
1.18k
            {
321
1.18k
                m_oMapFeatures[poFeatureIter->GetFID()] =
322
1.18k
                    std::unique_ptr<OGRFeature>(poFeatureIter);
323
1.18k
            }
324
49
            CPLFree(m_papoFeatures);
325
49
            m_papoFeatures = nullptr;
326
49
            m_nMaxFeatureCount = 0;
327
49
        }
328
49
        catch (const std::bad_alloc &)
329
49
        {
330
0
            m_oMapFeatures.clear();
331
0
            m_oMapFeaturesIter = m_oMapFeatures.end();
332
0
            CPLError(CE_Failure, CPLE_OutOfMemory, "Cannot allocate memory");
333
0
            return OGRERR_FAILURE;
334
0
        }
335
49
    }
336
337
6.96M
    for (int i = 0; i < m_poFeatureDefn->GetGeomFieldCount(); ++i)
338
2.51M
    {
339
2.51M
        OGRGeometry *poGeom = poFeature->GetGeomFieldRef(i);
340
2.51M
        if (poGeom != nullptr && poGeom->getSpatialReference() == nullptr)
341
116k
        {
342
116k
            poGeom->assignSpatialReference(
343
116k
                m_poFeatureDefn->GetGeomFieldDefn(i)->GetSpatialRef());
344
116k
        }
345
2.51M
    }
346
347
4.45M
    if (m_papoFeatures != nullptr || (m_oMapFeatures.empty() && nFID <= 100000))
348
4.44M
    {
349
4.44M
        if (nFID >= m_nMaxFeatureCount)
350
267k
        {
351
267k
            const GIntBig nNewCount = std::max(
352
267k
                m_nMaxFeatureCount + m_nMaxFeatureCount / 3 + 10, nFID + 1);
353
267k
            if (static_cast<GIntBig>(static_cast<size_t>(sizeof(OGRFeature *)) *
354
267k
                                     nNewCount) !=
355
267k
                static_cast<GIntBig>(sizeof(OGRFeature *)) * nNewCount)
356
0
            {
357
0
                CPLError(CE_Failure, CPLE_OutOfMemory,
358
0
                         "Cannot allocate array of " CPL_FRMT_GIB " elements",
359
0
                         nNewCount);
360
0
                return OGRERR_FAILURE;
361
0
            }
362
363
267k
            OGRFeature **papoNewFeatures =
364
267k
                static_cast<OGRFeature **>(VSI_REALLOC_VERBOSE(
365
267k
                    m_papoFeatures,
366
267k
                    static_cast<size_t>(sizeof(OGRFeature *) * nNewCount)));
367
267k
            if (papoNewFeatures == nullptr)
368
0
            {
369
0
                return OGRERR_FAILURE;
370
0
            }
371
267k
            m_papoFeatures = papoNewFeatures;
372
267k
            memset(m_papoFeatures + m_nMaxFeatureCount, 0,
373
267k
                   sizeof(OGRFeature *) *
374
267k
                       static_cast<size_t>(nNewCount - m_nMaxFeatureCount));
375
267k
            m_nMaxFeatureCount = nNewCount;
376
267k
        }
377
378
#ifdef DEBUG
379
        // Just to please Coverity. Cannot happen.
380
        if (m_papoFeatures == nullptr)
381
        {
382
            return OGRERR_FAILURE;
383
        }
384
#endif
385
386
4.44M
        if (m_papoFeatures[nFID] != nullptr)
387
661
        {
388
661
            delete m_papoFeatures[nFID];
389
661
            m_papoFeatures[nFID] = nullptr;
390
661
        }
391
4.44M
        else
392
4.44M
        {
393
4.44M
            ++m_nFeatureCount;
394
4.44M
        }
395
396
4.44M
        m_papoFeatures[nFID] = poFeature.release();
397
4.44M
    }
398
1.24k
    else
399
1.24k
    {
400
1.24k
        FeatureIterator oIter = m_oMapFeatures.find(nFID);
401
1.24k
        if (oIter != m_oMapFeatures.end())
402
0
        {
403
0
            oIter->second = std::move(poFeature);
404
0
        }
405
1.24k
        else
406
1.24k
        {
407
1.24k
            try
408
1.24k
            {
409
1.24k
                m_oMapFeatures[nFID] = std::move(poFeature);
410
1.24k
                m_oMapFeaturesIter = m_oMapFeatures.end();
411
1.24k
                m_nFeatureCount++;
412
1.24k
            }
413
1.24k
            catch (const std::bad_alloc &)
414
1.24k
            {
415
0
                CPLError(CE_Failure, CPLE_OutOfMemory,
416
0
                         "Cannot allocate memory");
417
0
                return OGRERR_FAILURE;
418
0
            }
419
1.24k
        }
420
1.24k
    }
421
422
4.45M
    m_bUpdated = true;
423
424
4.45M
    return OGRERR_NONE;
425
4.45M
}
426
427
/************************************************************************/
428
/*                        PrepareCreateFeature()                        */
429
/************************************************************************/
430
431
void OGRMemLayer::PrepareCreateFeature(OGRFeature *poFeature)
432
4.44M
{
433
4.44M
    if (poFeature->GetFID() != OGRNullFID &&
434
208k
        poFeature->GetFID() != m_iNextCreateFID)
435
208k
        m_bHasHoles = true;
436
437
    // If the feature has already a FID and that a feature with the same
438
    // FID is already registered in the layer, then unset our FID.
439
4.44M
    if (poFeature->GetFID() >= 0)
440
208k
    {
441
208k
        if (m_papoFeatures != nullptr)
442
208k
        {
443
208k
            if (poFeature->GetFID() < m_nMaxFeatureCount &&
444
206k
                m_papoFeatures[poFeature->GetFID()] != nullptr)
445
0
            {
446
0
                poFeature->SetFID(OGRNullFID);
447
0
            }
448
208k
        }
449
423
        else
450
423
        {
451
423
            FeatureIterator oIter = m_oMapFeatures.find(poFeature->GetFID());
452
423
            if (oIter != m_oMapFeatures.end())
453
0
                poFeature->SetFID(OGRNullFID);
454
423
        }
455
208k
    }
456
4.44M
}
457
458
/************************************************************************/
459
/*                           ICreateFeature()                           */
460
/************************************************************************/
461
462
OGRErr OGRMemLayer::ICreateFeature(OGRFeature *poFeature)
463
464
4.39M
{
465
4.39M
    if (!m_bUpdatable)
466
0
        return OGRERR_FAILURE;
467
468
4.39M
    PrepareCreateFeature(poFeature);
469
470
4.39M
    GIntBig nFID = poFeature->GetFID();
471
4.39M
    const OGRErr eErr = SetFeatureInternal(
472
4.39M
        std::unique_ptr<OGRFeature>(poFeature->Clone()), &nFID);
473
4.39M
    poFeature->SetFID(nFID);
474
4.39M
    return eErr;
475
4.39M
}
476
477
/************************************************************************/
478
/*                       ICreateFeatureUniqPtr()                        */
479
/************************************************************************/
480
481
OGRErr OGRMemLayer::ICreateFeatureUniqPtr(std::unique_ptr<OGRFeature> poFeature,
482
                                          GIntBig *pnFID)
483
51.0k
{
484
51.0k
    if (!m_bUpdatable)
485
0
        return OGRERR_FAILURE;
486
487
51.0k
    PrepareCreateFeature(poFeature.get());
488
489
51.0k
    return SetFeatureInternal(std::move(poFeature), pnFID);
490
51.0k
}
491
492
/************************************************************************/
493
/*                           UpsertFeature()                            */
494
/************************************************************************/
495
496
OGRErr OGRMemLayer::IUpsertFeature(OGRFeature *poFeature)
497
498
0
{
499
0
    if (!TestCapability(OLCUpsertFeature))
500
0
        return OGRERR_FAILURE;
501
502
0
    if (GetFeatureRef(poFeature->GetFID()))
503
0
    {
504
0
        return ISetFeature(poFeature);
505
0
    }
506
0
    else
507
0
    {
508
0
        return ICreateFeature(poFeature);
509
0
    }
510
0
}
511
512
/************************************************************************/
513
/*                           UpdateFeature()                            */
514
/************************************************************************/
515
516
OGRErr OGRMemLayer::IUpdateFeature(OGRFeature *poFeature,
517
                                   int nUpdatedFieldsCount,
518
                                   const int *panUpdatedFieldsIdx,
519
                                   int nUpdatedGeomFieldsCount,
520
                                   const int *panUpdatedGeomFieldsIdx,
521
                                   bool bUpdateStyleString)
522
523
0
{
524
0
    if (!TestCapability(OLCUpdateFeature))
525
0
        return OGRERR_FAILURE;
526
527
0
    auto poFeatureRef = GetFeatureRef(poFeature->GetFID());
528
0
    if (!poFeatureRef)
529
0
        return OGRERR_NON_EXISTING_FEATURE;
530
531
0
    for (int i = 0; i < nUpdatedFieldsCount; ++i)
532
0
    {
533
0
        poFeatureRef->SetField(
534
0
            panUpdatedFieldsIdx[i],
535
0
            poFeature->GetRawFieldRef(panUpdatedFieldsIdx[i]));
536
0
    }
537
0
    for (int i = 0; i < nUpdatedGeomFieldsCount; ++i)
538
0
    {
539
0
        poFeatureRef->SetGeomFieldDirectly(
540
0
            panUpdatedGeomFieldsIdx[i],
541
0
            poFeature->StealGeometry(panUpdatedGeomFieldsIdx[i]));
542
0
    }
543
0
    if (bUpdateStyleString)
544
0
    {
545
0
        poFeatureRef->SetStyleString(poFeature->GetStyleString());
546
0
    }
547
548
0
    m_bUpdated = true;
549
550
0
    return OGRERR_NONE;
551
0
}
552
553
/************************************************************************/
554
/*                           DeleteFeature()                            */
555
/************************************************************************/
556
557
OGRErr OGRMemLayer::DeleteFeature(GIntBig nFID)
558
559
0
{
560
0
    if (!m_bUpdatable)
561
0
        return OGRERR_FAILURE;
562
563
0
    if (nFID < 0)
564
0
    {
565
0
        return OGRERR_FAILURE;
566
0
    }
567
568
0
    if (m_papoFeatures != nullptr)
569
0
    {
570
0
        if (nFID >= m_nMaxFeatureCount || m_papoFeatures[nFID] == nullptr)
571
0
        {
572
0
            return OGRERR_FAILURE;
573
0
        }
574
0
        delete m_papoFeatures[nFID];
575
0
        m_papoFeatures[nFID] = nullptr;
576
0
    }
577
0
    else
578
0
    {
579
0
        FeatureIterator oIter = m_oMapFeatures.find(nFID);
580
0
        if (oIter == m_oMapFeatures.end())
581
0
        {
582
0
            return OGRERR_FAILURE;
583
0
        }
584
0
        m_oMapFeatures.erase(oIter);
585
0
    }
586
587
0
    m_bHasHoles = true;
588
0
    --m_nFeatureCount;
589
590
0
    m_bUpdated = true;
591
592
0
    return OGRERR_NONE;
593
0
}
594
595
/************************************************************************/
596
/*                          GetFeatureCount()                           */
597
/*                                                                      */
598
/*      If a spatial filter is in effect, we turn control over to       */
599
/*      the generic counter.  Otherwise we return the total count.      */
600
/*      Eventually we should consider implementing a more efficient     */
601
/*      way of counting features matching a spatial query.              */
602
/************************************************************************/
603
604
GIntBig OGRMemLayer::GetFeatureCount(int bForce)
605
606
70.5k
{
607
70.5k
    if (m_poFilterGeom != nullptr || m_poAttrQuery != nullptr)
608
0
        return OGRLayer::GetFeatureCount(bForce);
609
610
70.5k
    return m_nFeatureCount;
611
70.5k
}
612
613
/************************************************************************/
614
/*                           TestCapability()                           */
615
/************************************************************************/
616
617
int OGRMemLayer::TestCapability(const char *pszCap) const
618
619
452k
{
620
452k
    if (EQUAL(pszCap, OLCRandomRead))
621
0
        return TRUE;
622
623
452k
    else if (EQUAL(pszCap, OLCSequentialWrite) || EQUAL(pszCap, OLCRandomWrite))
624
0
        return m_bUpdatable;
625
626
452k
    else if (EQUAL(pszCap, OLCFastFeatureCount))
627
0
        return m_poFilterGeom == nullptr && m_poAttrQuery == nullptr;
628
629
452k
    else if (EQUAL(pszCap, OLCFastSpatialFilter))
630
0
        return FALSE;
631
632
452k
    else if (EQUAL(pszCap, OLCDeleteFeature) ||
633
452k
             EQUAL(pszCap, OLCUpsertFeature) || EQUAL(pszCap, OLCUpdateFeature))
634
0
        return m_bUpdatable;
635
636
452k
    else if (EQUAL(pszCap, OLCCreateField) ||
637
452k
             EQUAL(pszCap, OLCCreateGeomField) ||
638
452k
             EQUAL(pszCap, OLCDeleteField) || EQUAL(pszCap, OLCReorderFields) ||
639
452k
             EQUAL(pszCap, OLCAlterFieldDefn) ||
640
452k
             EQUAL(pszCap, OLCAlterGeomFieldDefn))
641
0
        return m_bUpdatable;
642
643
452k
    else if (EQUAL(pszCap, OLCFastSetNextByIndex))
644
0
        return m_poFilterGeom == nullptr && m_poAttrQuery == nullptr &&
645
0
               ((m_papoFeatures != nullptr && !m_bHasHoles) ||
646
0
                m_oMapFeatures.empty());
647
648
452k
    else if (EQUAL(pszCap, OLCStringsAsUTF8))
649
0
        return m_bAdvertizeUTF8;
650
651
452k
    else if (EQUAL(pszCap, OLCCurveGeometries))
652
219k
        return TRUE;
653
654
232k
    else if (EQUAL(pszCap, OLCMeasuredGeometries))
655
219k
        return TRUE;
656
657
12.4k
    else if (EQUAL(pszCap, OLCZGeometries))
658
12.3k
        return TRUE;
659
660
54
    return FALSE;
661
452k
}
662
663
/************************************************************************/
664
/*                            CreateField()                             */
665
/************************************************************************/
666
667
OGRErr OGRMemLayer::CreateField(const OGRFieldDefn *poField,
668
                                int /* bApproxOK */)
669
1.57M
{
670
1.57M
    if (!m_bUpdatable)
671
0
        return OGRERR_FAILURE;
672
673
    // Simple case, no features exist yet.
674
1.57M
    if (m_nFeatureCount == 0)
675
977k
    {
676
977k
        whileUnsealing(m_poFeatureDefn)->AddFieldDefn(poField);
677
977k
        return OGRERR_NONE;
678
977k
    }
679
680
    // Add field definition and setup remap definition.
681
595k
    {
682
595k
        whileUnsealing(m_poFeatureDefn)->AddFieldDefn(poField);
683
595k
    }
684
685
    // Remap all the internal features.  Hopefully there aren't any
686
    // external features referring to our OGRFeatureDefn!
687
595k
    auto poIter = std::unique_ptr<IOGRMemLayerFeatureIterator>(GetIterator());
688
595k
    OGRFeature *poFeature = nullptr;
689
6.94M
    while ((poFeature = poIter->Next()) != nullptr)
690
6.35M
    {
691
6.35M
        poFeature->AppendField();
692
6.35M
    }
693
694
595k
    m_bUpdated = true;
695
696
595k
    return OGRERR_NONE;
697
1.57M
}
698
699
/************************************************************************/
700
/*                            DeleteField()                             */
701
/************************************************************************/
702
703
OGRErr OGRMemLayer::DeleteField(int iField)
704
0
{
705
0
    if (!m_bUpdatable)
706
0
        return OGRERR_FAILURE;
707
708
0
    if (iField < 0 || iField >= m_poFeatureDefn->GetFieldCount())
709
0
    {
710
0
        CPLError(CE_Failure, CPLE_NotSupported, "Invalid field index");
711
0
        return OGRERR_FAILURE;
712
0
    }
713
714
    // Update all the internal features.  Hopefully there aren't any
715
    // external features referring to our OGRFeatureDefn!
716
0
    auto poIter = std::unique_ptr<IOGRMemLayerFeatureIterator>(GetIterator());
717
0
    while (OGRFeature *poFeature = poIter->Next())
718
0
    {
719
0
        OGRField *poFieldRaw = poFeature->GetRawFieldRef(iField);
720
0
        if (poFeature->IsFieldSetAndNotNull(iField) &&
721
0
            !poFeature->IsFieldNull(iField))
722
0
        {
723
            // Little trick to unallocate the field.
724
0
            OGRField sField;
725
0
            OGR_RawField_SetUnset(&sField);
726
0
            poFeature->SetField(iField, &sField);
727
0
        }
728
729
0
        if (iField < m_poFeatureDefn->GetFieldCount() - 1)
730
0
        {
731
0
            memmove(poFieldRaw, poFieldRaw + 1,
732
0
                    sizeof(OGRField) *
733
0
                        (m_poFeatureDefn->GetFieldCount() - 1 - iField));
734
0
        }
735
0
    }
736
737
0
    m_bUpdated = true;
738
739
0
    return whileUnsealing(m_poFeatureDefn)->DeleteFieldDefn(iField);
740
0
}
741
742
/************************************************************************/
743
/*                           ReorderFields()                            */
744
/************************************************************************/
745
746
OGRErr OGRMemLayer::ReorderFields(int *panMap)
747
0
{
748
0
    if (!m_bUpdatable)
749
0
        return OGRERR_FAILURE;
750
751
0
    if (m_poFeatureDefn->GetFieldCount() == 0)
752
0
        return OGRERR_NONE;
753
754
0
    const OGRErr eErr =
755
0
        OGRCheckPermutation(panMap, m_poFeatureDefn->GetFieldCount());
756
0
    if (eErr != OGRERR_NONE)
757
0
        return eErr;
758
759
    // Remap all the internal features.  Hopefully there aren't any
760
    // external features referring to our OGRFeatureDefn!
761
0
    auto poIter = std::unique_ptr<IOGRMemLayerFeatureIterator>(GetIterator());
762
0
    while (OGRFeature *poFeature = poIter->Next())
763
0
    {
764
0
        poFeature->RemapFields(nullptr, panMap);
765
0
    }
766
767
0
    m_bUpdated = true;
768
769
0
    return whileUnsealing(m_poFeatureDefn)->ReorderFieldDefns(panMap);
770
0
}
771
772
/************************************************************************/
773
/*                           AlterFieldDefn()                           */
774
/************************************************************************/
775
776
OGRErr OGRMemLayer::AlterFieldDefn(int iField, OGRFieldDefn *poNewFieldDefn,
777
                                   int nFlagsIn)
778
13.8k
{
779
13.8k
    if (!m_bUpdatable)
780
0
        return OGRERR_FAILURE;
781
782
13.8k
    if (iField < 0 || iField >= m_poFeatureDefn->GetFieldCount())
783
0
    {
784
0
        CPLError(CE_Failure, CPLE_NotSupported, "Invalid field index");
785
0
        return OGRERR_FAILURE;
786
0
    }
787
788
13.8k
    OGRFieldDefn *poFieldDefn = m_poFeatureDefn->GetFieldDefn(iField);
789
13.8k
    auto oTemporaryUnsealer(poFieldDefn->GetTemporaryUnsealer());
790
791
13.8k
    if ((nFlagsIn & ALTER_TYPE_FLAG) &&
792
13.8k
        (poFieldDefn->GetType() != poNewFieldDefn->GetType() ||
793
0
         poFieldDefn->GetSubType() != poNewFieldDefn->GetSubType()))
794
13.8k
    {
795
13.8k
        if ((poNewFieldDefn->GetType() == OFTDate ||
796
13.8k
             poNewFieldDefn->GetType() == OFTTime ||
797
13.8k
             poNewFieldDefn->GetType() == OFTDateTime) &&
798
209
            (poFieldDefn->GetType() == OFTDate ||
799
126
             poFieldDefn->GetType() == OFTTime ||
800
0
             poFieldDefn->GetType() == OFTDateTime))
801
209
        {
802
            // Do nothing on features.
803
209
        }
804
13.6k
        else if (poNewFieldDefn->GetType() == OFTInteger64 &&
805
818
                 poFieldDefn->GetType() == OFTInteger)
806
818
        {
807
            // Update all the internal features.  Hopefully there aren't any
808
            // external features referring to our OGRFeatureDefn!
809
818
            IOGRMemLayerFeatureIterator *poIter = GetIterator();
810
818
            OGRFeature *poFeature = nullptr;
811
40.2k
            while ((poFeature = poIter->Next()) != nullptr)
812
39.4k
            {
813
39.4k
                OGRField *poFieldRaw = poFeature->GetRawFieldRef(iField);
814
39.4k
                if (poFeature->IsFieldSetAndNotNull(iField) &&
815
1.05k
                    !poFeature->IsFieldNull(iField))
816
1.05k
                {
817
1.05k
                    const GIntBig nVal = poFieldRaw->Integer;
818
1.05k
                    poFieldRaw->Integer64 = nVal;
819
1.05k
                }
820
39.4k
            }
821
818
            delete poIter;
822
818
        }
823
12.8k
        else if (poNewFieldDefn->GetType() == OFTReal &&
824
2.90k
                 poFieldDefn->GetType() == OFTInteger)
825
2.47k
        {
826
            // Update all the internal features.  Hopefully there aren't any
827
            // external features referring to our OGRFeatureDefn!
828
2.47k
            IOGRMemLayerFeatureIterator *poIter = GetIterator();
829
2.47k
            OGRFeature *poFeature = nullptr;
830
82.3k
            while ((poFeature = poIter->Next()) != nullptr)
831
79.8k
            {
832
79.8k
                OGRField *poFieldRaw = poFeature->GetRawFieldRef(iField);
833
79.8k
                if (poFeature->IsFieldSetAndNotNull(iField) &&
834
3.21k
                    !poFeature->IsFieldNull(iField))
835
3.21k
                {
836
3.21k
                    const double dfVal = poFieldRaw->Integer;
837
3.21k
                    poFieldRaw->Real = dfVal;
838
3.21k
                }
839
79.8k
            }
840
2.47k
            delete poIter;
841
2.47k
        }
842
10.3k
        else if (poNewFieldDefn->GetType() == OFTReal &&
843
427
                 poFieldDefn->GetType() == OFTInteger64)
844
427
        {
845
            // Update all the internal features.  Hopefully there aren't any
846
            // external features referring to our OGRFeatureDefn!
847
427
            IOGRMemLayerFeatureIterator *poIter = GetIterator();
848
427
            OGRFeature *poFeature = nullptr;
849
14.5k
            while ((poFeature = poIter->Next()) != nullptr)
850
14.1k
            {
851
14.1k
                OGRField *poFieldRaw = poFeature->GetRawFieldRef(iField);
852
14.1k
                if (poFeature->IsFieldSetAndNotNull(iField) &&
853
975
                    !poFeature->IsFieldNull(iField))
854
975
                {
855
975
                    const double dfVal =
856
975
                        static_cast<double>(poFieldRaw->Integer64);
857
975
                    poFieldRaw->Real = dfVal;
858
975
                }
859
14.1k
            }
860
427
            delete poIter;
861
427
        }
862
9.93k
        else
863
9.93k
        {
864
9.93k
            if (poNewFieldDefn->GetType() != OFTString)
865
0
            {
866
0
                CPLError(CE_Failure, CPLE_NotSupported,
867
0
                         "Can only convert from OFTInteger to OFTReal, "
868
0
                         "or from anything to OFTString");
869
0
                return OGRERR_FAILURE;
870
0
            }
871
872
            // Update all the internal features.  Hopefully there aren't any
873
            // external features referring to our OGRFeatureDefn!
874
9.93k
            IOGRMemLayerFeatureIterator *poIter = GetIterator();
875
9.93k
            OGRFeature *poFeature = nullptr;
876
480k
            while ((poFeature = poIter->Next()) != nullptr)
877
470k
            {
878
470k
                OGRField *poFieldRaw = poFeature->GetRawFieldRef(iField);
879
470k
                if (poFeature->IsFieldSetAndNotNull(iField) &&
880
13.8k
                    !poFeature->IsFieldNull(iField))
881
13.8k
                {
882
13.8k
                    char *pszVal =
883
13.8k
                        CPLStrdup(poFeature->GetFieldAsString(iField));
884
885
                    // Little trick to unallocate the field.
886
13.8k
                    OGRField sField;
887
13.8k
                    OGR_RawField_SetUnset(&sField);
888
13.8k
                    poFeature->SetField(iField, &sField);
889
890
13.8k
                    poFieldRaw->String = pszVal;
891
13.8k
                }
892
470k
            }
893
9.93k
            delete poIter;
894
9.93k
        }
895
896
13.8k
        poFieldDefn->SetSubType(OFSTNone);
897
13.8k
        poFieldDefn->SetType(poNewFieldDefn->GetType());
898
13.8k
        poFieldDefn->SetSubType(poNewFieldDefn->GetSubType());
899
13.8k
    }
900
901
13.8k
    if (nFlagsIn & ALTER_NAME_FLAG)
902
0
        poFieldDefn->SetName(poNewFieldDefn->GetNameRef());
903
13.8k
    if (nFlagsIn & ALTER_WIDTH_PRECISION_FLAG)
904
0
    {
905
0
        poFieldDefn->SetWidth(poNewFieldDefn->GetWidth());
906
0
        poFieldDefn->SetPrecision(poNewFieldDefn->GetPrecision());
907
0
    }
908
909
13.8k
    m_bUpdated = true;
910
911
13.8k
    return OGRERR_NONE;
912
13.8k
}
913
914
/************************************************************************/
915
/*                         AlterGeomFieldDefn()                         */
916
/************************************************************************/
917
918
OGRErr OGRMemLayer::AlterGeomFieldDefn(
919
    int iGeomField, const OGRGeomFieldDefn *poNewGeomFieldDefn, int nFlagsIn)
920
0
{
921
0
    if (!m_bUpdatable)
922
0
        return OGRERR_FAILURE;
923
924
0
    if (iGeomField < 0 || iGeomField >= m_poFeatureDefn->GetGeomFieldCount())
925
0
    {
926
0
        CPLError(CE_Failure, CPLE_NotSupported, "Invalid field index");
927
0
        return OGRERR_FAILURE;
928
0
    }
929
930
0
    auto poFieldDefn = m_poFeatureDefn->GetGeomFieldDefn(iGeomField);
931
0
    auto oTemporaryUnsealer(poFieldDefn->GetTemporaryUnsealer());
932
933
0
    if (nFlagsIn & ALTER_GEOM_FIELD_DEFN_NAME_FLAG)
934
0
        poFieldDefn->SetName(poNewGeomFieldDefn->GetNameRef());
935
0
    if (nFlagsIn & ALTER_GEOM_FIELD_DEFN_TYPE_FLAG)
936
0
    {
937
0
        if (poNewGeomFieldDefn->GetType() == wkbNone)
938
0
            return OGRERR_FAILURE;
939
0
        poFieldDefn->SetType(poNewGeomFieldDefn->GetType());
940
0
    }
941
0
    if (nFlagsIn & ALTER_GEOM_FIELD_DEFN_NULLABLE_FLAG)
942
0
        poFieldDefn->SetNullable(poNewGeomFieldDefn->IsNullable());
943
944
0
    if (nFlagsIn & ALTER_GEOM_FIELD_DEFN_SRS_FLAG)
945
0
    {
946
0
        OGRSpatialReference *poSRSNew = nullptr;
947
0
        const auto poSRSNewRef = poNewGeomFieldDefn->GetSpatialRef();
948
0
        if (poSRSNewRef)
949
0
        {
950
0
            poSRSNew = poSRSNewRef->Clone();
951
0
            if ((nFlagsIn & ALTER_GEOM_FIELD_DEFN_SRS_COORD_EPOCH_FLAG) == 0)
952
0
            {
953
0
                const auto poSRSOld = poFieldDefn->GetSpatialRef();
954
0
                if (poSRSOld)
955
0
                    poSRSNew->SetCoordinateEpoch(
956
0
                        poSRSOld->GetCoordinateEpoch());
957
0
                else
958
0
                    poSRSNew->SetCoordinateEpoch(0);
959
0
            }
960
0
        }
961
0
        poFieldDefn->SetSpatialRef(poSRSNew);
962
0
        if (poSRSNew)
963
0
            poSRSNew->Release();
964
0
    }
965
0
    else if (nFlagsIn & ALTER_GEOM_FIELD_DEFN_SRS_COORD_EPOCH_FLAG)
966
0
    {
967
0
        const auto poSRSOld = poFieldDefn->GetSpatialRef();
968
0
        const auto poSRSNewRef = poNewGeomFieldDefn->GetSpatialRef();
969
0
        if (poSRSOld && poSRSNewRef)
970
0
        {
971
0
            auto poSRSNew = poSRSOld->Clone();
972
0
            poSRSNew->SetCoordinateEpoch(poSRSNewRef->GetCoordinateEpoch());
973
0
            poFieldDefn->SetSpatialRef(poSRSNew);
974
0
            poSRSNew->Release();
975
0
        }
976
0
    }
977
978
0
    m_bUpdated = true;
979
980
0
    return OGRERR_NONE;
981
0
}
982
983
/************************************************************************/
984
/*                          CreateGeomField()                           */
985
/************************************************************************/
986
987
OGRErr OGRMemLayer::CreateGeomField(const OGRGeomFieldDefn *poGeomField,
988
                                    int /* bApproxOK */)
989
3.64k
{
990
3.64k
    if (!m_bUpdatable)
991
0
        return OGRERR_FAILURE;
992
993
    // Simple case, no features exist yet.
994
3.64k
    if (m_nFeatureCount == 0)
995
3.64k
    {
996
3.64k
        whileUnsealing(m_poFeatureDefn)->AddGeomFieldDefn(poGeomField);
997
3.64k
        return OGRERR_NONE;
998
3.64k
    }
999
1000
    // Add field definition and setup remap definition.
1001
0
    whileUnsealing(m_poFeatureDefn)->AddGeomFieldDefn(poGeomField);
1002
1003
0
    const int nGeomFieldCount = m_poFeatureDefn->GetGeomFieldCount();
1004
0
    std::vector<int> anRemap(nGeomFieldCount);
1005
0
    for (int i = 0; i < nGeomFieldCount; ++i)
1006
0
    {
1007
0
        if (i < nGeomFieldCount - 1)
1008
0
            anRemap[i] = i;
1009
0
        else
1010
0
            anRemap[i] = -1;
1011
0
    }
1012
1013
    // Remap all the internal features.  Hopefully there aren't any
1014
    // external features referring to our OGRFeatureDefn!
1015
0
    auto poIter = std::unique_ptr<IOGRMemLayerFeatureIterator>(GetIterator());
1016
0
    while (OGRFeature *poFeature = poIter->Next())
1017
0
    {
1018
0
        poFeature->RemapGeomFields(nullptr, anRemap.data());
1019
0
    }
1020
1021
0
    m_bUpdated = true;
1022
1023
0
    return OGRERR_NONE;
1024
3.64k
}
1025
1026
/************************************************************************/
1027
/*                       OGRMemLayerIteratorArray                       */
1028
/************************************************************************/
1029
1030
class OGRMemLayerIteratorArray final : public IOGRMemLayerFeatureIterator
1031
{
1032
    GIntBig m_iCurIdx = 0;
1033
    const GIntBig m_nMaxFeatureCount;
1034
    OGRFeature **const m_papoFeatures;
1035
1036
    CPL_DISALLOW_COPY_ASSIGN(OGRMemLayerIteratorArray)
1037
1038
  public:
1039
    OGRMemLayerIteratorArray(GIntBig nMaxFeatureCount,
1040
                             OGRFeature **papoFeatures)
1041
609k
        : m_nMaxFeatureCount(nMaxFeatureCount), m_papoFeatures(papoFeatures)
1042
609k
    {
1043
609k
    }
1044
1045
    OGRFeature *Next() override;
1046
};
1047
1048
OGRFeature *OGRMemLayerIteratorArray::Next()
1049
7.56M
{
1050
13.5M
    while (m_iCurIdx < m_nMaxFeatureCount)
1051
12.9M
    {
1052
12.9M
        OGRFeature *poFeature = m_papoFeatures[m_iCurIdx];
1053
12.9M
        ++m_iCurIdx;
1054
12.9M
        if (poFeature != nullptr)
1055
6.95M
            return poFeature;
1056
12.9M
    }
1057
609k
    return nullptr;
1058
7.56M
}
1059
1060
/************************************************************************/
1061
/*                        OGRMemLayerIteratorMap                        */
1062
/************************************************************************/
1063
1064
class OGRMemLayerIteratorMap final : public IOGRMemLayerFeatureIterator
1065
{
1066
    typedef std::map<GIntBig, std::unique_ptr<OGRFeature>> FeatureMap;
1067
    typedef FeatureMap::iterator FeatureIterator;
1068
1069
    const FeatureMap &m_oMapFeatures;
1070
    FeatureIterator m_oIter;
1071
1072
  public:
1073
    explicit OGRMemLayerIteratorMap(FeatureMap &oMapFeatures)
1074
0
        : m_oMapFeatures(oMapFeatures), m_oIter(oMapFeatures.begin())
1075
0
    {
1076
0
    }
1077
1078
    OGRFeature *Next() override;
1079
1080
  private:
1081
    CPL_DISALLOW_COPY_ASSIGN(OGRMemLayerIteratorMap)
1082
};
1083
1084
OGRFeature *OGRMemLayerIteratorMap::Next()
1085
0
{
1086
0
    if (m_oIter != m_oMapFeatures.end())
1087
0
    {
1088
0
        OGRFeature *poFeature = m_oIter->second.get();
1089
0
        ++m_oIter;
1090
0
        return poFeature;
1091
0
    }
1092
0
    return nullptr;
1093
0
}
1094
1095
/************************************************************************/
1096
/*                            GetIterator()                             */
1097
/************************************************************************/
1098
1099
IOGRMemLayerFeatureIterator *OGRMemLayer::GetIterator()
1100
609k
{
1101
609k
    if (m_oMapFeatures.empty())
1102
609k
        return new OGRMemLayerIteratorArray(m_nMaxFeatureCount, m_papoFeatures);
1103
1104
0
    return new OGRMemLayerIteratorMap(m_oMapFeatures);
1105
609k
}