LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/mem - ogrmemlayer.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 181 174 96.1 %
Date: 2011-12-18 Functions: 19 16 84.2 %

       1                 : /******************************************************************************
       2                 :  * $Id: ogrmemlayer.cpp 23064 2011-09-05 20:39:52Z rouault $
       3                 :  *
       4                 :  * Project:  OpenGIS Simple Features Reference Implementation
       5                 :  * Purpose:  Implements OGRMemLayer class.
       6                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2003, Frank Warmerdam <warmerdam@pobox.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 "ogr_mem.h"
      31                 : #include "cpl_conv.h"
      32                 : #include "ogr_p.h"
      33                 : 
      34                 : CPL_CVSID("$Id: ogrmemlayer.cpp 23064 2011-09-05 20:39:52Z rouault $");
      35                 : 
      36                 : /************************************************************************/
      37                 : /*                            OGRMemLayer()                             */
      38                 : /************************************************************************/
      39                 : 
      40              57 : OGRMemLayer::OGRMemLayer( const char * pszName, OGRSpatialReference *poSRSIn, 
      41              57 :                           OGRwkbGeometryType eReqType )
      42                 : 
      43                 : {
      44              57 :     if( poSRSIn == NULL )
      45              48 :         poSRS = NULL;
      46                 :     else
      47               9 :         poSRS = poSRSIn->Clone();
      48                 :     
      49              57 :     iNextReadFID = 0;
      50              57 :     iNextCreateFID = 0;
      51                 : 
      52              57 :     nFeatureCount = 0;
      53              57 :     nMaxFeatureCount = 0;
      54              57 :     papoFeatures = NULL;
      55                 : 
      56              57 :     poFeatureDefn = new OGRFeatureDefn( pszName );
      57              57 :     poFeatureDefn->SetGeomType( eReqType );
      58              57 :     poFeatureDefn->Reference();
      59              57 : }
      60                 : 
      61                 : /************************************************************************/
      62                 : /*                           ~OGRMemLayer()                           */
      63                 : /************************************************************************/
      64                 : 
      65              57 : OGRMemLayer::~OGRMemLayer()
      66                 : 
      67                 : {
      68              57 :     if( m_nFeaturesRead > 0 && poFeatureDefn != NULL )
      69                 :     {
      70                 :         CPLDebug( "Mem", "%d features read on layer '%s'.",
      71                 :                   (int) m_nFeaturesRead, 
      72              42 :                   poFeatureDefn->GetName() );
      73                 :     }
      74                 : 
      75             777 :     for( int i = 0; i < nMaxFeatureCount; i++ )
      76                 :     {
      77             720 :         if( papoFeatures[i] != NULL )
      78             256 :             delete papoFeatures[i];
      79                 :     }
      80              57 :     CPLFree( papoFeatures );
      81                 : 
      82              57 :     if( poFeatureDefn )
      83              57 :         poFeatureDefn->Release();
      84                 : 
      85              57 :     if( poSRS )
      86               9 :         poSRS->Release();
      87              57 : }
      88                 : 
      89                 : /************************************************************************/
      90                 : /*                            ResetReading()                            */
      91                 : /************************************************************************/
      92                 : 
      93             127 : void OGRMemLayer::ResetReading()
      94                 : 
      95                 : {
      96             127 :     iNextReadFID = 0;
      97             127 : }
      98                 : 
      99                 : /************************************************************************/
     100                 : /*                           GetNextFeature()                           */
     101                 : /************************************************************************/
     102                 : 
     103             326 : OGRFeature *OGRMemLayer::GetNextFeature()
     104                 : 
     105                 : {
     106            1412 :     while( iNextReadFID < nMaxFeatureCount )
     107                 :     {
     108            1028 :         OGRFeature *poFeature = papoFeatures[iNextReadFID++];
     109                 : 
     110            1028 :         if( poFeature == NULL )
     111             469 :             continue;
     112                 : 
     113             559 :         if( (m_poFilterGeom == NULL
     114                 :              || FilterGeometry( poFeature->GetGeometryRef() ) )
     115                 :             && (m_poAttrQuery == NULL
     116                 :                 || m_poAttrQuery->Evaluate( poFeature ) ) )
     117                 :         {
     118             268 :             m_nFeaturesRead++;
     119             268 :             return poFeature->Clone();
     120                 :         }
     121                 :     }
     122                 : 
     123              58 :     return NULL;
     124                 : }
     125                 : 
     126                 : /************************************************************************/
     127                 : /*                           SetNextByIndex()                           */
     128                 : /************************************************************************/
     129                 : 
     130               4 : OGRErr OGRMemLayer::SetNextByIndex( long nIndex )
     131                 : 
     132                 : {
     133               4 :     if( m_poFilterGeom != NULL || m_poAttrQuery != NULL )
     134               1 :         return OGRLayer::SetNextByIndex( nIndex );
     135                 :         
     136               3 :     if (nIndex < 0 || nIndex >= nMaxFeatureCount)
     137               2 :         return OGRERR_FAILURE;
     138                 : 
     139               1 :     iNextReadFID = nIndex;
     140                 : 
     141               1 :     return OGRERR_NONE;
     142                 : }
     143                 : 
     144                 : /************************************************************************/
     145                 : /*                             GetFeature()                             */
     146                 : /************************************************************************/
     147                 : 
     148               5 : OGRFeature *OGRMemLayer::GetFeature( long nFeatureId )
     149                 : 
     150                 : {
     151               5 :     if( nFeatureId < 0 || nFeatureId >= nMaxFeatureCount )
     152               2 :         return NULL;
     153               3 :     else if( papoFeatures[nFeatureId] == NULL )
     154               1 :         return NULL;
     155                 :     else
     156               2 :         return papoFeatures[nFeatureId]->Clone();
     157                 : }
     158                 : 
     159                 : /************************************************************************/
     160                 : /*                             SetFeature()                             */
     161                 : /************************************************************************/
     162                 : 
     163             262 : OGRErr OGRMemLayer::SetFeature( OGRFeature *poFeature )
     164                 : 
     165                 : {
     166             262 :     if( poFeature == NULL )
     167               0 :         return OGRERR_FAILURE;
     168                 : 
     169             262 :     if( poFeature->GetFID() == OGRNullFID )
     170                 :     {
     171             672 :         while( iNextCreateFID < nMaxFeatureCount 
     172             200 :                && papoFeatures[iNextCreateFID] != NULL )
     173               0 :             iNextCreateFID++;
     174             236 :         poFeature->SetFID( iNextCreateFID++ );
     175                 :     }
     176              26 :     else if ( poFeature->GetFID() < OGRNullFID )
     177                 :     {
     178                 :         CPLError(CE_Failure, CPLE_NotSupported,
     179               1 :                  "negative FID are not supported");
     180               1 :         return OGRERR_FAILURE;
     181                 :     }
     182                 : 
     183             261 :     if( poFeature->GetFID() >= nMaxFeatureCount )
     184                 :     {
     185              57 :         int nNewCount = MAX(2*nMaxFeatureCount+10, poFeature->GetFID() + 1 );
     186                 : 
     187                 :         OGRFeature** papoNewFeatures = (OGRFeature **) 
     188              57 :             VSIRealloc( papoFeatures, sizeof(OGRFeature *) * nNewCount);
     189              57 :         if (papoNewFeatures == NULL)
     190                 :         {
     191                 :             CPLError(CE_Failure, CPLE_OutOfMemory,
     192               0 :                      "Cannot allocate array of %d elements", nNewCount);
     193               0 :             return OGRERR_FAILURE;
     194                 :         }
     195              57 :         papoFeatures = papoNewFeatures;
     196                 :         memset( papoFeatures + nMaxFeatureCount, 0, 
     197              57 :                 sizeof(OGRFeature *) * (nNewCount - nMaxFeatureCount) );
     198              57 :         nMaxFeatureCount = nNewCount;
     199                 :     }
     200                 : 
     201             261 :     if( papoFeatures[poFeature->GetFID()] != NULL )
     202                 :     {
     203               4 :         delete papoFeatures[poFeature->GetFID()];
     204               4 :         papoFeatures[poFeature->GetFID()] = NULL;
     205               4 :         nFeatureCount--;
     206                 :     }
     207                 : 
     208             261 :     papoFeatures[poFeature->GetFID()] = poFeature->Clone();
     209             261 :     nFeatureCount++;
     210                 : 
     211             261 :     return OGRERR_NONE;
     212                 : }
     213                 : 
     214                 : /************************************************************************/
     215                 : /*                           CreateFeature()                            */
     216                 : /************************************************************************/
     217                 : 
     218             257 : OGRErr OGRMemLayer::CreateFeature( OGRFeature *poFeature )
     219                 : 
     220                 : {
     221             257 :     if( poFeature->GetFID() != OGRNullFID 
     222                 :         && poFeature->GetFID() >= 0
     223                 :         && poFeature->GetFID() < nMaxFeatureCount )
     224                 :     {
     225               6 :         if( papoFeatures[poFeature->GetFID()] != NULL )
     226               6 :             poFeature->SetFID( OGRNullFID );
     227                 :     }
     228                 : 
     229             257 :     if( poFeature->GetFID() > 10000000 )
     230               0 :         poFeature->SetFID( OGRNullFID );
     231                 : 
     232             257 :     return SetFeature( poFeature );
     233                 : }
     234                 : 
     235                 : /************************************************************************/
     236                 : /*                           DeleteFeature()                            */
     237                 : /************************************************************************/
     238                 : 
     239               2 : OGRErr OGRMemLayer::DeleteFeature( long nFID )
     240                 : 
     241                 : {
     242               4 :     if( nFID < 0 || nFID >= nMaxFeatureCount 
     243               2 :         || papoFeatures[nFID] == NULL )
     244                 :     {
     245               1 :         return OGRERR_FAILURE;
     246                 :     }
     247                 :     else 
     248                 :     {
     249               1 :         delete papoFeatures[nFID];
     250               1 :         papoFeatures[nFID] = NULL;
     251               1 :         nFeatureCount--;
     252               1 :         return OGRERR_NONE;
     253                 :     }
     254                 : }
     255                 : 
     256                 : /************************************************************************/
     257                 : /*                          GetFeatureCount()                           */
     258                 : /*                                                                      */
     259                 : /*      If a spatial filter is in effect, we turn control over to       */
     260                 : /*      the generic counter.  Otherwise we return the total count.      */
     261                 : /*      Eventually we should consider implementing a more efficient     */
     262                 : /*      way of counting features matching a spatial query.              */
     263                 : /************************************************************************/
     264                 : 
     265              15 : int OGRMemLayer::GetFeatureCount( int bForce )
     266                 : 
     267                 : {
     268              15 :     if( m_poFilterGeom != NULL || m_poAttrQuery != NULL )
     269               3 :         return OGRLayer::GetFeatureCount( bForce );
     270                 :     else
     271              12 :         return nFeatureCount;
     272                 : }
     273                 : 
     274                 : /************************************************************************/
     275                 : /*                           TestCapability()                           */
     276                 : /************************************************************************/
     277                 : 
     278              34 : int OGRMemLayer::TestCapability( const char * pszCap )
     279                 : 
     280                 : {
     281              34 :     if( EQUAL(pszCap,OLCRandomRead) )
     282               1 :         return TRUE;
     283                 : 
     284              33 :     else if( EQUAL(pszCap,OLCSequentialWrite) 
     285                 :              || EQUAL(pszCap,OLCRandomWrite) )
     286               4 :         return TRUE;
     287                 : 
     288              29 :     else if( EQUAL(pszCap,OLCFastFeatureCount) )
     289               1 :         return m_poFilterGeom == NULL && m_poAttrQuery == NULL;
     290                 : 
     291              28 :     else if( EQUAL(pszCap,OLCFastSpatialFilter) )
     292               1 :         return FALSE;
     293                 : 
     294              27 :     else if( EQUAL(pszCap,OLCDeleteFeature) )
     295               1 :         return TRUE;
     296                 : 
     297              26 :     else if( EQUAL(pszCap,OLCCreateField) ||
     298                 :              EQUAL(pszCap,OLCDeleteField) ||
     299                 :              EQUAL(pszCap,OLCReorderFields) ||
     300                 :              EQUAL(pszCap,OLCAlterFieldDefn) )
     301               3 :         return TRUE;
     302                 : 
     303              23 :     else if( EQUAL(pszCap,OLCFastSetNextByIndex) )
     304               2 :         return m_poFilterGeom == NULL && m_poAttrQuery == NULL;
     305                 : 
     306                 :     else 
     307              21 :         return FALSE;
     308                 : }
     309                 : 
     310                 : /************************************************************************/
     311                 : /*                            CreateField()                             */
     312                 : /************************************************************************/
     313                 : 
     314              67 : OGRErr OGRMemLayer::CreateField( OGRFieldDefn *poField, int bApproxOK )
     315                 : 
     316                 : {
     317                 : /* -------------------------------------------------------------------- */
     318                 : /*      simple case, no features exist yet.                             */
     319                 : /* -------------------------------------------------------------------- */
     320              67 :     if( nFeatureCount == 0 )
     321                 :     {
     322              61 :         poFeatureDefn->AddFieldDefn( poField );
     323              61 :         return OGRERR_NONE;
     324                 :     }
     325                 : 
     326                 : /* -------------------------------------------------------------------- */
     327                 : /*      Add field definition and setup remap definition.                */
     328                 : /* -------------------------------------------------------------------- */
     329                 :     int  *panRemap;
     330                 :     int   i;
     331                 : 
     332               6 :     poFeatureDefn->AddFieldDefn( poField );
     333                 : 
     334               6 :     panRemap = (int *) CPLMalloc(sizeof(int) * poFeatureDefn->GetFieldCount());
     335              30 :     for( i = 0; i < poFeatureDefn->GetFieldCount(); i++ )
     336                 :     {
     337              24 :         if( i < poFeatureDefn->GetFieldCount() - 1 )
     338              18 :             panRemap[i] = i;
     339                 :         else
     340               6 :             panRemap[i] = -1;
     341                 :     }
     342                 : 
     343                 : /* -------------------------------------------------------------------- */
     344                 : /*      Remap all the internal features.  Hopefully there aren't any    */
     345                 : /*      external features referring to our OGRFeatureDefn!              */
     346                 : /* -------------------------------------------------------------------- */
     347              86 :     for( i = 0; i < nMaxFeatureCount; i++ )
     348                 :     {
     349              80 :         if( papoFeatures[i] != NULL )
     350              31 :             papoFeatures[i]->RemapFields( NULL, panRemap );
     351                 :     }
     352                 : 
     353               6 :     CPLFree( panRemap );
     354                 : 
     355               6 :     return OGRERR_NONE;
     356                 : }
     357                 : 
     358                 : /************************************************************************/
     359                 : /*                            DeleteField()                             */
     360                 : /************************************************************************/
     361                 : 
     362              10 : OGRErr OGRMemLayer::DeleteField( int iField )
     363                 : {
     364              10 :     if (iField < 0 || iField >= poFeatureDefn->GetFieldCount())
     365                 :     {
     366                 :         CPLError( CE_Failure, CPLE_NotSupported,
     367               2 :                   "Invalid field index");
     368               2 :         return OGRERR_FAILURE;
     369                 :     }
     370                 : 
     371                 : /* -------------------------------------------------------------------- */
     372                 : /*      Update all the internal features.  Hopefully there aren't any   */
     373                 : /*      external features referring to our OGRFeatureDefn!              */
     374                 : /* -------------------------------------------------------------------- */
     375              68 :     for( int i = 0; i < nMaxFeatureCount; i++ )
     376                 :     {
     377              60 :         if( papoFeatures[i] == NULL )
     378              36 :             continue;
     379                 : 
     380              24 :         OGRField* poFieldRaw = papoFeatures[i]->GetRawFieldRef(iField);
     381              24 :         if( papoFeatures[i]->IsFieldSet(iField) )
     382                 :         {
     383                 :             /* Little trick to unallocate the field */
     384                 :             OGRField sField;
     385              12 :             sField.Set.nMarker1 = OGRUnsetMarker;
     386              12 :             sField.Set.nMarker2 = OGRUnsetMarker;
     387              12 :             papoFeatures[i]->SetField(iField, &sField);
     388                 :         }
     389                 : 
     390              24 :         if (iField < poFeatureDefn->GetFieldCount() - 1)
     391                 :         {
     392                 :             memmove( poFieldRaw, poFieldRaw + 1,
     393              12 :                      sizeof(OGRField) * (poFeatureDefn->GetFieldCount() - 1 - iField) );
     394                 :         }
     395                 :     }
     396                 : 
     397               8 :     return poFeatureDefn->DeleteFieldDefn( iField );
     398                 : }
     399                 : 
     400                 : /************************************************************************/
     401                 : /*                           ReorderFields()                            */
     402                 : /************************************************************************/
     403                 : 
     404              12 : OGRErr OGRMemLayer::ReorderFields( int* panMap )
     405                 : {
     406              12 :     if (poFeatureDefn->GetFieldCount() == 0)
     407               1 :         return OGRERR_NONE;
     408                 : 
     409              11 :     OGRErr eErr = OGRCheckPermutation(panMap, poFeatureDefn->GetFieldCount());
     410              11 :     if (eErr != OGRERR_NONE)
     411               1 :         return eErr;
     412                 : 
     413                 : /* -------------------------------------------------------------------- */
     414                 : /*      Remap all the internal features.  Hopefully there aren't any    */
     415                 : /*      external features referring to our OGRFeatureDefn!              */
     416                 : /* -------------------------------------------------------------------- */
     417             110 :     for( int i = 0; i < nMaxFeatureCount; i++ )
     418                 :     {
     419             100 :         if( papoFeatures[i] != NULL )
     420              40 :             papoFeatures[i]->RemapFields( NULL, panMap );
     421                 :     }
     422                 : 
     423              10 :     return poFeatureDefn->ReorderFieldDefns( panMap );
     424                 : }
     425                 : 
     426                 : /************************************************************************/
     427                 : /*                           AlterFieldDefn()                           */
     428                 : /************************************************************************/
     429                 : 
     430              15 : OGRErr OGRMemLayer::AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nFlags )
     431                 : {
     432              15 :     if (iField < 0 || iField >= poFeatureDefn->GetFieldCount())
     433                 :     {
     434                 :         CPLError( CE_Failure, CPLE_NotSupported,
     435               2 :                   "Invalid field index");
     436               2 :         return OGRERR_FAILURE;
     437                 :     }
     438                 : 
     439              13 :     OGRFieldDefn* poFieldDefn = poFeatureDefn->GetFieldDefn(iField);
     440                 : 
     441              13 :     if ((nFlags & ALTER_TYPE_FLAG) &&
     442                 :         poFieldDefn->GetType() != poNewFieldDefn->GetType())
     443                 :     {
     444               4 :         if (poNewFieldDefn->GetType() != OFTString)
     445                 :         {
     446                 :             CPLError( CE_Failure, CPLE_NotSupported,
     447               0 :                       "Can only convert to OFTString");
     448               0 :             return OGRERR_FAILURE;
     449                 :         }
     450                 : 
     451                 : /* -------------------------------------------------------------------- */
     452                 : /*      Update all the internal features.  Hopefully there aren't any   */
     453                 : /*      external features referring to our OGRFeatureDefn!              */
     454                 : /* -------------------------------------------------------------------- */
     455              24 :         for( int i = 0; i < nMaxFeatureCount; i++ )
     456                 :         {
     457              20 :             if( papoFeatures[i] == NULL )
     458              12 :                 continue;
     459                 : 
     460               8 :             OGRField* poFieldRaw = papoFeatures[i]->GetRawFieldRef(iField);
     461               8 :             if( papoFeatures[i]->IsFieldSet(iField) )
     462                 :             {
     463               2 :                 char* pszVal = CPLStrdup(papoFeatures[i]->GetFieldAsString(iField));
     464                 : 
     465                 :                 /* Little trick to unallocate the field */
     466                 :                 OGRField sField;
     467               2 :                 sField.Set.nMarker1 = OGRUnsetMarker;
     468               2 :                 sField.Set.nMarker2 = OGRUnsetMarker;
     469               2 :                 papoFeatures[i]->SetField(iField, &sField);
     470                 : 
     471               2 :                 poFieldRaw->String = pszVal;
     472                 :             }
     473                 :         }
     474                 : 
     475               4 :         poFieldDefn->SetType(poNewFieldDefn->GetType());
     476                 :     }
     477                 : 
     478              13 :     if (nFlags & ALTER_NAME_FLAG)
     479               9 :         poFieldDefn->SetName(poNewFieldDefn->GetNameRef());
     480              13 :     if (nFlags & ALTER_WIDTH_PRECISION_FLAG)
     481                 :     {
     482              11 :         poFieldDefn->SetWidth(poNewFieldDefn->GetWidth());
     483              11 :         poFieldDefn->SetPrecision(poNewFieldDefn->GetPrecision());
     484                 :     }
     485                 : 
     486              13 :     return OGRERR_NONE;
     487                 : }
     488                 : 
     489                 : /************************************************************************/
     490                 : /*                           GetSpatialRef()                            */
     491                 : /************************************************************************/
     492                 : 
     493              11 : OGRSpatialReference *OGRMemLayer::GetSpatialRef()
     494                 : 
     495                 : {
     496              11 :     return poSRS;
     497                 : }

Generated by: LCOV version 1.7