LCOV - code coverage report
Current view: top level - frmts/mem - ogrmemlayer.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 421 479 87.9 %
Date: 2026-04-19 18:43:50 Functions: 31 33 93.9 %

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

Generated by: LCOV version 1.14