LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/shape - ogrshapedatasource.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 403 328 81.4 %
Date: 2012-04-28 Functions: 17 14 82.4 %

       1                 : /******************************************************************************
       2                 :  * $Id: ogrshapedatasource.cpp 23972 2012-02-13 21:19:46Z rouault $
       3                 :  *
       4                 :  * Project:  OpenGIS Simple Features Reference Implementation
       5                 :  * Purpose:  Implements OGRShapeDataSource class.
       6                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 1999,  Les Technologies SoftMap Inc.
      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 "ogrshape.h"
      31                 : #include "cpl_conv.h"
      32                 : #include "cpl_string.h"
      33                 : #include <set>
      34                 : 
      35                 : #define MAX_SIMULTANEOUSLY_OPENED_LAYERS    100
      36                 : //#define IMMEDIATE_OPENING 1
      37                 : 
      38                 : CPL_CVSID("$Id: ogrshapedatasource.cpp 23972 2012-02-13 21:19:46Z rouault $");
      39                 : 
      40                 : /************************************************************************/
      41                 : /*                         OGRShapeDataSource()                         */
      42                 : /************************************************************************/
      43                 : 
      44            2642 : OGRShapeDataSource::OGRShapeDataSource()
      45                 : 
      46                 : {
      47            2642 :     pszName = NULL;
      48            2642 :     papoLayers = NULL;
      49            2642 :     nLayers = 0;
      50            2642 :     bSingleFileDataSource = FALSE;
      51                 : 
      52            2642 :     poMRULayer = NULL;
      53            2642 :     poLRULayer = NULL;
      54            2642 :     nMRUListSize = 0;
      55            2642 : }
      56                 : 
      57                 : /************************************************************************/
      58                 : /*                        ~OGRShapeDataSource()                         */
      59                 : /************************************************************************/
      60                 : 
      61            2642 : OGRShapeDataSource::~OGRShapeDataSource()
      62                 : 
      63                 : {
      64            2642 :     CPLFree( pszName );
      65                 : 
      66            9016 :     for( int i = 0; i < nLayers; i++ )
      67                 :     {
      68            6374 :         CPLAssert( NULL != papoLayers[i] );
      69                 : 
      70            6374 :         delete papoLayers[i];
      71                 :     }
      72                 : 
      73            2642 :     CPLAssert( poMRULayer == NULL );
      74            2642 :     CPLAssert( poLRULayer == NULL );
      75            2642 :     CPLAssert( nMRUListSize == 0 );
      76                 :     
      77            2642 :     CPLFree( papoLayers );
      78            2642 : }
      79                 : 
      80                 : /************************************************************************/
      81                 : /*                                Open()                                */
      82                 : /************************************************************************/
      83                 : 
      84            2642 : int OGRShapeDataSource::Open( const char * pszNewName, int bUpdate,
      85                 :                               int bTestOpen, int bForceSingleFileDataSource )
      86                 : 
      87                 : {
      88                 :     VSIStatBufL  stat;
      89                 :     
      90            2642 :     CPLAssert( nLayers == 0 );
      91                 :     
      92            2642 :     pszName = CPLStrdup( pszNewName );
      93                 : 
      94            2642 :     bDSUpdate = bUpdate;
      95                 : 
      96            2642 :     bSingleFileDataSource = bForceSingleFileDataSource;
      97                 : 
      98                 : /* -------------------------------------------------------------------- */
      99                 : /*      If  bSingleFileDataSource is TRUE we don't try to do anything else.     */
     100                 : /*      This is only utilized when the OGRShapeDriver::Create()         */
     101                 : /*      method wants to create a stub OGRShapeDataSource for a          */
     102                 : /*      single shapefile.  The driver will take care of creating the    */
     103                 : /*      file by calling CreateLayer().                                  */
     104                 : /* -------------------------------------------------------------------- */
     105            2642 :     if( bSingleFileDataSource )
     106             188 :         return TRUE;
     107                 :     
     108                 : /* -------------------------------------------------------------------- */
     109                 : /*      Is the given path a directory or a regular file?                */
     110                 : /* -------------------------------------------------------------------- */
     111            2454 :     if( VSIStatExL( pszNewName, &stat, VSI_STAT_EXISTS_FLAG | VSI_STAT_NATURE_FLAG ) != 0 
     112                 :         || (!VSI_ISDIR(stat.st_mode) && !VSI_ISREG(stat.st_mode)) )
     113                 :     {
     114             372 :         if( !bTestOpen )
     115                 :             CPLError( CE_Failure, CPLE_AppDefined,
     116                 :                    "%s is neither a file or directory, Shape access failed.\n",
     117               0 :                       pszNewName );
     118                 : 
     119             372 :         return FALSE;
     120                 :     }
     121                 :     
     122                 : /* -------------------------------------------------------------------- */
     123                 : /*      Build a list of filenames we figure are Shape files.            */
     124                 : /* -------------------------------------------------------------------- */
     125            2082 :     if( VSI_ISREG(stat.st_mode) )
     126                 :     {
     127            1804 :         if( !OpenFile( pszNewName, bUpdate, bTestOpen ) )
     128                 :         {
     129            1106 :             if( !bTestOpen )
     130                 :                 CPLError( CE_Failure, CPLE_OpenFailed,
     131                 :                           "Failed to open shapefile %s.\n"
     132                 :                           "It may be corrupt or read-only file accessed in update mode.\n",
     133               0 :                           pszNewName );
     134                 : 
     135            1106 :             return FALSE;
     136                 :         }
     137                 : 
     138             698 :         bSingleFileDataSource = TRUE;
     139                 : 
     140             698 :         return TRUE;
     141                 :     }
     142                 :     else
     143                 :     {
     144             278 :         char      **papszCandidates = CPLReadDir( pszNewName );
     145             278 :         int       iCan, nCandidateCount = CSLCount( papszCandidates );
     146             278 :         int       bMightBeOldCoverage = FALSE;
     147             278 :         std::set<CPLString> osLayerNameSet;
     148                 : 
     149           24190 :         for( iCan = 0; iCan < nCandidateCount; iCan++ )
     150                 :         {
     151                 :             char        *pszFilename;
     152           23912 :             const char  *pszCandidate = papszCandidates[iCan];
     153                 : 
     154           23912 :             if( EQUAL(pszCandidate,"ARC") )
     155               0 :                 bMightBeOldCoverage = TRUE;
     156                 : 
     157           23912 :             if( strlen(pszCandidate) < 4
     158                 :                 || !EQUAL(pszCandidate+strlen(pszCandidate)-4,".shp") )
     159           17422 :                 continue;
     160                 : 
     161                 :             pszFilename =
     162            6490 :                 CPLStrdup(CPLFormFilename(pszNewName, pszCandidate, NULL));
     163                 : 
     164            6490 :             osLayerNameSet.insert(CPLGetBasename(pszCandidate));
     165                 : #ifdef IMMEDIATE_OPENING
     166                 :             if( !OpenFile( pszFilename, bUpdate, bTestOpen )
     167                 :                 && !bTestOpen )
     168                 :             {
     169                 :                 CPLError( CE_Failure, CPLE_OpenFailed,
     170                 :                           "Failed to open shapefile %s.\n"
     171                 :                           "It may be corrupt or read-only file accessed in update mode.\n",
     172                 :                           pszFilename );
     173                 :                 CPLFree( pszFilename );
     174                 :                 CSLDestroy( papszCandidates );
     175                 :                 return FALSE;
     176                 :             }
     177                 : #else
     178            6490 :             oVectorLayerName.push_back(pszFilename);
     179                 : #endif
     180            6490 :             CPLFree( pszFilename );
     181                 :         }
     182                 : 
     183                 :         // Try and .dbf files without apparent associated shapefiles. 
     184           24190 :         for( iCan = 0; iCan < nCandidateCount; iCan++ )
     185                 :         {
     186                 :             char        *pszFilename;
     187           23912 :             const char  *pszCandidate = papszCandidates[iCan];
     188                 :             const char  *pszLayerName;
     189                 : 
     190                 :             // We don't consume .dbf files in a directory that looks like
     191                 :             // an old style Arc/Info (for PC?) that unless we found at least
     192                 :             // some shapefiles.  See Bug 493. 
     193           23912 :             if( bMightBeOldCoverage && osLayerNameSet.size() == 0 )
     194               0 :                 continue;
     195                 : 
     196           23912 :             if( strlen(pszCandidate) < 4
     197                 :                 || !EQUAL(pszCandidate+strlen(pszCandidate)-4,".dbf") )
     198           17446 :                 continue;
     199                 : 
     200            6466 :             pszLayerName = CPLGetBasename(pszCandidate);
     201            6466 :             if (osLayerNameSet.find(pszLayerName) != osLayerNameSet.end())
     202            6436 :                 continue;
     203                 : 
     204                 :             // We don't want to access .dbf files with an associated .tab
     205                 :             // file, or it will never get recognised as a mapinfo dataset.
     206              30 :             int  iCan2, bFoundTAB = FALSE;
     207            7560 :             for( iCan2 = 0; iCan2 < nCandidateCount; iCan2++ )
     208                 :             {
     209            7530 :                 const char *pszCandidate2 = papszCandidates[iCan2];
     210                 : 
     211            7530 :                 if( EQUALN(pszCandidate2,pszLayerName,strlen(pszLayerName))
     212                 :                     && EQUAL(pszCandidate2 + strlen(pszLayerName), ".tab") )
     213               0 :                     bFoundTAB = TRUE;
     214                 :             }
     215                 : 
     216              30 :             if( bFoundTAB )
     217               0 :                 continue;
     218                 : 
     219                 :             pszFilename =
     220              30 :                 CPLStrdup(CPLFormFilename(pszNewName, pszCandidate, NULL));
     221                 : 
     222              30 :             osLayerNameSet.insert(CPLGetBasename(pszCandidate));
     223                 : 
     224                 : #ifdef IMMEDIATE_OPENING
     225                 :             if( !OpenFile( pszFilename, bUpdate, bTestOpen )
     226                 :                 && !bTestOpen )
     227                 :             {
     228                 :                 CPLError( CE_Failure, CPLE_OpenFailed,
     229                 :                           "Failed to open dbf file %s.\n"
     230                 :                           "It may be corrupt or read-only file accessed in update mode.\n",
     231                 :                           pszFilename );
     232                 :                 CPLFree( pszFilename );
     233                 :                 CSLDestroy( papszCandidates );
     234                 :                 return FALSE;
     235                 :             }
     236                 : #else
     237              30 :             oVectorLayerName.push_back(pszFilename);
     238                 : #endif
     239              30 :             CPLFree( pszFilename );
     240                 :         }
     241                 : 
     242             278 :         CSLDestroy( papszCandidates );
     243                 : 
     244                 : #ifdef IMMEDIATE_OPENING
     245                 :         int nDirLayers = nLayers;
     246                 : #else
     247             278 :         int nDirLayers = oVectorLayerName.size();
     248                 : #endif
     249                 : 
     250             278 :         CPLErrorReset();
     251                 : 
     252             278 :         return nDirLayers > 0 || !bTestOpen;
     253                 :     }
     254                 : }
     255                 : 
     256                 : /************************************************************************/
     257                 : /*                              OpenFile()                              */
     258                 : /************************************************************************/
     259                 : 
     260            6116 : int OGRShapeDataSource::OpenFile( const char *pszNewName, int bUpdate,
     261                 :                                   int bTestOpen )
     262                 : 
     263                 : {
     264                 :     SHPHandle   hSHP;
     265                 :     DBFHandle   hDBF;
     266            6116 :     const char *pszExtension = CPLGetExtension( pszNewName );
     267                 : 
     268                 :     (void) bTestOpen;
     269                 : 
     270            6116 :     if( !EQUAL(pszExtension,"shp") && !EQUAL(pszExtension,"shx")
     271                 :         && !EQUAL(pszExtension,"dbf") )
     272            1106 :         return FALSE;
     273                 : 
     274                 : /* -------------------------------------------------------------------- */
     275                 : /*      SHPOpen() should include better (CPL based) error reporting,    */
     276                 : /*      and we should be trying to distinquish at this point whether    */
     277                 : /*      failure is a result of trying to open a non-shapefile, or       */
     278                 : /*      whether it was a shapefile and we want to report the error      */
     279                 : /*      up.                                                             */
     280                 : /*                                                                      */
     281                 : /*      Care is taken to suppress the error and only reissue it if      */
     282                 : /*      we think it is appropriate.                                     */
     283                 : /* -------------------------------------------------------------------- */
     284            5010 :     CPLPushErrorHandler( CPLQuietErrorHandler );
     285            5010 :     if( bUpdate )
     286            3350 :         hSHP = SHPOpen( pszNewName, "r+" );
     287                 :     else
     288            1660 :         hSHP = SHPOpen( pszNewName, "r" );
     289            5010 :     CPLPopErrorHandler();
     290                 : 
     291            5010 :     if( hSHP == NULL 
     292                 :         && (!EQUAL(CPLGetExtension(pszNewName),"dbf") 
     293                 :             || strstr(CPLGetLastErrorMsg(),".shp") == NULL) )
     294                 :     {
     295               2 :         CPLString osMsg = CPLGetLastErrorMsg();
     296                 : 
     297               2 :         CPLError( CE_Failure, CPLE_OpenFailed, "%s", osMsg.c_str() );
     298                 : 
     299               2 :         return FALSE;
     300                 :     }
     301            5008 :     CPLErrorReset();
     302                 :     
     303                 : /* -------------------------------------------------------------------- */
     304                 : /*      Open the .dbf file, if it exists.  To open a dbf file, the      */
     305                 : /*      filename has to either refer to a successfully opened shp       */
     306                 : /*      file or has to refer to the actual .dbf file.                   */
     307                 : /* -------------------------------------------------------------------- */
     308            5008 :     if( hSHP != NULL || EQUAL(CPLGetExtension(pszNewName),"dbf") )
     309                 :     {
     310            5008 :         if( bUpdate )
     311                 :         {
     312            3350 :             hDBF = DBFOpen( pszNewName, "r+" );
     313            3350 :             if( hSHP != NULL && hDBF == NULL )
     314                 :             {
     315                 :                 VSIStatBufL sStat;
     316               6 :                 const char* pszDBFName = CPLResetExtension(pszNewName, "dbf");
     317               6 :                 VSILFILE* fp = NULL;
     318               6 :                 if( VSIStatExL( pszDBFName, &sStat, VSI_STAT_EXISTS_FLAG) == 0 )
     319                 :                 {
     320               0 :                     fp = VSIFOpenL(pszDBFName, "r+");
     321               0 :                     if (fp == NULL)
     322                 :                     {
     323                 :                         CPLError( CE_Failure, CPLE_OpenFailed,
     324                 :                                 "%s exists, but cannot be opened in update mode",
     325               0 :                                 pszDBFName );
     326               0 :                         return FALSE;
     327                 :                     }
     328                 :                 }
     329                 :                 else
     330                 :                 {
     331               6 :                     pszDBFName = CPLResetExtension(pszNewName, "DBF");
     332               6 :                     if( VSIStatExL( pszDBFName, &sStat, VSI_STAT_EXISTS_FLAG) == 0 )
     333                 :                     {
     334               0 :                         fp = VSIFOpenL(pszDBFName, "r+");
     335               0 :                         if (fp == NULL)
     336                 :                         {
     337                 :                             CPLError( CE_Failure, CPLE_OpenFailed,
     338                 :                                     "%s exists, but cannot be opened in update mode",
     339               0 :                                     pszDBFName );
     340               0 :                             return FALSE;
     341                 :                         }
     342                 :                     }
     343                 :                 }
     344               6 :                 if (fp != NULL)
     345               0 :                     VSIFCloseL(fp);
     346                 :             }
     347                 :         }
     348                 :         else
     349            1658 :             hDBF = DBFOpen( pszNewName, "r" );
     350                 :     }
     351                 :     else
     352               0 :         hDBF = NULL;
     353                 :         
     354            5008 :     if( hDBF == NULL && hSHP == NULL )
     355               0 :         return FALSE;
     356                 : 
     357                 : /* -------------------------------------------------------------------- */
     358                 : /*      Create the layer object.                                        */
     359                 : /* -------------------------------------------------------------------- */
     360                 :     OGRShapeLayer       *poLayer;
     361                 : 
     362                 :     poLayer = new OGRShapeLayer( this, pszNewName, hSHP, hDBF, NULL, FALSE, bUpdate,
     363            5008 :                                  wkbNone );
     364                 : 
     365                 : /* -------------------------------------------------------------------- */
     366                 : /*      Add layer to data source layer list.                            */
     367                 : /* -------------------------------------------------------------------- */
     368            5008 :     AddLayer(poLayer);
     369                 : 
     370            5008 :     return TRUE;
     371                 : }
     372                 : 
     373                 : 
     374                 : /************************************************************************/
     375                 : /*                             AddLayer()                               */
     376                 : /************************************************************************/
     377                 : 
     378            7390 : void OGRShapeDataSource::AddLayer(OGRShapeLayer* poLayer)
     379                 : {
     380                 :     papoLayers = (OGRShapeLayer **)
     381            7390 :         CPLRealloc( papoLayers,  sizeof(OGRShapeLayer *) * (nLayers+1) );
     382            7390 :     papoLayers[nLayers++] = poLayer;
     383                 : 
     384                 :     /* If we reach the limit, then register all the already opened layers */
     385                 :     /* Technically this code would not be necessary if there was not the */
     386                 :     /* following initial test in SetLastUsedLayer() : */
     387                 :     /*      if (nLayers < MAX_SIMULTANEOUSLY_OPENED_LAYERS) */
     388                 :     /*         return; */
     389            7390 :     if (nLayers == MAX_SIMULTANEOUSLY_OPENED_LAYERS && nMRUListSize == 0)
     390                 :     {
     391            1010 :         for(int i=0;i<nLayers;i++)
     392            1000 :             SetLastUsedLayer(papoLayers[i]);
     393                 :     }
     394            7390 : }
     395                 : 
     396                 : /************************************************************************/
     397                 : /*                            CreateLayer()                             */
     398                 : /************************************************************************/
     399                 : 
     400                 : OGRLayer *
     401            2384 : OGRShapeDataSource::CreateLayer( const char * pszLayerName,
     402                 :                                  OGRSpatialReference *poSRS,
     403                 :                                  OGRwkbGeometryType eType,
     404                 :                                  char ** papszOptions )
     405                 : 
     406                 : {
     407                 :     SHPHandle   hSHP;
     408                 :     DBFHandle   hDBF;
     409                 :     int         nShapeType;
     410                 : 
     411                 :     /* To ensure that existing layers are created */
     412            2384 :     GetLayerCount();
     413                 : 
     414                 : /* -------------------------------------------------------------------- */
     415                 : /*      Check that the layer doesn't already exist.                     */
     416                 : /* -------------------------------------------------------------------- */
     417            2384 :     if (GetLayerByName(pszLayerName) != NULL)
     418                 :     {
     419                 :         CPLError( CE_Failure, CPLE_AppDefined, "Layer '%s' already exists",
     420               2 :                     pszLayerName);
     421               2 :         return NULL;
     422                 :     }
     423                 : 
     424                 : /* -------------------------------------------------------------------- */
     425                 : /*      Verify we are in update mode.                                   */
     426                 : /* -------------------------------------------------------------------- */
     427            2382 :     if( !bDSUpdate )
     428                 :     {
     429                 :         CPLError( CE_Failure, CPLE_NoWriteAccess,
     430                 :                   "Data source %s opened read-only.\n"
     431                 :                   "New layer %s cannot be created.\n",
     432               0 :                   pszName, pszLayerName );
     433                 : 
     434               0 :         return NULL;
     435                 :     }
     436                 : 
     437                 : /* -------------------------------------------------------------------- */
     438                 : /*      Figure out what type of layer we need.                          */
     439                 : /* -------------------------------------------------------------------- */
     440            4572 :     if( eType == wkbUnknown || eType == wkbLineString )
     441            2190 :         nShapeType = SHPT_ARC;
     442             192 :     else if( eType == wkbPoint )
     443               4 :         nShapeType = SHPT_POINT;
     444             188 :     else if( eType == wkbPolygon )
     445             136 :         nShapeType = SHPT_POLYGON;
     446              52 :     else if( eType == wkbMultiPoint )
     447               4 :         nShapeType = SHPT_MULTIPOINT;
     448              48 :     else if( eType == wkbPoint25D )
     449               2 :         nShapeType = SHPT_POINTZ;
     450              46 :     else if( eType == wkbLineString25D )
     451               8 :         nShapeType = SHPT_ARCZ;
     452              38 :     else if( eType == wkbMultiLineString )
     453               4 :         nShapeType = SHPT_ARC;
     454              34 :     else if( eType == wkbMultiLineString25D )
     455               2 :         nShapeType = SHPT_ARCZ;
     456              32 :     else if( eType == wkbPolygon25D )
     457              10 :         nShapeType = SHPT_POLYGONZ;
     458              22 :     else if( eType == wkbMultiPolygon )
     459              10 :         nShapeType = SHPT_POLYGON;
     460              12 :     else if( eType == wkbMultiPolygon25D )
     461               2 :         nShapeType = SHPT_POLYGONZ;
     462              10 :     else if( eType == wkbMultiPoint25D )
     463               2 :         nShapeType = SHPT_MULTIPOINTZ;
     464               8 :     else if( eType == wkbNone )
     465               8 :         nShapeType = SHPT_NULL;
     466                 :     else
     467               0 :         nShapeType = -1;
     468                 : 
     469                 : /* -------------------------------------------------------------------- */
     470                 : /*      Has the application overridden this with a special creation     */
     471                 : /*      option?                                                         */
     472                 : /* -------------------------------------------------------------------- */
     473            2382 :     const char *pszOverride = CSLFetchNameValue( papszOptions, "SHPT" );
     474                 : 
     475            2382 :     if( pszOverride == NULL )
     476                 :         /* ignore */;
     477               4 :     else if( EQUAL(pszOverride,"POINT") )
     478                 :     {
     479               0 :         nShapeType = SHPT_POINT;
     480               0 :         eType = wkbPoint;
     481                 :     }
     482               4 :     else if( EQUAL(pszOverride,"ARC") )
     483                 :     {
     484               0 :         nShapeType = SHPT_ARC;
     485               0 :         eType = wkbLineString;
     486                 :     }
     487               4 :     else if( EQUAL(pszOverride,"POLYGON") )
     488                 :     {
     489               0 :         nShapeType = SHPT_POLYGON;
     490               0 :         eType = wkbPolygon;
     491                 :     }
     492               4 :     else if( EQUAL(pszOverride,"MULTIPOINT") )
     493                 :     {
     494               0 :         nShapeType = SHPT_MULTIPOINT;
     495               0 :         eType = wkbMultiPoint;
     496                 :     }
     497               4 :     else if( EQUAL(pszOverride,"POINTZ") )
     498                 :     {
     499               0 :         nShapeType = SHPT_POINTZ;
     500               0 :         eType = wkbPoint25D;
     501                 :     }
     502               4 :     else if( EQUAL(pszOverride,"ARCZ") )
     503                 :     {
     504               0 :         nShapeType = SHPT_ARCZ;
     505               0 :         eType = wkbLineString25D;
     506                 :     }
     507               4 :     else if( EQUAL(pszOverride,"POLYGONZ") )
     508                 :     {
     509               4 :         nShapeType = SHPT_POLYGONZ;
     510               4 :         eType = wkbPolygon25D;
     511                 :     }
     512               0 :     else if( EQUAL(pszOverride,"MULTIPOINTZ") )
     513                 :     {
     514               0 :         nShapeType = SHPT_MULTIPOINTZ;
     515               0 :         eType = wkbMultiPoint25D;
     516                 :     }
     517               0 :     else if( EQUAL(pszOverride,"NONE") || EQUAL(pszOverride,"NULL") )
     518                 :     {
     519               0 :         nShapeType = SHPT_NULL;
     520               0 :         eType = wkbNone;
     521                 :     }
     522                 :     else
     523                 :     {
     524                 :         CPLError( CE_Failure, CPLE_NotSupported,
     525                 :                   "Unknown SHPT value of `%s' passed to Shapefile layer\n"
     526                 :                   "creation.  Creation aborted.\n",
     527               0 :                   pszOverride );
     528                 : 
     529               0 :         return NULL;
     530                 :     }
     531                 : 
     532            2382 :     if( nShapeType == -1 )
     533                 :     {
     534                 :         CPLError( CE_Failure, CPLE_NotSupported,
     535                 :                   "Geometry type of `%s' not supported in shapefiles.\n"
     536                 :                   "Type can be overridden with a layer creation option\n"
     537                 :                   "of SHPT=POINT/ARC/POLYGON/MULTIPOINT/POINTZ/ARCZ/POLYGONZ/MULTIPOINTZ.\n",
     538               0 :                   OGRGeometryTypeToName(eType) );
     539               0 :         return NULL;
     540                 :     }
     541                 :     
     542                 : /* -------------------------------------------------------------------- */
     543                 : /*      What filename do we use, excluding the extension?               */
     544                 : /* -------------------------------------------------------------------- */
     545                 :     char *pszBasename;
     546                 : 
     547            2574 :     if(  bSingleFileDataSource && nLayers == 0 )
     548                 :     {
     549             192 :         char *pszPath = CPLStrdup(CPLGetPath(pszName));
     550             192 :         char *pszFBasename = CPLStrdup(CPLGetBasename(pszName));
     551                 : 
     552             192 :         pszBasename = CPLStrdup(CPLFormFilename(pszPath, pszFBasename, NULL));
     553                 : 
     554             192 :         CPLFree( pszFBasename );
     555             192 :         CPLFree( pszPath );
     556                 :     }
     557            2190 :     else if(  bSingleFileDataSource )
     558                 :     {
     559                 :         /* This is a very weird use case : the user creates/open a datasource */
     560                 :         /* made of a single shapefile 'foo.shp' and wants to add a new layer */
     561                 :         /* to it, 'bar'. So we create a new shapefile 'bar.shp' in the same */
     562                 :         /* directory as 'foo.shp' */
     563                 :         /* So technically, we will not be any longer a single file */
     564                 :         /* datasource ... Ahem ahem */
     565               2 :         char *pszPath = CPLStrdup(CPLGetPath(pszName));
     566               2 :         pszBasename = CPLStrdup(CPLFormFilename(pszPath,pszLayerName,NULL));
     567               2 :         CPLFree( pszPath );
     568                 :     }
     569                 :     else
     570            2188 :         pszBasename = CPLStrdup(CPLFormFilename(pszName,pszLayerName,NULL));
     571                 : 
     572                 : /* -------------------------------------------------------------------- */
     573                 : /*      Create the shapefile.                                           */
     574                 : /* -------------------------------------------------------------------- */
     575                 :     char        *pszFilename;
     576                 : 
     577            2382 :     if( nShapeType != SHPT_NULL )
     578                 :     {
     579            2374 :         pszFilename = CPLStrdup(CPLFormFilename( NULL, pszBasename, "shp" ));
     580                 : 
     581            2374 :         hSHP = SHPCreate( pszFilename, nShapeType );
     582                 :         
     583            2374 :         if( hSHP == NULL )
     584                 :         {
     585                 :             CPLError( CE_Failure, CPLE_OpenFailed,
     586                 :                       "Failed to open Shapefile `%s'.\n",
     587               0 :                       pszFilename );
     588               0 :             CPLFree( pszFilename );
     589               0 :             CPLFree( pszBasename );
     590               0 :             return NULL;
     591                 :         }
     592            2374 :         CPLFree( pszFilename );
     593                 :     }
     594                 :     else
     595               8 :         hSHP = NULL;
     596                 : 
     597                 : /* -------------------------------------------------------------------- */
     598                 : /*      Has a specific LDID been specified by the caller?               */
     599                 : /* -------------------------------------------------------------------- */
     600            2382 :     const char *pszLDID = CSLFetchNameValue( papszOptions, "ENCODING" );
     601                 : 
     602                 : /* -------------------------------------------------------------------- */
     603                 : /*      Create a DBF file.                                              */
     604                 : /* -------------------------------------------------------------------- */
     605            2382 :     pszFilename = CPLStrdup(CPLFormFilename( NULL, pszBasename, "dbf" ));
     606                 : 
     607            2382 :     if( pszLDID != NULL )
     608               0 :         hDBF = DBFCreateEx( pszFilename, pszLDID );
     609                 :     else
     610            2382 :         hDBF = DBFCreate( pszFilename );
     611                 : 
     612            2382 :     if( hDBF == NULL )
     613                 :     {
     614                 :         CPLError( CE_Failure, CPLE_OpenFailed,
     615                 :                   "Failed to open Shape DBF file `%s'.\n",
     616               0 :                   pszFilename );
     617               0 :         CPLFree( pszFilename );
     618               0 :         CPLFree( pszBasename );
     619               0 :         SHPClose(hSHP);
     620               0 :         return NULL;
     621                 :     }
     622                 : 
     623            2382 :     CPLFree( pszFilename );
     624                 : 
     625                 : /* -------------------------------------------------------------------- */
     626                 : /*      Create the .prj file, if required.                              */
     627                 : /* -------------------------------------------------------------------- */
     628            2382 :     if( poSRS != NULL )
     629                 :     {
     630             162 :         char    *pszWKT = NULL;
     631             162 :         CPLString osPrjFile = CPLFormFilename( NULL, pszBasename, "prj");
     632                 :         VSILFILE    *fp;
     633                 : 
     634                 :         /* the shape layer needs it's own copy */
     635             162 :         poSRS = poSRS->Clone();
     636             162 :         poSRS->morphToESRI();
     637                 : 
     638             162 :         if( poSRS->exportToWkt( &pszWKT ) == OGRERR_NONE 
     639                 :             && (fp = VSIFOpenL( osPrjFile, "wt" )) != NULL )
     640                 :         {
     641             162 :             VSIFWriteL( pszWKT, strlen(pszWKT), 1, fp );
     642             162 :             VSIFCloseL( fp );
     643                 :         }
     644                 : 
     645             162 :         CPLFree( pszWKT );
     646                 : 
     647             162 :         poSRS->morphFromESRI();
     648                 :     }
     649                 : 
     650                 : /* -------------------------------------------------------------------- */
     651                 : /*      Create the layer object.                                        */
     652                 : /* -------------------------------------------------------------------- */
     653                 :     OGRShapeLayer       *poLayer;
     654                 : 
     655                 :     poLayer = new OGRShapeLayer( this, pszBasename, hSHP, hDBF, poSRS, TRUE, TRUE,
     656            2382 :                                  eType );
     657                 : 
     658            2382 :     CPLFree( pszBasename );
     659                 : 
     660            2382 :     poLayer->SetResizeAtClose( CSLFetchBoolean( papszOptions, "RESIZE", FALSE ) );
     661                 : 
     662                 : /* -------------------------------------------------------------------- */
     663                 : /*      Add layer to data source layer list.                            */
     664                 : /* -------------------------------------------------------------------- */
     665            2382 :     AddLayer(poLayer);
     666                 : 
     667            2382 :     return poLayer;
     668                 : }
     669                 : 
     670                 : /************************************************************************/
     671                 : /*                           TestCapability()                           */
     672                 : /************************************************************************/
     673                 : 
     674             150 : int OGRShapeDataSource::TestCapability( const char * pszCap )
     675                 : 
     676                 : {
     677             150 :     if( EQUAL(pszCap,ODsCCreateLayer) )
     678             150 :         return bDSUpdate;
     679               0 :     else if( EQUAL(pszCap,ODsCDeleteLayer) )
     680               0 :         return bDSUpdate;
     681                 :     else
     682               0 :         return FALSE;
     683                 : }
     684                 : 
     685                 : /************************************************************************/
     686                 : /*                            GetLayerCount()                           */
     687                 : /************************************************************************/
     688                 : 
     689         2181434 : int OGRShapeDataSource::GetLayerCount()
     690                 : 
     691                 : {
     692                 : #ifndef IMMEDIATE_OPENING
     693         2181434 :     if (oVectorLayerName.size() != 0)
     694                 :     {
     695            3400 :         for(size_t i = 0; i < oVectorLayerName.size(); i++)
     696                 :         {
     697            3252 :             const char* pszFilename = oVectorLayerName[i].c_str();
     698            3252 :             const char* pszLayerName = CPLGetBasename(pszFilename);
     699                 : 
     700                 :             int j;
     701          512848 :             for(j=0;j<nLayers;j++)
     702                 :             {
     703          510708 :                 if (strcmp(papoLayers[j]->GetName(), pszLayerName) == 0)
     704            1112 :                     break;
     705                 :             }
     706            3252 :             if (j < nLayers)
     707            1112 :                 continue;
     708                 : 
     709            2140 :             if( !OpenFile( pszFilename, bDSUpdate, TRUE ) )
     710                 :             {
     711                 :                 CPLError( CE_Failure, CPLE_OpenFailed,
     712                 :                           "Failed to open file %s.\n"
     713                 :                           "It may be corrupt or read-only file accessed in update mode.\n",
     714               0 :                           pszFilename );
     715                 :             }
     716                 :         }
     717             148 :         oVectorLayerName.resize(0);
     718                 :     }
     719                 : #endif
     720                 : 
     721         2181434 :     return nLayers;
     722                 : }
     723                 : 
     724                 : /************************************************************************/
     725                 : /*                              GetLayer()                              */
     726                 : /************************************************************************/
     727                 : 
     728         1086618 : OGRLayer *OGRShapeDataSource::GetLayer( int iLayer )
     729                 : 
     730                 : {
     731                 :     /* To ensure that existing layers are created */
     732         1086618 :     GetLayerCount();
     733                 : 
     734         1086618 :     if( iLayer < 0 || iLayer >= nLayers )
     735               0 :         return NULL;
     736                 :     else
     737         1086618 :         return papoLayers[iLayer];
     738                 : }
     739                 : 
     740                 : /************************************************************************/
     741                 : /*                           GetLayerByName()                           */
     742                 : /************************************************************************/
     743                 : 
     744            6150 : OGRLayer *OGRShapeDataSource::GetLayerByName(const char * pszLayerNameIn)
     745                 : {
     746                 : #ifndef IMMEDIATE_OPENING
     747            6150 :     if (oVectorLayerName.size() != 0)
     748                 :     {
     749                 :         int j;
     750          505226 :         for(j=0;j<nLayers;j++)
     751                 :         {
     752          503054 :             if (strcmp(papoLayers[j]->GetName(), pszLayerNameIn) == 0)
     753                 :             {
     754            1100 :                 return papoLayers[j];
     755                 :             }
     756                 :         }
     757                 : 
     758                 :         size_t i;
     759            2172 :         for(j = 0; j < 2; j++)
     760                 :         {
     761          503234 :             for(i = 0; i < oVectorLayerName.size(); i++)
     762                 :             {
     763          503234 :                 const char* pszFilename = oVectorLayerName[i].c_str();
     764          503234 :                 const char* pszLayerName = CPLGetBasename(pszFilename);
     765                 : 
     766          503234 :                 if (j == 0)
     767                 :                 {
     768          503234 :                     if (strcmp(pszLayerName, pszLayerNameIn) != 0)
     769          501062 :                         continue;
     770                 :                 }
     771                 :                 else
     772                 :                 {
     773               0 :                     if ( !EQUAL(pszLayerName, pszLayerNameIn) )
     774               0 :                         continue;
     775                 :                 }
     776                 : 
     777            2172 :                 if( !OpenFile( pszFilename, bDSUpdate, TRUE ) )
     778                 :                 {
     779                 :                     CPLError( CE_Failure, CPLE_OpenFailed,
     780                 :                             "Failed to open file %s.\n"
     781                 :                             "It may be corrupt or read-only file accessed in update mode.\n",
     782               2 :                             pszFilename );
     783               2 :                     return NULL;
     784                 :                 }
     785                 :                 else
     786                 :                 {
     787            2170 :                     return papoLayers[nLayers - 1];
     788                 :                 }
     789                 :             }
     790                 :         }
     791                 : 
     792               0 :         return NULL;
     793                 :     }
     794                 : #endif
     795                 : 
     796            2878 :     return OGRDataSource::GetLayerByName(pszLayerNameIn);
     797                 : }
     798                 : 
     799                 : /************************************************************************/
     800                 : /*                             ExecuteSQL()                             */
     801                 : /*                                                                      */
     802                 : /*      We override this to provide special handling of CREATE          */
     803                 : /*      SPATIAL INDEX commands.  Support forms are:                     */
     804                 : /*                                                                      */
     805                 : /*        CREATE SPATIAL INDEX ON layer_name [DEPTH n]                  */
     806                 : /*        DROP SPATIAL INDEX ON layer_name                              */
     807                 : /*        REPACK layer_name                                             */
     808                 : /*        RECOMPUTE EXTENT ON layer_name                                */
     809                 : /************************************************************************/
     810                 : 
     811            1452 : OGRLayer * OGRShapeDataSource::ExecuteSQL( const char *pszStatement,
     812                 :                                            OGRGeometry *poSpatialFilter,
     813                 :                                            const char *pszDialect )
     814                 : 
     815                 : {
     816                 : /* ==================================================================== */
     817                 : /*      Handle command to drop a spatial index.                         */
     818                 : /* ==================================================================== */
     819            1452 :     if( EQUALN(pszStatement, "REPACK ", 7) )
     820                 :     {
     821                 :         OGRShapeLayer *poLayer = (OGRShapeLayer *) 
     822              12 :             GetLayerByName( pszStatement + 7 );
     823                 : 
     824              12 :         if( poLayer != NULL )
     825              12 :             poLayer->Repack();
     826                 :         else
     827                 :         {
     828                 :             CPLError( CE_Failure, CPLE_AppDefined, 
     829                 :                       "No such layer as '%s' in REPACK.", 
     830               0 :                       pszStatement + 7 );
     831                 :         }
     832              12 :         return NULL;
     833                 :     }
     834                 : 
     835                 : /* ==================================================================== */
     836                 : /*      Handle command to shrink columns to their minimum size.         */
     837                 : /* ==================================================================== */
     838            1440 :     if( EQUALN(pszStatement, "RESIZE ", 7) )
     839                 :     {
     840                 :         OGRShapeLayer *poLayer = (OGRShapeLayer *)
     841               2 :             GetLayerByName( pszStatement + 7 );
     842                 : 
     843               2 :         if( poLayer != NULL )
     844               2 :             poLayer->ResizeDBF();
     845                 :         else
     846                 :         {
     847                 :             CPLError( CE_Failure, CPLE_AppDefined,
     848                 :                       "No such layer as '%s' in RESIZE.",
     849               0 :                       pszStatement + 7 );
     850                 :         }
     851               2 :         return NULL;
     852                 :     }
     853                 : 
     854                 : /* ==================================================================== */
     855                 : /*      Handle command to recompute extent                             */
     856                 : /* ==================================================================== */
     857            1438 :     if( EQUALN(pszStatement, "RECOMPUTE EXTENT ON ", 20) )
     858                 :     {
     859                 :         OGRShapeLayer *poLayer = (OGRShapeLayer *) 
     860               6 :             GetLayerByName( pszStatement + 20 );
     861                 : 
     862               6 :         if( poLayer != NULL )
     863               4 :             poLayer->RecomputeExtent();
     864                 :         else
     865                 :         {
     866                 :             CPLError( CE_Failure, CPLE_AppDefined, 
     867                 :                       "No such layer as '%s' in RECOMPUTE EXTENT.", 
     868               2 :                       pszStatement + 20 );
     869                 :         }
     870               6 :         return NULL;
     871                 :     }
     872                 :     
     873                 : /* ==================================================================== */
     874                 : /*      Handle command to drop a spatial index.                         */
     875                 : /* ==================================================================== */
     876            1432 :     if( EQUALN(pszStatement, "DROP SPATIAL INDEX ON ", 22) )
     877                 :     {
     878                 :         OGRShapeLayer *poLayer = (OGRShapeLayer *) 
     879               4 :             GetLayerByName( pszStatement + 22 );
     880                 : 
     881               4 :         if( poLayer != NULL )
     882               4 :             poLayer->DropSpatialIndex();
     883                 :         else
     884                 :         {
     885                 :             CPLError( CE_Failure, CPLE_AppDefined, 
     886                 :                       "No such layer as '%s' in DROP SPATIAL INDEX.", 
     887               0 :                       pszStatement + 22 );
     888                 :         }
     889               4 :         return NULL;
     890                 :     }
     891                 :     
     892                 : /* ==================================================================== */
     893                 : /*      Handle all comands except spatial index creation generically.   */
     894                 : /* ==================================================================== */
     895            1428 :     if( !EQUALN(pszStatement,"CREATE SPATIAL INDEX ON ",24) )
     896                 :     {
     897            1404 :         char **papszTokens = CSLTokenizeString( pszStatement );
     898            2228 :         if( CSLCount(papszTokens) >=4
     899             784 :             && (EQUAL(papszTokens[0],"CREATE") || EQUAL(papszTokens[0],"DROP"))
     900              20 :             && EQUAL(papszTokens[1],"INDEX")
     901              20 :             && EQUAL(papszTokens[2],"ON") )
     902                 :         {
     903              20 :             OGRShapeLayer *poLayer = (OGRShapeLayer *) GetLayerByName(papszTokens[3]);
     904              20 :             if (poLayer != NULL)
     905              20 :                 poLayer->InitializeIndexSupport( poLayer->GetFullName() );
     906                 :         }
     907            1404 :         CSLDestroy( papszTokens );
     908                 : 
     909                 :         return OGRDataSource::ExecuteSQL( pszStatement, poSpatialFilter, 
     910            1404 :                                           pszDialect );
     911                 :     }
     912                 : 
     913                 : /* -------------------------------------------------------------------- */
     914                 : /*      Parse into keywords.                                            */
     915                 : /* -------------------------------------------------------------------- */
     916              24 :     char **papszTokens = CSLTokenizeString( pszStatement );
     917                 :     
     918             120 :     if( CSLCount(papszTokens) < 5
     919              24 :         || !EQUAL(papszTokens[0],"CREATE")
     920              24 :         || !EQUAL(papszTokens[1],"SPATIAL")
     921              24 :         || !EQUAL(papszTokens[2],"INDEX") 
     922              24 :         || !EQUAL(papszTokens[3],"ON") 
     923                 :         || CSLCount(papszTokens) > 7 
     924               0 :         || (CSLCount(papszTokens) == 7 && !EQUAL(papszTokens[5],"DEPTH")) )
     925                 :     {
     926               0 :         CSLDestroy( papszTokens );
     927                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     928                 :                   "Syntax error in CREATE SPATIAL INDEX command.\n"
     929                 :                   "Was '%s'\n"
     930                 :                   "Should be of form 'CREATE SPATIAL INDEX ON <table> [DEPTH <n>]'",
     931               0 :                   pszStatement );
     932               0 :         return NULL;
     933                 :     }
     934                 : 
     935                 : /* -------------------------------------------------------------------- */
     936                 : /*      Get depth if provided.                                          */
     937                 : /* -------------------------------------------------------------------- */
     938              24 :     int nDepth = 0;
     939              24 :     if( CSLCount(papszTokens) == 7 )
     940               0 :         nDepth = atoi(papszTokens[6]);
     941                 : 
     942                 : /* -------------------------------------------------------------------- */
     943                 : /*      What layer are we operating on.                                 */
     944                 : /* -------------------------------------------------------------------- */
     945              24 :     OGRShapeLayer *poLayer = (OGRShapeLayer *) GetLayerByName(papszTokens[4]);
     946                 : 
     947              24 :     if( poLayer == NULL )
     948                 :     {
     949                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     950                 :                   "Layer %s not recognised.", 
     951               0 :                   papszTokens[4] );
     952               0 :         CSLDestroy( papszTokens );
     953               0 :         return NULL;
     954                 :     }
     955                 : 
     956              24 :     CSLDestroy( papszTokens );
     957                 : 
     958              24 :     poLayer->CreateSpatialIndex( nDepth );
     959              24 :     return NULL;
     960                 : }
     961                 : 
     962                 : 
     963                 : /************************************************************************/
     964                 : /*                            DeleteLayer()                             */
     965                 : /************************************************************************/
     966                 : 
     967            1016 : OGRErr OGRShapeDataSource::DeleteLayer( int iLayer )
     968                 : 
     969                 : {
     970                 :     char *pszFilename;
     971                 : 
     972                 : /* -------------------------------------------------------------------- */
     973                 : /*      Verify we are in update mode.                                   */
     974                 : /* -------------------------------------------------------------------- */
     975            1016 :     if( !bDSUpdate )
     976                 :     {
     977                 :         CPLError( CE_Failure, CPLE_NoWriteAccess,
     978                 :                   "Data source %s opened read-only.\n"
     979                 :                   "Layer %d cannot be deleted.\n",
     980               0 :                   pszName, iLayer );
     981                 : 
     982               0 :         return OGRERR_FAILURE;
     983                 :     }
     984                 : 
     985            1016 :     if( iLayer < 0 || iLayer >= nLayers )
     986                 :     {
     987                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     988                 :                   "Layer %d not in legal range of 0 to %d.", 
     989               0 :                   iLayer, nLayers-1 );
     990               0 :         return OGRERR_FAILURE;
     991                 :     }
     992                 : 
     993            1016 :     OGRShapeLayer* poLayerToDelete = (OGRShapeLayer*) papoLayers[iLayer];
     994                 : 
     995            1016 :     pszFilename = CPLStrdup(poLayerToDelete->GetFullName());
     996                 : 
     997            1016 :     delete poLayerToDelete;
     998                 : 
     999          173936 :     while( iLayer < nLayers - 1 )
    1000                 :     {
    1001          171904 :         papoLayers[iLayer] = papoLayers[iLayer+1];
    1002          171904 :         iLayer++;
    1003                 :     }
    1004                 : 
    1005            1016 :     nLayers--;
    1006                 : 
    1007            1016 :     VSIUnlink( CPLResetExtension(pszFilename, "shp") );
    1008            1016 :     VSIUnlink( CPLResetExtension(pszFilename, "shx") );
    1009            1016 :     VSIUnlink( CPLResetExtension(pszFilename, "dbf") );
    1010            1016 :     VSIUnlink( CPLResetExtension(pszFilename, "prj") );
    1011            1016 :     VSIUnlink( CPLResetExtension(pszFilename, "qix") );
    1012                 : 
    1013            1016 :     CPLFree( pszFilename );
    1014                 : 
    1015            1016 :     return OGRERR_NONE;
    1016                 : }
    1017                 : 
    1018                 : /************************************************************************/
    1019                 : /*                          SetLastUsedLayer()                          */
    1020                 : /************************************************************************/
    1021                 : 
    1022          247748 : void OGRShapeDataSource::SetLastUsedLayer( OGRShapeLayer* poLayer )
    1023                 : {
    1024                 :     /* We could remove that check and things would still work in */
    1025                 :     /* 99.99% cases */
    1026                 :     /* The only rationale for that test is to avoid breaking applications */
    1027                 :     /* that would deal with layers of the same datasource in different */
    1028                 :     /* threads. In GDAL < 1.9.0, this would work in most cases I can */
    1029                 :     /* imagine as shapefile layers are pretty much independant from each */
    1030                 :     /* others (although it has never been guaranteed to be a valid use case, */
    1031                 :     /* and the shape driver is likely more the exception than the rule in */
    1032                 :     /* permitting accessing layers from different threads !) */
    1033                 :     /* Anyway the LRU list mechanism leaves the door open to concurrent accesses to it */
    1034                 :     /* so when the datasource has not many layers, we don't try to build the */
    1035                 :     /* LRU list to avoid concurrency issues. I haven't bothered making the analysis */
    1036                 :     /* of how a mutex could be used to protect that (my intuition is that it would */
    1037                 :     /* need to be placed at the beginning of OGRShapeLayer::TouchLayer() ) */
    1038          247748 :     if (nLayers < MAX_SIMULTANEOUSLY_OPENED_LAYERS)
    1039          236286 :         return;
    1040                 : 
    1041                 :     /* If we are already the MRU layer, nothing to do */
    1042           11462 :     if (poLayer == poMRULayer)
    1043            6442 :         return;
    1044                 : 
    1045                 :     //CPLDebug("SHAPE", "SetLastUsedLayer(%s)", poLayer->GetName());
    1046                 : 
    1047            5024 :     if (poLayer->poPrevLayer != NULL || poLayer->poNextLayer != NULL)
    1048                 :     {
    1049                 :         /* Remove current layer from its current place in the list */
    1050               4 :         UnchainLayer(poLayer);
    1051                 :     }
    1052            5016 :     else if (nMRUListSize == MAX_SIMULTANEOUSLY_OPENED_LAYERS)
    1053                 :     {
    1054                 :         /* If we have reached the maximum allowed number of layers */
    1055                 :         /* simultaneously opened, then close the LRU one that */
    1056                 :         /* was still active until now */
    1057            4012 :         CPLAssert(poLRULayer != NULL);
    1058                 : 
    1059            4012 :         poLRULayer->CloseFileDescriptors();
    1060            4012 :         UnchainLayer(poLRULayer);
    1061                 :     }
    1062                 : 
    1063                 :     /* Put current layer on top of MRU list */
    1064            5020 :     CPLAssert(poLayer->poPrevLayer == NULL);
    1065            5020 :     CPLAssert(poLayer->poNextLayer == NULL);
    1066            5020 :     poLayer->poNextLayer = poMRULayer;
    1067            5020 :     if (poMRULayer != NULL)
    1068                 :     {
    1069            5010 :         CPLAssert(poMRULayer->poPrevLayer == NULL);
    1070            5010 :         poMRULayer->poPrevLayer = poLayer;
    1071                 :     }
    1072            5020 :     poMRULayer = poLayer;
    1073            5020 :     if (poLRULayer == NULL)
    1074              10 :         poLRULayer = poLayer;
    1075            5020 :     nMRUListSize ++;
    1076                 : }
    1077                 : 
    1078                 : 
    1079                 : /************************************************************************/
    1080                 : /*                            UnchainLayer()                            */
    1081                 : /*                                                                      */
    1082                 : /* Remove the layer from the MRU list                                   */
    1083                 : /************************************************************************/
    1084                 : 
    1085           11406 : void OGRShapeDataSource::UnchainLayer( OGRShapeLayer* poLayer )
    1086                 : {
    1087                 :     //CPLDebug("SHAPE", "UnchainLayer(%s)", poLayer->GetName());
    1088                 : 
    1089           11406 :     OGRShapeLayer* poPrevLayer = poLayer->poPrevLayer;
    1090           11406 :     OGRShapeLayer* poNextLayer = poLayer->poNextLayer;
    1091                 : 
    1092           11406 :     if (poPrevLayer != NULL)
    1093            5004 :         CPLAssert(poPrevLayer->poNextLayer == poLayer);
    1094           11406 :     if (poNextLayer != NULL)
    1095              18 :         CPLAssert(poNextLayer->poPrevLayer == poLayer);
    1096                 : 
    1097           11406 :     if (poPrevLayer != NULL || poNextLayer != NULL || poLayer == poMRULayer)
    1098            5020 :         nMRUListSize --;
    1099                 : 
    1100           11406 :     if (poLayer == poMRULayer)
    1101              16 :         poMRULayer = poNextLayer;
    1102           11406 :     if (poLayer == poLRULayer)
    1103            5002 :         poLRULayer = poPrevLayer;
    1104           11406 :     if (poPrevLayer != NULL)
    1105            5004 :         poPrevLayer->poNextLayer = poNextLayer;
    1106           11406 :     if (poNextLayer != NULL)
    1107              18 :         poNextLayer->poPrevLayer = poPrevLayer;
    1108           11406 :     poLayer->poPrevLayer = NULL;
    1109           11406 :     poLayer->poNextLayer = NULL;
    1110           11406 : }

Generated by: LCOV version 1.7