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

Generated by: LCOV version 1.14