LTP GCOV extension - code coverage report
Current view: directory - ogr/ogrsf_frmts/shape - ogrshapedatasource.cpp
Test: gdal_filtered.info
Date: 2010-07-12 Instrumented lines: 291
Code covered: 74.6 % Executed lines: 217

       1                 : /******************************************************************************
       2                 :  * $Id: ogrshapedatasource.cpp 19753 2010-05-22 15:37:08Z 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                 : 
      34                 : CPL_CVSID("$Id: ogrshapedatasource.cpp 19753 2010-05-22 15:37:08Z rouault $");
      35                 : 
      36                 : /************************************************************************/
      37                 : /*                         OGRShapeDataSource()                         */
      38                 : /************************************************************************/
      39                 : 
      40             658 : OGRShapeDataSource::OGRShapeDataSource()
      41                 : 
      42                 : {
      43             658 :     pszName = NULL;
      44             658 :     papoLayers = NULL;
      45             658 :     nLayers = 0;
      46             658 :     bSingleNewFile = FALSE;
      47             658 : }
      48                 : 
      49                 : /************************************************************************/
      50                 : /*                        ~OGRShapeDataSource()                         */
      51                 : /************************************************************************/
      52                 : 
      53             658 : OGRShapeDataSource::~OGRShapeDataSource()
      54                 : 
      55                 : {
      56             658 :     CPLFree( pszName );
      57                 : 
      58            1679 :     for( int i = 0; i < nLayers; i++ )
      59                 :     {
      60            1021 :         CPLAssert( NULL != papoLayers[i] );
      61                 : 
      62            1021 :         delete papoLayers[i];
      63                 :     }
      64                 :     
      65             658 :     CPLFree( papoLayers );
      66             658 : }
      67                 : 
      68                 : /************************************************************************/
      69                 : /*                                Open()                                */
      70                 : /************************************************************************/
      71                 : 
      72                 : int OGRShapeDataSource::Open( const char * pszNewName, int bUpdate,
      73             658 :                               int bTestOpen, int bSingleNewFileIn )
      74                 : 
      75                 : {
      76                 :     VSIStatBufL  stat;
      77                 :     
      78             658 :     CPLAssert( nLayers == 0 );
      79                 :     
      80             658 :     pszName = CPLStrdup( pszNewName );
      81                 : 
      82             658 :     bDSUpdate = bUpdate;
      83                 : 
      84             658 :     bSingleNewFile = bSingleNewFileIn;
      85                 : 
      86                 : /* -------------------------------------------------------------------- */
      87                 : /*      If bSingleNewFile is TRUE we don't try to do anything else.     */
      88                 : /*      This is only utilized when the OGRShapeDriver::Create()         */
      89                 : /*      method wants to create a stub OGRShapeDataSource for a          */
      90                 : /*      single shapefile.  The driver will take care of creating the    */
      91                 : /*      file by calling CreateLayer().                                  */
      92                 : /* -------------------------------------------------------------------- */
      93             658 :     if( bSingleNewFile )
      94              65 :         return TRUE;
      95                 :     
      96                 : /* -------------------------------------------------------------------- */
      97                 : /*      Is the given path a directory or a regular file?                */
      98                 : /* -------------------------------------------------------------------- */
      99             593 :     if( VSIStatL( pszNewName, &stat ) != 0 
     100                 :         || (!VSI_ISDIR(stat.st_mode) && !VSI_ISREG(stat.st_mode)) )
     101                 :     {
     102              80 :         if( !bTestOpen )
     103                 :             CPLError( CE_Failure, CPLE_AppDefined,
     104                 :                    "%s is neither a file or directory, Shape access failed.\n",
     105               0 :                       pszNewName );
     106                 : 
     107              80 :         return FALSE;
     108                 :     }
     109                 :     
     110                 : /* -------------------------------------------------------------------- */
     111                 : /*      Build a list of filenames we figure are Shape files.            */
     112                 : /* -------------------------------------------------------------------- */
     113             513 :     if( VSI_ISREG(stat.st_mode) )
     114                 :     {
     115             436 :         if( !OpenFile( pszNewName, bUpdate, bTestOpen ) )
     116                 :         {
     117             220 :             if( !bTestOpen )
     118                 :                 CPLError( CE_Failure, CPLE_OpenFailed,
     119                 :                           "Failed to open shapefile %s.\n"
     120                 :                           "It may be corrupt or read-only file accessed in update mode.\n",
     121               0 :                           pszNewName );
     122                 : 
     123             220 :             return FALSE;
     124                 :         }
     125                 : 
     126             216 :         return TRUE;
     127                 :     }
     128                 :     else
     129                 :     {
     130              77 :         char      **papszCandidates = CPLReadDir( pszNewName );
     131              77 :         int       iCan, nCandidateCount = CSLCount( papszCandidates );
     132              77 :         int       bMightBeOldCoverage = FALSE;
     133                 : 
     134            2658 :         for( iCan = 0; iCan < nCandidateCount; iCan++ )
     135                 :         {
     136                 :             char        *pszFilename;
     137            2581 :             const char  *pszCandidate = papszCandidates[iCan];
     138                 : 
     139            2581 :             if( EQUAL(pszCandidate,"ARC") )
     140               0 :                 bMightBeOldCoverage = TRUE;
     141                 : 
     142            2581 :             if( strlen(pszCandidate) < 4
     143                 :                 || !EQUAL(pszCandidate+strlen(pszCandidate)-4,".shp") )
     144            1909 :                 continue;
     145                 : 
     146                 :             pszFilename =
     147             672 :                 CPLStrdup(CPLFormFilename(pszNewName, pszCandidate, NULL));
     148                 : 
     149             672 :             if( !OpenFile( pszFilename, bUpdate, bTestOpen )
     150                 :                 && !bTestOpen )
     151                 :             {
     152                 :                 CPLError( CE_Failure, CPLE_OpenFailed,
     153                 :                           "Failed to open shapefile %s.\n"
     154                 :                           "It may be corrupt or read-only file accessed in update mode.\n",
     155               0 :                           pszFilename );
     156               0 :                 CPLFree( pszFilename );
     157               0 :                 return FALSE;
     158                 :             }
     159                 :             
     160             672 :             CPLFree( pszFilename );
     161                 :         }
     162                 : 
     163                 :         // Try and .dbf files without apparent associated shapefiles. 
     164            2658 :         for( iCan = 0; iCan < nCandidateCount; iCan++ )
     165                 :         {
     166                 :             char        *pszFilename;
     167            2581 :             const char  *pszCandidate = papszCandidates[iCan];
     168                 :             const char  *pszLayerName;
     169            2581 :             int         iLayer, bGotAlready = FALSE;
     170                 : 
     171                 :             // We don't consume .dbf files in a directory that looks like
     172                 :             // an old style Arc/Info (for PC?) that unless we found at least
     173                 :             // some shapefiles.  See Bug 493. 
     174            2581 :             if( bMightBeOldCoverage && nLayers == 0 )
     175               0 :                 continue;
     176                 : 
     177            2581 :             if( strlen(pszCandidate) < 4
     178                 :                 || !EQUAL(pszCandidate+strlen(pszCandidate)-4,".dbf") )
     179            1913 :                 continue;
     180                 : 
     181             668 :             pszLayerName = CPLGetBasename(pszCandidate);
     182           12296 :             for( iLayer = 0; iLayer < nLayers; iLayer++ )
     183                 :             {
     184           11628 :                 if( EQUAL(pszLayerName,
     185                 :                           GetLayer(iLayer)->GetLayerDefn()->GetName()) )
     186             660 :                     bGotAlready = TRUE;
     187                 :             }
     188                 :             
     189             668 :             if( bGotAlready )
     190             660 :                 continue;
     191                 : 
     192                 :             // We don't want to access .dbf files with an associated .tab
     193                 :             // file, or it will never get recognised as a mapinfo dataset.
     194               8 :             int  iCan2, bFoundTAB = FALSE;
     195            1296 :             for( iCan2 = 0; iCan2 < nCandidateCount; iCan2++ )
     196                 :             {
     197            1288 :                 const char *pszCandidate2 = papszCandidates[iCan2];
     198                 : 
     199            1288 :                 if( EQUALN(pszCandidate2,pszLayerName,strlen(pszLayerName))
     200                 :                     && EQUAL(pszCandidate2 + strlen(pszLayerName), ".tab") )
     201               0 :                     bFoundTAB = TRUE;
     202                 :             }
     203                 : 
     204               8 :             if( bFoundTAB )
     205               0 :                 continue;
     206                 :             
     207                 :             pszFilename =
     208               8 :                 CPLStrdup(CPLFormFilename(pszNewName, pszCandidate, NULL));
     209                 : 
     210               8 :             if( !OpenFile( pszFilename, bUpdate, bTestOpen )
     211                 :                 && !bTestOpen )
     212                 :             {
     213                 :                 CPLError( CE_Failure, CPLE_OpenFailed,
     214                 :                           "Failed to open dbf file %s.\n"
     215                 :                           "It may be corrupt or read-only file accessed in update mode.\n",
     216               0 :                           pszFilename );
     217               0 :                 CPLFree( pszFilename );
     218               0 :                 return FALSE;
     219                 :             }
     220                 :             
     221               8 :             CPLFree( pszFilename );
     222                 :         }
     223                 : 
     224              77 :         CSLDestroy( papszCandidates );
     225                 :         
     226              77 :         if( !bTestOpen && nLayers == 0 && !bUpdate )
     227                 :         {
     228                 :             CPLError( CE_Failure, CPLE_OpenFailed,
     229                 :                       "No Shapefiles found in directory %s\n",
     230               0 :                       pszNewName );
     231                 :         }
     232                 :     }
     233                 : 
     234              77 :     return nLayers > 0 || bUpdate;
     235                 : }
     236                 : 
     237                 : /************************************************************************/
     238                 : /*                              OpenFile()                              */
     239                 : /************************************************************************/
     240                 : 
     241                 : int OGRShapeDataSource::OpenFile( const char *pszNewName, int bUpdate,
     242            1116 :                                   int bTestOpen )
     243                 : 
     244                 : {
     245                 :     SHPHandle   hSHP;
     246                 :     DBFHandle   hDBF;
     247            1116 :     const char *pszExtension = CPLGetExtension( pszNewName );
     248                 : 
     249                 :     (void) bTestOpen;
     250                 : 
     251            1116 :     if( !EQUAL(pszExtension,"shp") && !EQUAL(pszExtension,"shx")
     252                 :         && !EQUAL(pszExtension,"dbf") )
     253             220 :         return FALSE;
     254                 : 
     255                 : /* -------------------------------------------------------------------- */
     256                 : /*      SHPOpen() should include better (CPL based) error reporting,    */
     257                 : /*      and we should be trying to distinquish at this point whether    */
     258                 : /*      failure is a result of trying to open a non-shapefile, or       */
     259                 : /*      whether it was a shapefile and we want to report the error      */
     260                 : /*      up.                                                             */
     261                 : /*                                                                      */
     262                 : /*      Care is taken to suppress the error and only reissue it if      */
     263                 : /*      we think it is appropriate.                                     */
     264                 : /* -------------------------------------------------------------------- */
     265             896 :     CPLPushErrorHandler( CPLQuietErrorHandler );
     266             896 :     if( bUpdate )
     267             656 :         hSHP = SHPOpen( pszNewName, "r+" );
     268                 :     else
     269             240 :         hSHP = SHPOpen( pszNewName, "r" );
     270             896 :     CPLPopErrorHandler();
     271                 : 
     272             896 :     if( hSHP == NULL 
     273                 :         && (!EQUAL(CPLGetExtension(pszNewName),"dbf") 
     274                 :             || strstr(CPLGetLastErrorMsg(),".shp") == NULL) )
     275                 :     {
     276               0 :         CPLString osMsg = CPLGetLastErrorMsg();
     277                 : 
     278               0 :         CPLError( CE_Failure, CPLE_OpenFailed, "%s", osMsg.c_str() );
     279                 : 
     280               0 :         return FALSE;
     281                 :     }
     282             896 :     CPLErrorReset();
     283                 :     
     284                 : /* -------------------------------------------------------------------- */
     285                 : /*      Open the .dbf file, if it exists.  To open a dbf file, the      */
     286                 : /*      filename has to either refer to a successfully opened shp       */
     287                 : /*      file or has to refer to the actual .dbf file.                   */
     288                 : /* -------------------------------------------------------------------- */
     289             896 :     if( hSHP != NULL || EQUAL(CPLGetExtension(pszNewName),"dbf") )
     290                 :     {
     291             896 :         if( bUpdate )
     292             656 :             hDBF = DBFOpen( pszNewName, "r+" );
     293                 :         else
     294             240 :             hDBF = DBFOpen( pszNewName, "r" );
     295                 :     }
     296                 :     else
     297               0 :         hDBF = NULL;
     298                 :         
     299             896 :     if( hDBF == NULL && hSHP == NULL )
     300               0 :         return FALSE;
     301                 : 
     302                 : /* -------------------------------------------------------------------- */
     303                 : /*      Is there an associated .prj file we can read?                   */
     304                 : /* -------------------------------------------------------------------- */
     305             896 :     OGRSpatialReference *poSRS = NULL;
     306             896 :     const char  *pszPrjFile = CPLResetExtension( pszNewName, "prj" );
     307             896 :     FILE        *fp = NULL;
     308                 : 
     309             896 :     fp = VSIFOpenL( pszPrjFile, "r" );
     310                 : 
     311             896 :     if( NULL == fp )
     312                 :     {
     313             819 :         pszPrjFile = CPLResetExtension( pszNewName, "PRJ" );
     314             819 :         fp = VSIFOpenL( pszPrjFile, "r" );
     315                 :     }
     316                 : 
     317             896 :     if( fp != NULL )
     318                 :     {
     319                 :         char    **papszLines;
     320                 : 
     321             171 :         VSIFCloseL( fp );
     322                 :         
     323             171 :         papszLines = CSLLoad( pszPrjFile );
     324                 : 
     325             171 :         poSRS = new OGRSpatialReference();
     326             171 :         if( poSRS->importFromESRI( papszLines ) != OGRERR_NONE )
     327                 :         {
     328               0 :             delete poSRS;
     329               0 :             poSRS = NULL;
     330                 :         }
     331             171 :         CSLDestroy( papszLines );
     332                 :     }
     333                 : 
     334                 : /* -------------------------------------------------------------------- */
     335                 : /*      Create the layer object.                                        */
     336                 : /* -------------------------------------------------------------------- */
     337                 :     OGRShapeLayer       *poLayer;
     338                 : 
     339                 :     poLayer = new OGRShapeLayer( pszNewName, hSHP, hDBF, poSRS, bUpdate,
     340             896 :                                  wkbNone );
     341                 : 
     342                 : 
     343             896 :     poLayer->InitializeIndexSupport( pszNewName );
     344                 : 
     345                 : /* -------------------------------------------------------------------- */
     346                 : /*      Add layer to data source layer list.                            */
     347                 : /* -------------------------------------------------------------------- */
     348                 :     papoLayers = (OGRShapeLayer **)
     349             896 :         CPLRealloc( papoLayers,  sizeof(OGRShapeLayer *) * (nLayers+1) );
     350             896 :     papoLayers[nLayers++] = poLayer;
     351                 :     
     352             896 :     return TRUE;
     353                 : }
     354                 : 
     355                 : /************************************************************************/
     356                 : /*                            CreateLayer()                             */
     357                 : /************************************************************************/
     358                 : 
     359                 : OGRLayer *
     360                 : OGRShapeDataSource::CreateLayer( const char * pszLayerName,
     361                 :                                  OGRSpatialReference *poSRS,
     362                 :                                  OGRwkbGeometryType eType,
     363             128 :                                  char ** papszOptions )
     364                 : 
     365                 : {
     366                 :     SHPHandle   hSHP;
     367                 :     DBFHandle   hDBF;
     368                 :     int         nShapeType;
     369                 :     int         iLayer;
     370                 : 
     371                 : /* -------------------------------------------------------------------- */
     372                 : /*      Check that the layer doesn't already exist.                     */
     373                 : /* -------------------------------------------------------------------- */
     374             736 :     for( iLayer = 0; iLayer < nLayers; iLayer++ )
     375                 :     {
     376             609 :         OGRLayer        *poLayer = papoLayers[iLayer];
     377                 : 
     378             609 :         if( poLayer != NULL 
     379                 :             && EQUAL(poLayer->GetLayerDefn()->GetName(),pszLayerName) )
     380                 :         {
     381                 :             CPLError( CE_Failure, CPLE_AppDefined, "Layer '%s' already exists",
     382               1 :                       pszLayerName);
     383               1 :             return NULL;
     384                 :         }
     385                 :     }
     386                 : 
     387                 : /* -------------------------------------------------------------------- */
     388                 : /*      Verify we are in update mode.                                   */
     389                 : /* -------------------------------------------------------------------- */
     390             127 :     if( !bDSUpdate )
     391                 :     {
     392                 :         CPLError( CE_Failure, CPLE_NoWriteAccess,
     393                 :                   "Data source %s opened read-only.\n"
     394                 :                   "New layer %s cannot be created.\n",
     395               0 :                   pszName, pszLayerName );
     396                 : 
     397               0 :         return NULL;
     398                 :     }
     399                 : 
     400                 : /* -------------------------------------------------------------------- */
     401                 : /*      Figure out what type of layer we need.                          */
     402                 : /* -------------------------------------------------------------------- */
     403             185 :     if( eType == wkbUnknown || eType == wkbLineString )
     404              58 :         nShapeType = SHPT_ARC;
     405              69 :     else if( eType == wkbPoint )
     406               2 :         nShapeType = SHPT_POINT;
     407              67 :     else if( eType == wkbPolygon )
     408              45 :         nShapeType = SHPT_POLYGON;
     409              22 :     else if( eType == wkbMultiPoint )
     410               2 :         nShapeType = SHPT_MULTIPOINT;
     411              20 :     else if( eType == wkbPoint25D )
     412               1 :         nShapeType = SHPT_POINTZ;
     413              19 :     else if( eType == wkbLineString25D )
     414               4 :         nShapeType = SHPT_ARCZ;
     415              15 :     else if( eType == wkbMultiLineString )
     416               2 :         nShapeType = SHPT_ARC;
     417              13 :     else if( eType == wkbMultiLineString25D )
     418               1 :         nShapeType = SHPT_ARCZ;
     419              12 :     else if( eType == wkbPolygon25D )
     420               3 :         nShapeType = SHPT_POLYGONZ;
     421               9 :     else if( eType == wkbMultiPolygon )
     422               5 :         nShapeType = SHPT_POLYGON;
     423               4 :     else if( eType == wkbMultiPolygon25D )
     424               1 :         nShapeType = SHPT_POLYGONZ;
     425               3 :     else if( eType == wkbMultiPoint25D )
     426               1 :         nShapeType = SHPT_MULTIPOINTZ;
     427               2 :     else if( eType == wkbNone )
     428               2 :         nShapeType = SHPT_NULL;
     429                 :     else
     430               0 :         nShapeType = -1;
     431                 : 
     432                 : /* -------------------------------------------------------------------- */
     433                 : /*      Has the application overridden this with a special creation     */
     434                 : /*      option?                                                         */
     435                 : /* -------------------------------------------------------------------- */
     436             127 :     const char *pszOverride = CSLFetchNameValue( papszOptions, "SHPT" );
     437                 : 
     438             127 :     if( pszOverride == NULL )
     439                 :         /* ignore */;
     440               2 :     else if( EQUAL(pszOverride,"POINT") )
     441                 :     {
     442               0 :         nShapeType = SHPT_POINT;
     443               0 :         eType = wkbPoint;
     444                 :     }
     445               2 :     else if( EQUAL(pszOverride,"ARC") )
     446                 :     {
     447               0 :         nShapeType = SHPT_ARC;
     448               0 :         eType = wkbLineString;
     449                 :     }
     450               2 :     else if( EQUAL(pszOverride,"POLYGON") )
     451                 :     {
     452               0 :         nShapeType = SHPT_POLYGON;
     453               0 :         eType = wkbPolygon;
     454                 :     }
     455               2 :     else if( EQUAL(pszOverride,"MULTIPOINT") )
     456                 :     {
     457               0 :         nShapeType = SHPT_MULTIPOINT;
     458               0 :         eType = wkbMultiPoint;
     459                 :     }
     460               2 :     else if( EQUAL(pszOverride,"POINTZ") )
     461                 :     {
     462               0 :         nShapeType = SHPT_POINTZ;
     463               0 :         eType = wkbPoint25D;
     464                 :     }
     465               2 :     else if( EQUAL(pszOverride,"ARCZ") )
     466                 :     {
     467               0 :         nShapeType = SHPT_ARCZ;
     468               0 :         eType = wkbLineString25D;
     469                 :     }
     470               2 :     else if( EQUAL(pszOverride,"POLYGONZ") )
     471                 :     {
     472               2 :         nShapeType = SHPT_POLYGONZ;
     473               2 :         eType = wkbPolygon25D;
     474                 :     }
     475               0 :     else if( EQUAL(pszOverride,"MULTIPOINTZ") )
     476                 :     {
     477               0 :         nShapeType = SHPT_MULTIPOINTZ;
     478               0 :         eType = wkbMultiPoint25D;
     479                 :     }
     480               0 :     else if( EQUAL(pszOverride,"NONE") )
     481                 :     {
     482               0 :         nShapeType = SHPT_NULL;
     483                 :     }
     484                 :     else
     485                 :     {
     486                 :         CPLError( CE_Failure, CPLE_NotSupported,
     487                 :                   "Unknown SHPT value of `%s' passed to Shapefile layer\n"
     488                 :                   "creation.  Creation aborted.\n",
     489               0 :                   pszOverride );
     490                 : 
     491               0 :         return NULL;
     492                 :     }
     493                 : 
     494             127 :     if( nShapeType == -1 )
     495                 :     {
     496                 :         CPLError( CE_Failure, CPLE_NotSupported,
     497                 :                   "Geometry type of `%s' not supported in shapefiles.\n"
     498                 :                   "Type can be overridden with a layer creation option\n"
     499                 :                   "of SHPT=POINT/ARC/POLYGON/MULTIPOINT/POINTZ/ARCZ/POLYGONZ/MULTIPOINTZ.\n",
     500               0 :                   OGRGeometryTypeToName(eType) );
     501               0 :         return NULL;
     502                 :     }
     503                 :     
     504                 : /* -------------------------------------------------------------------- */
     505                 : /*      What filename do we use, excluding the extension?               */
     506                 : /* -------------------------------------------------------------------- */
     507                 :     char *pszBasename;
     508                 : 
     509             192 :     if( bSingleNewFile && nLayers == 0 )
     510                 :     {
     511              65 :         char *pszPath = CPLStrdup(CPLGetPath(pszName));
     512              65 :         char *pszFBasename = CPLStrdup(CPLGetBasename(pszName));
     513                 : 
     514              65 :         pszBasename = CPLStrdup(CPLFormFilename(pszPath, pszFBasename, NULL));
     515                 : 
     516              65 :         CPLFree( pszFBasename );
     517              65 :         CPLFree( pszPath );
     518                 :     }
     519              62 :     else if( bSingleNewFile )
     520                 :     {
     521               0 :         char *pszPath = CPLStrdup(CPLGetPath(pszName));
     522               0 :         pszBasename = CPLStrdup(CPLFormFilename(pszPath,pszLayerName,NULL));
     523               0 :         CPLFree( pszPath );
     524                 :     }
     525                 :     else
     526              62 :         pszBasename = CPLStrdup(CPLFormFilename(pszName,pszLayerName,NULL));
     527                 : 
     528                 : /* -------------------------------------------------------------------- */
     529                 : /*      Create the shapefile.                                           */
     530                 : /* -------------------------------------------------------------------- */
     531                 :     char        *pszFilename;
     532                 : 
     533             127 :     if( nShapeType != SHPT_NULL )
     534                 :     {
     535             125 :         pszFilename = CPLStrdup(CPLFormFilename( NULL, pszBasename, "shp" ));
     536                 : 
     537             125 :         hSHP = SHPCreate( pszFilename, nShapeType );
     538                 :         
     539             125 :         if( hSHP == NULL )
     540                 :         {
     541                 :             CPLError( CE_Failure, CPLE_OpenFailed,
     542                 :                       "Failed to open Shapefile `%s'.\n",
     543               0 :                       pszFilename );
     544               0 :             CPLFree( pszFilename );
     545               0 :             CPLFree( pszBasename );
     546               0 :             return NULL;
     547                 :         }
     548             125 :         CPLFree( pszFilename );
     549                 :     }
     550                 :     else
     551               2 :         hSHP = NULL;
     552                 : 
     553                 : /* -------------------------------------------------------------------- */
     554                 : /*      Create a DBF file.                                              */
     555                 : /* -------------------------------------------------------------------- */
     556             127 :     pszFilename = CPLStrdup(CPLFormFilename( NULL, pszBasename, "dbf" ));
     557                 :     
     558             127 :     hDBF = DBFCreate( pszFilename );
     559                 : 
     560             127 :     if( hDBF == NULL )
     561                 :     {
     562                 :         CPLError( CE_Failure, CPLE_OpenFailed,
     563                 :                   "Failed to open Shape DBF file `%s'.\n",
     564               0 :                   pszFilename );
     565               0 :         CPLFree( pszFilename );
     566               0 :         CPLFree( pszBasename );
     567               0 :         SHPClose(hSHP);
     568               0 :         return NULL;
     569                 :     }
     570                 : 
     571             127 :     CPLFree( pszFilename );
     572                 : 
     573                 : /* -------------------------------------------------------------------- */
     574                 : /*      Create the .prj file, if required.                              */
     575                 : /* -------------------------------------------------------------------- */
     576             127 :     if( poSRS != NULL )
     577                 :     {
     578              62 :         char    *pszWKT = NULL;
     579              62 :         CPLString osPrjFile = CPLFormFilename( NULL, pszBasename, "prj");
     580                 :         FILE    *fp;
     581                 : 
     582                 :         /* the shape layer needs it's own copy */
     583              62 :         poSRS = poSRS->Clone();
     584              62 :         poSRS->morphToESRI();
     585                 : 
     586              62 :         if( poSRS->exportToWkt( &pszWKT ) == OGRERR_NONE 
     587                 :             && (fp = VSIFOpenL( osPrjFile, "wt" )) != NULL )
     588                 :         {
     589              62 :             VSIFWriteL( pszWKT, strlen(pszWKT), 1, fp );
     590              62 :             VSIFCloseL( fp );
     591                 :         }
     592                 : 
     593              62 :         CPLFree( pszWKT );
     594                 : 
     595              62 :         poSRS->morphFromESRI();
     596                 :     }
     597                 : 
     598                 : /* -------------------------------------------------------------------- */
     599                 : /*      Create the layer object.                                        */
     600                 : /* -------------------------------------------------------------------- */
     601                 :     OGRShapeLayer       *poLayer;
     602                 : 
     603                 :     poLayer = new OGRShapeLayer( pszBasename, hSHP, hDBF, poSRS, TRUE,
     604             127 :                                  eType );
     605                 :     
     606             127 :     poLayer->InitializeIndexSupport( pszBasename );
     607                 : 
     608             127 :     CPLFree( pszBasename );
     609                 : 
     610                 : /* -------------------------------------------------------------------- */
     611                 : /*      Add layer to data source layer list.                            */
     612                 : /* -------------------------------------------------------------------- */
     613                 :     papoLayers = (OGRShapeLayer **)
     614             127 :         CPLRealloc( papoLayers,  sizeof(OGRShapeLayer *) * (nLayers+1) );
     615                 :     
     616             127 :     papoLayers[nLayers++] = poLayer;
     617                 : 
     618             127 :     return poLayer;
     619                 : }
     620                 : 
     621                 : /************************************************************************/
     622                 : /*                           TestCapability()                           */
     623                 : /************************************************************************/
     624                 : 
     625              46 : int OGRShapeDataSource::TestCapability( const char * pszCap )
     626                 : 
     627                 : {
     628              46 :     if( EQUAL(pszCap,ODsCCreateLayer) )
     629              46 :         return bDSUpdate;
     630               0 :     else if( EQUAL(pszCap,ODsCDeleteLayer) )
     631               0 :         return bDSUpdate;
     632                 :     else
     633               0 :         return FALSE;
     634                 : }
     635                 : 
     636                 : /************************************************************************/
     637                 : /*                              GetLayer()                              */
     638                 : /************************************************************************/
     639                 : 
     640           14207 : OGRLayer *OGRShapeDataSource::GetLayer( int iLayer )
     641                 : 
     642                 : {
     643           14207 :     if( iLayer < 0 || iLayer >= nLayers )
     644               0 :         return NULL;
     645                 :     else
     646           14207 :         return papoLayers[iLayer];
     647                 : }
     648                 : 
     649                 : /************************************************************************/
     650                 : /*                             ExecuteSQL()                             */
     651                 : /*                                                                      */
     652                 : /*      We override this to provide special handling of CREATE          */
     653                 : /*      SPATIAL INDEX commands.  Support forms are:                     */
     654                 : /*                                                                      */
     655                 : /*        CREATE SPATIAL INDEX ON layer_name [DEPTH n]                  */
     656                 : /*        DROP SPATIAL INDEX ON layer_name                              */
     657                 : /*        REPACK layer_name                                             */
     658                 : /************************************************************************/
     659                 : 
     660                 : OGRLayer * OGRShapeDataSource::ExecuteSQL( const char *pszStatement,
     661                 :                                            OGRGeometry *poSpatialFilter,
     662              53 :                                            const char *pszDialect )
     663                 : 
     664                 : {
     665                 : /* ==================================================================== */
     666                 : /*      Handle command to drop a spatial index.                         */
     667                 : /* ==================================================================== */
     668              53 :     if( EQUALN(pszStatement, "REPACK ", 7) )
     669                 :     {
     670                 :         OGRShapeLayer *poLayer = (OGRShapeLayer *) 
     671               3 :             GetLayerByName( pszStatement + 7 );
     672                 : 
     673               3 :         if( poLayer != NULL )
     674               3 :             poLayer->Repack();
     675                 :         else
     676                 :         {
     677                 :             CPLError( CE_Failure, CPLE_AppDefined, 
     678                 :                       "No such layer as '%s' in REPACK.", 
     679               0 :                       pszStatement + 7 );
     680                 :         }
     681               3 :         return NULL;
     682                 :     }
     683                 :     
     684                 : /* ==================================================================== */
     685                 : /*      Handle command to drop a spatial index.                         */
     686                 : /* ==================================================================== */
     687              50 :     if( EQUALN(pszStatement, "DROP SPATIAL INDEX ON ", 22) )
     688                 :     {
     689                 :         OGRShapeLayer *poLayer = (OGRShapeLayer *) 
     690               1 :             GetLayerByName( pszStatement + 22 );
     691                 : 
     692               1 :         if( poLayer != NULL )
     693               1 :             poLayer->DropSpatialIndex();
     694                 :         else
     695                 :         {
     696                 :             CPLError( CE_Failure, CPLE_AppDefined, 
     697                 :                       "No such layer as '%s' in DROP SPATIAL INDEX.", 
     698               0 :                       pszStatement + 19 );
     699                 :         }
     700               1 :         return NULL;
     701                 :     }
     702                 :     
     703                 : /* ==================================================================== */
     704                 : /*      Handle all comands except spatial index creation generically.   */
     705                 : /* ==================================================================== */
     706              49 :     if( !EQUALN(pszStatement,"CREATE SPATIAL INDEX ON ",24) )
     707                 :         return OGRDataSource::ExecuteSQL( pszStatement, poSpatialFilter, 
     708              46 :                                           pszDialect );
     709                 : 
     710                 : /* -------------------------------------------------------------------- */
     711                 : /*      Parse into keywords.                                            */
     712                 : /* -------------------------------------------------------------------- */
     713               3 :     char **papszTokens = CSLTokenizeString( pszStatement );
     714                 :     
     715               3 :     if( CSLCount(papszTokens) < 5
     716                 :         || !EQUAL(papszTokens[0],"CREATE")
     717                 :         || !EQUAL(papszTokens[1],"SPATIAL")
     718                 :         || !EQUAL(papszTokens[2],"INDEX") 
     719                 :         || !EQUAL(papszTokens[3],"ON") 
     720                 :         || CSLCount(papszTokens) > 7 
     721                 :         || (CSLCount(papszTokens) == 7 && !EQUAL(papszTokens[5],"DEPTH")) )
     722                 :     {
     723               0 :         CSLDestroy( papszTokens );
     724                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     725                 :                   "Syntax error in CREATE SPATIAL INDEX command.\n"
     726                 :                   "Was '%s'\n"
     727                 :                   "Should be of form 'CREATE SPATIAL INDEX ON <table> [DEPTH <n>]'",
     728               0 :                   pszStatement );
     729               0 :         return NULL;
     730                 :     }
     731                 : 
     732                 : /* -------------------------------------------------------------------- */
     733                 : /*      Get depth if provided.                                          */
     734                 : /* -------------------------------------------------------------------- */
     735               3 :     int nDepth = 0;
     736               3 :     if( CSLCount(papszTokens) == 7 )
     737               0 :         nDepth = atoi(papszTokens[6]);
     738                 : 
     739                 : /* -------------------------------------------------------------------- */
     740                 : /*      What layer are we operating on.                                 */
     741                 : /* -------------------------------------------------------------------- */
     742               3 :     OGRShapeLayer *poLayer = (OGRShapeLayer *) GetLayerByName(papszTokens[4]);
     743               3 :     CSLDestroy( papszTokens );
     744                 : 
     745               3 :     if( poLayer == NULL )
     746                 :     {
     747                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     748                 :                   "Layer %s not recognised.", 
     749               0 :                   papszTokens[4] );
     750               0 :         return NULL;
     751                 :     }
     752                 : 
     753               3 :     poLayer->CreateSpatialIndex( nDepth );
     754               3 :     return NULL;
     755                 : }
     756                 : 
     757                 : 
     758                 : /************************************************************************/
     759                 : /*                            DeleteLayer()                             */
     760                 : /************************************************************************/
     761                 : 
     762               2 : OGRErr OGRShapeDataSource::DeleteLayer( int iLayer )
     763                 : 
     764                 : {
     765                 :     char *pszFilename;
     766                 : 
     767                 : /* -------------------------------------------------------------------- */
     768                 : /*      Verify we are in update mode.                                   */
     769                 : /* -------------------------------------------------------------------- */
     770               2 :     if( !bDSUpdate )
     771                 :     {
     772                 :         CPLError( CE_Failure, CPLE_NoWriteAccess,
     773                 :                   "Data source %s opened read-only.\n"
     774                 :                   "Layer %d cannot be deleted.\n",
     775               0 :                   pszName, iLayer );
     776                 : 
     777               0 :         return OGRERR_FAILURE;
     778                 :     }
     779                 : 
     780               2 :     if( iLayer < 0 || iLayer >= nLayers )
     781                 :     {
     782                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     783                 :                   "Layer %d not in legal range of 0 to %d.", 
     784               0 :                   iLayer, nLayers-1 );
     785               0 :         return OGRERR_FAILURE;
     786                 :     }
     787                 : 
     788               2 :     pszFilename = CPLStrdup(((OGRShapeLayer*) papoLayers[iLayer])->GetFullName());
     789                 : 
     790               2 :     delete papoLayers[iLayer];
     791                 : 
     792               4 :     while( iLayer < nLayers - 1 )
     793                 :     {
     794               0 :         papoLayers[iLayer] = papoLayers[iLayer+1];
     795               0 :         iLayer++;
     796                 :     }
     797                 : 
     798               2 :     nLayers--;
     799                 : 
     800               2 :     VSIUnlink( CPLResetExtension(pszFilename, "shp") );
     801               2 :     VSIUnlink( CPLResetExtension(pszFilename, "shx") );
     802               2 :     VSIUnlink( CPLResetExtension(pszFilename, "dbf") );
     803               2 :     VSIUnlink( CPLResetExtension(pszFilename, "prj") );
     804               2 :     VSIUnlink( CPLResetExtension(pszFilename, "qix") );
     805                 : 
     806               2 :     CPLFree( pszFilename );
     807                 : 
     808               2 :     return OGRERR_NONE;
     809                 : }

Generated by: LTP GCOV extension version 1.5