LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/mem - ogrmemlayer.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 402 452 88.9 %
Date: 2024-05-06 13:02:59 Functions: 27 28 96.4 %

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

Generated by: LCOV version 1.14