EVOLUTION-MANAGER
Edit File: ogrmemlayer.cpp
/****************************************************************************** * * Project: OpenGIS Simple Features Reference Implementation * Purpose: Implements OGRMemLayer class. * Author: Frank Warmerdam, warmerdam@pobox.com * ****************************************************************************** * Copyright (c) 2003, Frank Warmerdam <warmerdam@pobox.com> * Copyright (c) 2009-2013, Even Rouault <even dot rouault at mines-paris dot org> * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #include "cpl_conv.h" #include "ogr_mem.h" #include "ogr_p.h" #include <algorithm> CPL_CVSID("$Id: ogrmemlayer.cpp 37988 2017-04-14 07:47:29Z rouault $"); /************************************************************************/ /* IOGRMemLayerFeatureIterator */ /************************************************************************/ class IOGRMemLayerFeatureIterator { public: virtual ~IOGRMemLayerFeatureIterator() {} virtual OGRFeature* Next() = 0; }; /************************************************************************/ /* OGRMemLayer() */ /************************************************************************/ OGRMemLayer::OGRMemLayer( const char * pszName, OGRSpatialReference *poSRSIn, OGRwkbGeometryType eReqType ) : m_poFeatureDefn(new OGRFeatureDefn( pszName )), m_nFeatureCount(0), m_iNextReadFID(0), m_nMaxFeatureCount(0), m_papoFeatures(NULL), m_bHasHoles(false), m_iNextCreateFID(0), m_bUpdatable(true), m_bAdvertizeUTF8(false), m_bUpdated(false) { m_poFeatureDefn->Reference(); SetDescription( m_poFeatureDefn->GetName() ); m_poFeatureDefn->SetGeomType( eReqType ); if( eReqType != wkbNone && poSRSIn != NULL ) { OGRSpatialReference* poSRS = poSRSIn->Clone(); m_poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS); poSRS->Release(); } m_oMapFeaturesIter = m_oMapFeatures.begin(); } /************************************************************************/ /* ~OGRMemLayer() */ /************************************************************************/ OGRMemLayer::~OGRMemLayer() { if( m_nFeaturesRead > 0 && m_poFeatureDefn != NULL ) { CPLDebug( "Mem", CPL_FRMT_GIB " features read on layer '%s'.", m_nFeaturesRead, m_poFeatureDefn->GetName() ); } if( m_papoFeatures != NULL ) { for( GIntBig i = 0; i < m_nMaxFeatureCount; i++ ) { if( m_papoFeatures[i] != NULL ) delete m_papoFeatures[i]; } CPLFree( m_papoFeatures ); } else { for( m_oMapFeaturesIter = m_oMapFeatures.begin(); m_oMapFeaturesIter != m_oMapFeatures.end(); ++m_oMapFeaturesIter ) { delete m_oMapFeaturesIter->second; } } if( m_poFeatureDefn ) m_poFeatureDefn->Release(); } /************************************************************************/ /* ResetReading() */ /************************************************************************/ void OGRMemLayer::ResetReading() { m_iNextReadFID = 0; m_oMapFeaturesIter = m_oMapFeatures.begin(); } /************************************************************************/ /* GetNextFeature() */ /************************************************************************/ OGRFeature *OGRMemLayer::GetNextFeature() { while( true ) { OGRFeature *poFeature = NULL; if( m_papoFeatures ) { if( m_iNextReadFID >= m_nMaxFeatureCount ) return NULL; poFeature = m_papoFeatures[m_iNextReadFID++]; if( poFeature == NULL ) continue; } else if( m_oMapFeaturesIter != m_oMapFeatures.end() ) { poFeature = m_oMapFeaturesIter->second; ++ m_oMapFeaturesIter; } else break; if( (m_poFilterGeom == NULL || FilterGeometry( poFeature->GetGeomFieldRef(m_iGeomFieldFilter) ) ) && (m_poAttrQuery == NULL || m_poAttrQuery->Evaluate( poFeature ) ) ) { m_nFeaturesRead++; return poFeature->Clone(); } } return NULL; } /************************************************************************/ /* SetNextByIndex() */ /************************************************************************/ OGRErr OGRMemLayer::SetNextByIndex( GIntBig nIndex ) { if( m_poFilterGeom != NULL || m_poAttrQuery != NULL || m_papoFeatures == NULL || m_bHasHoles ) return OGRLayer::SetNextByIndex( nIndex ); if( nIndex < 0 || nIndex >= m_nMaxFeatureCount ) return OGRERR_FAILURE; m_iNextReadFID = nIndex; return OGRERR_NONE; } /************************************************************************/ /* GetFeature() */ /************************************************************************/ OGRFeature *OGRMemLayer::GetFeature( GIntBig nFeatureId ) { if( nFeatureId < 0 ) return NULL; OGRFeature* poFeature = NULL; if( m_papoFeatures != NULL ) { if( nFeatureId >= m_nMaxFeatureCount ) return NULL; poFeature = m_papoFeatures[nFeatureId]; } else { FeatureIterator oIter = m_oMapFeatures.find(nFeatureId); if( oIter != m_oMapFeatures.end() ) poFeature = oIter->second; } if( poFeature == NULL ) return NULL; return poFeature->Clone(); } /************************************************************************/ /* ISetFeature() */ /************************************************************************/ OGRErr OGRMemLayer::ISetFeature( OGRFeature *poFeature ) { if( !m_bUpdatable ) return OGRERR_FAILURE; if( poFeature == NULL ) return OGRERR_FAILURE; // If we don't have a FID, find one available if( poFeature->GetFID() == OGRNullFID ) { if( m_papoFeatures != NULL ) { while( m_iNextCreateFID < m_nMaxFeatureCount && m_papoFeatures[m_iNextCreateFID] != NULL ) { m_iNextCreateFID++; } } else { FeatureIterator oIter; while( (oIter = m_oMapFeatures.find(m_iNextCreateFID)) != m_oMapFeatures.end() ) ++m_iNextCreateFID; } poFeature->SetFID( m_iNextCreateFID++ ); } else if( poFeature->GetFID() < OGRNullFID ) { CPLError( CE_Failure, CPLE_NotSupported, "negative FID are not supported" ); return OGRERR_FAILURE; } OGRFeature* poFeatureCloned = poFeature->Clone(); if( poFeatureCloned == NULL ) return OGRERR_FAILURE; const GIntBig nFID = poFeature->GetFID(); if( m_papoFeatures != NULL && nFID > 100000 && nFID > m_nMaxFeatureCount + 1000 ) { // Convert to map if gap from current max size is too big. IOGRMemLayerFeatureIterator* poIter = GetIterator(); try { OGRFeature* poFeatureIter = NULL; while( (poFeatureIter = poIter->Next()) != NULL ) { m_oMapFeatures[poFeatureIter->GetFID()] = poFeatureIter; } delete poIter; CPLFree(m_papoFeatures); m_papoFeatures = NULL; m_nMaxFeatureCount = 0; } catch( const std::bad_alloc& ) { m_oMapFeatures.clear(); CPLError(CE_Failure, CPLE_OutOfMemory, "Cannot allocate memory"); delete poFeatureCloned; delete poIter; return OGRERR_FAILURE; } } if( m_papoFeatures != NULL || (m_oMapFeatures.empty() && nFID <= 100000) ) { if( nFID >= m_nMaxFeatureCount ) { const GIntBig nNewCount = std::max(m_nMaxFeatureCount + m_nMaxFeatureCount/3+10, nFID + 1); if( static_cast<GIntBig>(static_cast<size_t>(sizeof(OGRFeature *)) * nNewCount) != static_cast<GIntBig>(sizeof(OGRFeature *)) * nNewCount ) { CPLError( CE_Failure, CPLE_OutOfMemory, "Cannot allocate array of " CPL_FRMT_GIB " elements", nNewCount ); delete poFeatureCloned; return OGRERR_FAILURE; } OGRFeature** papoNewFeatures = static_cast<OGRFeature **>( VSI_REALLOC_VERBOSE( m_papoFeatures, static_cast<size_t>(sizeof(OGRFeature *) * nNewCount) ) ); if( papoNewFeatures == NULL ) { delete poFeatureCloned; return OGRERR_FAILURE; } m_papoFeatures = papoNewFeatures; memset( m_papoFeatures + m_nMaxFeatureCount, 0, sizeof(OGRFeature *) * static_cast<size_t>(nNewCount - m_nMaxFeatureCount) ); m_nMaxFeatureCount = nNewCount; } #ifdef DEBUG // Just to please Coverity. Cannot happen. if( m_papoFeatures == NULL ) { delete poFeatureCloned; return OGRERR_FAILURE; } #endif if( m_papoFeatures[nFID] != NULL ) { delete m_papoFeatures[nFID]; m_papoFeatures[nFID] = NULL; } else { ++m_nFeatureCount; } m_papoFeatures[nFID] = poFeatureCloned; } else { FeatureIterator oIter = m_oMapFeatures.find(nFID); if( oIter != m_oMapFeatures.end() ) { delete oIter->second; oIter->second = poFeatureCloned; } else { try { m_oMapFeatures[nFID] = poFeatureCloned; m_nFeatureCount++; } catch( const std::bad_alloc& ) { CPLError(CE_Failure, CPLE_OutOfMemory, "Cannot allocate memory"); delete poFeatureCloned; return OGRERR_FAILURE; } } } for( int i = 0; i < m_poFeatureDefn->GetGeomFieldCount(); ++i ) { OGRGeometry* poGeom = poFeatureCloned->GetGeomFieldRef(i); if( poGeom != NULL && poGeom->getSpatialReference() == NULL ) { poGeom->assignSpatialReference( m_poFeatureDefn->GetGeomFieldDefn(i)->GetSpatialRef()); } } m_bUpdated = true; return OGRERR_NONE; } /************************************************************************/ /* ICreateFeature() */ /************************************************************************/ OGRErr OGRMemLayer::ICreateFeature( OGRFeature *poFeature ) { if( !m_bUpdatable ) return OGRERR_FAILURE; if( poFeature->GetFID() != OGRNullFID && poFeature->GetFID() != m_iNextCreateFID ) m_bHasHoles = true; // If the feature has already a FID and that a feature with the same // FID is already registered in the layer, then unset our FID. if( poFeature->GetFID() >= 0 ) { if( m_papoFeatures != NULL ) { if( poFeature->GetFID() < m_nMaxFeatureCount && m_papoFeatures[poFeature->GetFID()] != NULL ) { poFeature->SetFID( OGRNullFID ); } } else { FeatureIterator oIter = m_oMapFeatures.find(poFeature->GetFID()); if( oIter != m_oMapFeatures.end() ) poFeature->SetFID( OGRNullFID ); } } return SetFeature( poFeature ); } /************************************************************************/ /* DeleteFeature() */ /************************************************************************/ OGRErr OGRMemLayer::DeleteFeature( GIntBig nFID ) { if( !m_bUpdatable ) return OGRERR_FAILURE; if( nFID < 0 ) { return OGRERR_FAILURE; } if( m_papoFeatures != NULL ) { if( nFID >= m_nMaxFeatureCount || m_papoFeatures[nFID] == NULL ) { return OGRERR_FAILURE; } delete m_papoFeatures[nFID]; m_papoFeatures[nFID] = NULL; } else { FeatureIterator oIter = m_oMapFeatures.find(nFID); if( oIter == m_oMapFeatures.end() ) { return OGRERR_FAILURE; } delete oIter->second; m_oMapFeatures.erase(oIter); } m_bHasHoles = true; --m_nFeatureCount; m_bUpdated = true; return OGRERR_NONE; } /************************************************************************/ /* GetFeatureCount() */ /* */ /* If a spatial filter is in effect, we turn control over to */ /* the generic counter. Otherwise we return the total count. */ /* Eventually we should consider implementing a more efficient */ /* way of counting features matching a spatial query. */ /************************************************************************/ GIntBig OGRMemLayer::GetFeatureCount( int bForce ) { if( m_poFilterGeom != NULL || m_poAttrQuery != NULL ) return OGRLayer::GetFeatureCount( bForce ); return m_nFeatureCount; } /************************************************************************/ /* TestCapability() */ /************************************************************************/ int OGRMemLayer::TestCapability( const char * pszCap ) { if( EQUAL(pszCap,OLCRandomRead) ) return TRUE; else if( EQUAL(pszCap,OLCSequentialWrite) || EQUAL(pszCap,OLCRandomWrite) ) return m_bUpdatable; else if( EQUAL(pszCap,OLCFastFeatureCount) ) return m_poFilterGeom == NULL && m_poAttrQuery == NULL; else if( EQUAL(pszCap,OLCFastSpatialFilter) ) return FALSE; else if( EQUAL(pszCap,OLCDeleteFeature) ) return m_bUpdatable; else if( EQUAL(pszCap,OLCCreateField) || EQUAL(pszCap,OLCCreateGeomField) || EQUAL(pszCap,OLCDeleteField) || EQUAL(pszCap,OLCReorderFields) || EQUAL(pszCap,OLCAlterFieldDefn) ) return m_bUpdatable; else if( EQUAL(pszCap,OLCFastSetNextByIndex) ) return m_poFilterGeom == NULL && m_poAttrQuery == NULL && ((m_papoFeatures != NULL && !m_bHasHoles) || m_oMapFeatures.empty()); else if( EQUAL(pszCap,OLCStringsAsUTF8) ) return m_bAdvertizeUTF8; else if( EQUAL(pszCap,OLCCurveGeometries) ) return TRUE; else if( EQUAL(pszCap,OLCMeasuredGeometries) ) return TRUE; return FALSE; } /************************************************************************/ /* CreateField() */ /************************************************************************/ OGRErr OGRMemLayer::CreateField( OGRFieldDefn *poField, int /* bApproxOK */ ) { if( !m_bUpdatable ) return OGRERR_FAILURE; /* -------------------------------------------------------------------- */ /* simple case, no features exist yet. */ /* -------------------------------------------------------------------- */ if( m_nFeatureCount == 0 ) { m_poFeatureDefn->AddFieldDefn( poField ); return OGRERR_NONE; } /* -------------------------------------------------------------------- */ /* Add field definition and setup remap definition. */ /* -------------------------------------------------------------------- */ m_poFeatureDefn->AddFieldDefn( poField ); int *panRemap = static_cast<int *>( CPLMalloc(sizeof(int) * m_poFeatureDefn->GetFieldCount()) ); for( int i = 0; i < m_poFeatureDefn->GetFieldCount(); ++i ) { if( i < m_poFeatureDefn->GetFieldCount() - 1 ) panRemap[i] = i; else panRemap[i] = -1; } /* -------------------------------------------------------------------- */ /* Remap all the internal features. Hopefully there aren't any */ /* external features referring to our OGRFeatureDefn! */ /* -------------------------------------------------------------------- */ IOGRMemLayerFeatureIterator* poIter = GetIterator(); OGRFeature* poFeature = NULL; while( (poFeature = poIter->Next()) != NULL ) { poFeature->RemapFields( NULL, panRemap ); } delete poIter; CPLFree( panRemap ); m_bUpdated = true; return OGRERR_NONE; } /************************************************************************/ /* DeleteField() */ /************************************************************************/ OGRErr OGRMemLayer::DeleteField( int iField ) { if( !m_bUpdatable ) return OGRERR_FAILURE; if( iField < 0 || iField >= m_poFeatureDefn->GetFieldCount() ) { CPLError( CE_Failure, CPLE_NotSupported, "Invalid field index"); return OGRERR_FAILURE; } /* -------------------------------------------------------------------- */ /* Update all the internal features. Hopefully there aren't any */ /* external features referring to our OGRFeatureDefn! */ /* -------------------------------------------------------------------- */ IOGRMemLayerFeatureIterator* poIter = GetIterator(); OGRFeature* poFeature = NULL; while( (poFeature = poIter->Next()) != NULL ) { OGRField* poFieldRaw = poFeature->GetRawFieldRef(iField); if( poFeature->IsFieldSetAndNotNull(iField) && !poFeature->IsFieldNull(iField) ) { /* Little trick to unallocate the field */ OGRField sField; OGR_RawField_SetUnset(&sField); poFeature->SetField(iField, &sField); } if( iField < m_poFeatureDefn->GetFieldCount() - 1 ) { memmove( poFieldRaw, poFieldRaw + 1, sizeof(OGRField) * (m_poFeatureDefn->GetFieldCount() - 1 - iField) ); } } delete poIter; m_bUpdated = true; return m_poFeatureDefn->DeleteFieldDefn( iField ); } /************************************************************************/ /* ReorderFields() */ /************************************************************************/ OGRErr OGRMemLayer::ReorderFields( int* panMap ) { if( !m_bUpdatable ) return OGRERR_FAILURE; if( m_poFeatureDefn->GetFieldCount() == 0 ) return OGRERR_NONE; const OGRErr eErr = OGRCheckPermutation(panMap, m_poFeatureDefn->GetFieldCount() ); if( eErr != OGRERR_NONE) return eErr; /* -------------------------------------------------------------------- */ /* Remap all the internal features. Hopefully there aren't any */ /* external features referring to our OGRFeatureDefn! */ /* -------------------------------------------------------------------- */ IOGRMemLayerFeatureIterator* poIter = GetIterator(); OGRFeature* poFeature = NULL; while( (poFeature = poIter->Next()) != NULL ) { poFeature->RemapFields( NULL, panMap ); } delete poIter; m_bUpdated = true; return m_poFeatureDefn->ReorderFieldDefns( panMap ); } /************************************************************************/ /* AlterFieldDefn() */ /************************************************************************/ OGRErr OGRMemLayer::AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nFlagsIn ) { if( !m_bUpdatable ) return OGRERR_FAILURE; if( iField < 0 || iField >= m_poFeatureDefn->GetFieldCount() ) { CPLError( CE_Failure, CPLE_NotSupported, "Invalid field index"); return OGRERR_FAILURE; } OGRFieldDefn* poFieldDefn = m_poFeatureDefn->GetFieldDefn(iField); if( (nFlagsIn & ALTER_TYPE_FLAG) && (poFieldDefn->GetType() != poNewFieldDefn->GetType() || poFieldDefn->GetSubType() != poNewFieldDefn->GetSubType())) { if( (poNewFieldDefn->GetType() == OFTDate || poNewFieldDefn->GetType() == OFTTime || poNewFieldDefn->GetType() == OFTDateTime) && (poFieldDefn->GetType() == OFTDate || poFieldDefn->GetType() == OFTTime || poFieldDefn->GetType() == OFTDateTime) ) { // Do nothing on features. } else if( poNewFieldDefn->GetType() == OFTInteger64 && poFieldDefn->GetType() == OFTInteger ) { /* -------------------------------------------------------------------- */ /* Update all the internal features. Hopefully there aren't any */ /* external features referring to our OGRFeatureDefn! */ /* -------------------------------------------------------------------- */ IOGRMemLayerFeatureIterator* poIter = GetIterator(); OGRFeature* poFeature = NULL; while( (poFeature = poIter->Next()) != NULL ) { OGRField* poFieldRaw = poFeature->GetRawFieldRef(iField); if( poFeature->IsFieldSetAndNotNull(iField) && !poFeature->IsFieldNull(iField) ) { poFieldRaw->Integer64 = poFieldRaw->Integer; } } delete poIter; } else if( poNewFieldDefn->GetType() == OFTReal && poFieldDefn->GetType() == OFTInteger ) { /* -------------------------------------------------------------------- */ /* Update all the internal features. Hopefully there aren't any */ /* external features referring to our OGRFeatureDefn! */ /* -------------------------------------------------------------------- */ IOGRMemLayerFeatureIterator* poIter = GetIterator(); OGRFeature* poFeature = NULL; while( (poFeature = poIter->Next()) != NULL ) { OGRField* poFieldRaw = poFeature->GetRawFieldRef(iField); if( poFeature->IsFieldSetAndNotNull(iField) && !poFeature->IsFieldNull(iField) ) { poFieldRaw->Real = poFieldRaw->Integer; } } delete poIter; } else if( poNewFieldDefn->GetType() == OFTReal && poFieldDefn->GetType() == OFTInteger64 ) { /* -------------------------------------------------------------------- */ /* Update all the internal features. Hopefully there aren't any */ /* external features referring to our OGRFeatureDefn! */ /* -------------------------------------------------------------------- */ IOGRMemLayerFeatureIterator* poIter = GetIterator(); OGRFeature* poFeature = NULL; while( (poFeature = poIter->Next()) != NULL ) { OGRField* poFieldRaw = poFeature->GetRawFieldRef(iField); if( poFeature->IsFieldSetAndNotNull(iField) && !poFeature->IsFieldNull(iField) ) { poFieldRaw->Real = static_cast<double>( poFieldRaw->Integer64 ); } } delete poIter; } else { if( poNewFieldDefn->GetType() != OFTString ) { CPLError( CE_Failure, CPLE_NotSupported, "Can only convert from OFTInteger to OFTReal, " "or from anything to OFTString" ); return OGRERR_FAILURE; } /* -------------------------------------------------------------------- */ /* Update all the internal features. Hopefully there aren't any */ /* external features referring to our OGRFeatureDefn! */ /* -------------------------------------------------------------------- */ IOGRMemLayerFeatureIterator* poIter = GetIterator(); OGRFeature* poFeature = NULL; while( (poFeature = poIter->Next()) != NULL ) { OGRField* poFieldRaw = poFeature->GetRawFieldRef(iField); if( poFeature->IsFieldSetAndNotNull(iField) && !poFeature->IsFieldNull(iField) ) { char* pszVal = CPLStrdup(poFeature->GetFieldAsString(iField)); /* Little trick to unallocate the field */ OGRField sField; OGR_RawField_SetUnset(&sField); poFeature->SetField(iField, &sField); poFieldRaw->String = pszVal; } } delete poIter; } poFieldDefn->SetSubType(OFSTNone); poFieldDefn->SetType(poNewFieldDefn->GetType()); poFieldDefn->SetSubType(poNewFieldDefn->GetSubType()); } if( nFlagsIn & ALTER_NAME_FLAG ) poFieldDefn->SetName(poNewFieldDefn->GetNameRef()); if( nFlagsIn & ALTER_WIDTH_PRECISION_FLAG ) { poFieldDefn->SetWidth(poNewFieldDefn->GetWidth()); poFieldDefn->SetPrecision(poNewFieldDefn->GetPrecision()); } m_bUpdated = true; return OGRERR_NONE; } /************************************************************************/ /* CreateGeomField() */ /************************************************************************/ OGRErr OGRMemLayer::CreateGeomField( OGRGeomFieldDefn *poGeomField, int /* bApproxOK */ ) { if( !m_bUpdatable ) return OGRERR_FAILURE; /* -------------------------------------------------------------------- */ /* simple case, no features exist yet. */ /* -------------------------------------------------------------------- */ if( m_nFeatureCount == 0 ) { m_poFeatureDefn->AddGeomFieldDefn( poGeomField ); return OGRERR_NONE; } /* -------------------------------------------------------------------- */ /* Add field definition and setup remap definition. */ /* -------------------------------------------------------------------- */ m_poFeatureDefn->AddGeomFieldDefn( poGeomField ); int *panRemap = static_cast<int *>( CPLMalloc(sizeof(int) * m_poFeatureDefn->GetGeomFieldCount()) ); for( GIntBig i = 0; i < m_poFeatureDefn->GetGeomFieldCount(); ++i ) { if( i < m_poFeatureDefn->GetGeomFieldCount() - 1 ) panRemap[i] = static_cast<int>(i); else panRemap[i] = -1; } /* -------------------------------------------------------------------- */ /* Remap all the internal features. Hopefully there aren't any */ /* external features referring to our OGRFeatureDefn! */ /* -------------------------------------------------------------------- */ IOGRMemLayerFeatureIterator* poIter = GetIterator(); OGRFeature* poFeature = NULL; while( (poFeature = poIter->Next()) != NULL ) { poFeature->RemapGeomFields( NULL, panRemap ); } delete poIter; CPLFree( panRemap ); m_bUpdated = true; return OGRERR_NONE; } /************************************************************************/ /* OGRMemLayerIteratorArray */ /************************************************************************/ class OGRMemLayerIteratorArray: public IOGRMemLayerFeatureIterator { GIntBig m_iCurIdx; GIntBig m_nMaxFeatureCount; OGRFeature **m_papoFeatures; public: OGRMemLayerIteratorArray( GIntBig nMaxFeatureCount, OGRFeature **papoFeatures ): m_iCurIdx(0), m_nMaxFeatureCount(nMaxFeatureCount), m_papoFeatures(papoFeatures) {} virtual ~OGRMemLayerIteratorArray() {} virtual OGRFeature* Next() override { while( m_iCurIdx < m_nMaxFeatureCount ) { OGRFeature* poFeature = m_papoFeatures[m_iCurIdx]; ++m_iCurIdx; if( poFeature != NULL ) return poFeature; } return NULL; } }; /************************************************************************/ /* OGRMemLayerIteratorMap */ /************************************************************************/ class OGRMemLayerIteratorMap: public IOGRMemLayerFeatureIterator { typedef std::map<GIntBig, OGRFeature*> FeatureMap; typedef std::map<GIntBig, OGRFeature*>::iterator FeatureIterator; FeatureMap& m_oMapFeatures; FeatureIterator m_oIter; public: explicit OGRMemLayerIteratorMap(FeatureMap& oMapFeatures): m_oMapFeatures(oMapFeatures), m_oIter(oMapFeatures.begin()) {} virtual ~OGRMemLayerIteratorMap() {} virtual OGRFeature* Next() override { if( m_oIter != m_oMapFeatures.end() ) { OGRFeature* poFeature = m_oIter->second; ++m_oIter; return poFeature; } return NULL; } private: CPL_DISALLOW_COPY_ASSIGN(OGRMemLayerIteratorMap) }; /************************************************************************/ /* GetIterator() */ /************************************************************************/ IOGRMemLayerFeatureIterator* OGRMemLayer::GetIterator() { if( m_oMapFeatures.empty() ) return new OGRMemLayerIteratorArray(m_nMaxFeatureCount, m_papoFeatures); return new OGRMemLayerIteratorMap(m_oMapFeatures); }