LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/shape - ogrshapedatasource.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 288 214 74.3 %
Date: 2010-01-09 Functions: 10 10 100.0 %

       1                 : /******************************************************************************
       2                 :  * $Id: ogrshapedatasource.cpp 17806 2009-10-13 17:27:54Z 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 17806 2009-10-13 17:27:54Z rouault $");
      35                 : 
      36                 : /************************************************************************/
      37                 : /*                         OGRShapeDataSource()                         */
      38                 : /************************************************************************/
      39                 : 
      40             420 : OGRShapeDataSource::OGRShapeDataSource()
      41                 : 
      42                 : {
      43             420 :     pszName = NULL;
      44             420 :     papoLayers = NULL;
      45             420 :     nLayers = 0;
      46             420 :     bSingleNewFile = FALSE;
      47             420 : }
      48                 : 
      49                 : /************************************************************************/
      50                 : /*                        ~OGRShapeDataSource()                         */
      51                 : /************************************************************************/
      52                 : 
      53             840 : OGRShapeDataSource::~OGRShapeDataSource()
      54                 : 
      55                 : {
      56             420 :     CPLFree( pszName );
      57                 : 
      58            1333 :     for( int i = 0; i < nLayers; i++ )
      59                 :     {
      60                 :         CPLAssert( NULL != papoLayers[i] );
      61                 : 
      62             913 :         delete papoLayers[i];
      63                 :     }
      64                 :     
      65             420 :     CPLFree( papoLayers );
      66             840 : }
      67                 : 
      68                 : /************************************************************************/
      69                 : /*                                Open()                                */
      70                 : /************************************************************************/
      71                 : 
      72             420 : int OGRShapeDataSource::Open( const char * pszNewName, int bUpdate,
      73                 :                               int bTestOpen, int bSingleNewFileIn )
      74                 : 
      75                 : {
      76                 :     VSIStatBufL  stat;
      77                 :     
      78                 :     CPLAssert( nLayers == 0 );
      79                 :     
      80             420 :     pszName = CPLStrdup( pszNewName );
      81                 : 
      82             420 :     bDSUpdate = bUpdate;
      83                 : 
      84             420 :     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             420 :     if( bSingleNewFile )
      94              29 :         return TRUE;
      95                 :     
      96                 : /* -------------------------------------------------------------------- */
      97                 : /*      Is the given path a directory or a regular file?                */
      98                 : /* -------------------------------------------------------------------- */
      99             391 :     if( VSIStatL( pszNewName, &stat ) != 0 
     100                 :         || (!VSI_ISDIR(stat.st_mode) && !VSI_ISREG(stat.st_mode)) )
     101                 :     {
     102              71 :         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              71 :         return FALSE;
     108                 :     }
     109                 :     
     110                 : /* -------------------------------------------------------------------- */
     111                 : /*      Build a list of filenames we figure are Shape files.            */
     112                 : /* -------------------------------------------------------------------- */
     113             320 :     if( VSI_ISREG(stat.st_mode) )
     114                 :     {
     115             251 :         if( !OpenFile( pszNewName, bUpdate, bTestOpen ) )
     116                 :         {
     117             124 :             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             124 :             return FALSE;
     124                 :         }
     125                 : 
     126             127 :         return TRUE;
     127                 :     }
     128                 :     else
     129                 :     {
     130              69 :         char      **papszCandidates = CPLReadDir( pszNewName );
     131              69 :         int       iCan, nCandidateCount = CSLCount( papszCandidates );
     132              69 :         int       bMightBeOldCoverage = FALSE;
     133                 : 
     134            2645 :         for( iCan = 0; iCan < nCandidateCount; iCan++ )
     135                 :         {
     136                 :             char        *pszFilename;
     137            2576 :             const char  *pszCandidate = papszCandidates[iCan];
     138                 : 
     139            2576 :             if( EQUAL(pszCandidate,"ARC") )
     140               0 :                 bMightBeOldCoverage = TRUE;
     141                 : 
     142            2576 :             if( strlen(pszCandidate) < 4
     143                 :                 || !EQUAL(pszCandidate+strlen(pszCandidate)-4,".shp") )
     144            1887 :                 continue;
     145                 : 
     146                 :             pszFilename =
     147             689 :                 CPLStrdup(CPLFormFilename(pszNewName, pszCandidate, NULL));
     148                 : 
     149             689 :             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             689 :             CPLFree( pszFilename );
     161                 :         }
     162                 : 
     163                 :         // Try and .dbf files without apparent associated shapefiles. 
     164            2645 :         for( iCan = 0; iCan < nCandidateCount; iCan++ )
     165                 :         {
     166                 :             char        *pszFilename;
     167            2576 :             const char  *pszCandidate = papszCandidates[iCan];
     168                 :             const char  *pszLayerName;
     169            2576 :             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            2576 :             if( bMightBeOldCoverage && nLayers == 0 )
     175               0 :                 continue;
     176                 : 
     177            2576 :             if( strlen(pszCandidate) < 4
     178                 :                 || !EQUAL(pszCandidate+strlen(pszCandidate)-4,".dbf") )
     179            1891 :                 continue;
     180                 : 
     181             685 :             pszLayerName = CPLGetBasename(pszCandidate);
     182           12716 :             for( iLayer = 0; iLayer < nLayers; iLayer++ )
     183                 :             {
     184           12031 :                 if( EQUAL(pszLayerName,
     185                 :                           GetLayer(iLayer)->GetLayerDefn()->GetName()) )
     186             677 :                     bGotAlready = TRUE;
     187                 :             }
     188                 :             
     189             685 :             if( bGotAlready )
     190             677 :                 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            1072 :             for( iCan2 = 0; iCan2 < nCandidateCount; iCan2++ )
     196                 :             {
     197            1064 :                 const char *pszCandidate2 = papszCandidates[iCan2];
     198                 : 
     199            1064 :                 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              69 :         CSLDestroy( papszCandidates );
     225                 :         
     226              69 :         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              69 :     return nLayers > 0 || bUpdate;
     235                 : }
     236                 : 
     237                 : /************************************************************************/
     238                 : /*                              OpenFile()                              */
     239                 : /************************************************************************/
     240                 : 
     241             948 : int OGRShapeDataSource::OpenFile( const char *pszNewName, int bUpdate,
     242                 :                                   int bTestOpen )
     243                 : 
     244                 : {
     245                 :     SHPHandle   hSHP;
     246                 :     DBFHandle   hDBF;
     247             948 :     const char *pszExtension = CPLGetExtension( pszNewName );
     248                 : 
     249                 :     (void) bTestOpen;
     250                 : 
     251             948 :     if( !EQUAL(pszExtension,"shp") && !EQUAL(pszExtension,"shx")
     252                 :         && !EQUAL(pszExtension,"dbf") )
     253             124 :         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             824 :     CPLPushErrorHandler( CPLQuietErrorHandler );
     266             824 :     if( bUpdate )
     267             666 :         hSHP = SHPOpen( pszNewName, "r+" );
     268                 :     else
     269             158 :         hSHP = SHPOpen( pszNewName, "r" );
     270             824 :     CPLPopErrorHandler();
     271                 : 
     272             824 :     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             824 :     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             824 :     if( hSHP != NULL || EQUAL(CPLGetExtension(pszNewName),"dbf") )
     290                 :     {
     291             824 :         if( bUpdate )
     292             666 :             hDBF = DBFOpen( pszNewName, "r+" );
     293                 :         else
     294             158 :             hDBF = DBFOpen( pszNewName, "r" );
     295                 :     }
     296                 :     else
     297               0 :         hDBF = NULL;
     298                 :         
     299             824 :     if( hDBF == NULL && hSHP == NULL )
     300               0 :         return FALSE;
     301                 : 
     302                 : /* -------------------------------------------------------------------- */
     303                 : /*      Is there an associated .prj file we can read?                   */
     304                 : /* -------------------------------------------------------------------- */
     305             824 :     OGRSpatialReference *poSRS = NULL;
     306             824 :     const char  *pszPrjFile = CPLResetExtension( pszNewName, "prj" );
     307             824 :     FILE        *fp = NULL;
     308                 : 
     309             824 :     fp = VSIFOpen( pszPrjFile, "r" );
     310                 : 
     311                 : #ifndef WIN32
     312             824 :     if( NULL == fp )
     313                 :     {
     314             783 :         pszPrjFile = CPLResetExtension( pszNewName, "PRJ" );
     315             783 :         fp = VSIFOpen( pszPrjFile, "r" );
     316                 :     }
     317                 : #endif
     318                 : 
     319             824 :     if( fp != NULL )
     320                 :     {
     321                 :         char    **papszLines;
     322                 : 
     323              91 :         VSIFClose( fp );
     324                 :         
     325              91 :         papszLines = CSLLoad( pszPrjFile );
     326                 : 
     327              91 :         poSRS = new OGRSpatialReference();
     328              91 :         if( poSRS->importFromESRI( papszLines ) != OGRERR_NONE )
     329                 :         {
     330               0 :             delete poSRS;
     331               0 :             poSRS = NULL;
     332                 :         }
     333              91 :         CSLDestroy( papszLines );
     334                 :     }
     335                 : 
     336                 : /* -------------------------------------------------------------------- */
     337                 : /*      Create the layer object.                                        */
     338                 : /* -------------------------------------------------------------------- */
     339                 :     OGRShapeLayer       *poLayer;
     340                 : 
     341                 :     poLayer = new OGRShapeLayer( pszNewName, hSHP, hDBF, poSRS, bUpdate,
     342             824 :                                  wkbNone );
     343                 : 
     344                 : 
     345             824 :     poLayer->InitializeIndexSupport( pszNewName );
     346                 : 
     347                 : /* -------------------------------------------------------------------- */
     348                 : /*      Add layer to data source layer list.                            */
     349                 : /* -------------------------------------------------------------------- */
     350                 :     papoLayers = (OGRShapeLayer **)
     351             824 :         CPLRealloc( papoLayers,  sizeof(OGRShapeLayer *) * (nLayers+1) );
     352             824 :     papoLayers[nLayers++] = poLayer;
     353                 :     
     354             824 :     return TRUE;
     355                 : }
     356                 : 
     357                 : /************************************************************************/
     358                 : /*                            CreateLayer()                             */
     359                 : /************************************************************************/
     360                 : 
     361                 : OGRLayer *
     362              90 : OGRShapeDataSource::CreateLayer( const char * pszLayerName,
     363                 :                                  OGRSpatialReference *poSRS,
     364                 :                                  OGRwkbGeometryType eType,
     365                 :                                  char ** papszOptions )
     366                 : 
     367                 : {
     368                 :     SHPHandle   hSHP;
     369                 :     DBFHandle   hDBF;
     370                 :     int         nShapeType;
     371                 : 
     372                 : /* -------------------------------------------------------------------- */
     373                 : /*      Verify we are in update mode.                                   */
     374                 : /* -------------------------------------------------------------------- */
     375              90 :     if( !bDSUpdate )
     376                 :     {
     377                 :         CPLError( CE_Failure, CPLE_NoWriteAccess,
     378                 :                   "Data source %s opened read-only.\n"
     379                 :                   "New layer %s cannot be created.\n",
     380               0 :                   pszName, pszLayerName );
     381                 : 
     382               0 :         return NULL;
     383                 :     }
     384                 : 
     385                 : /* -------------------------------------------------------------------- */
     386                 : /*      Figure out what type of layer we need.                          */
     387                 : /* -------------------------------------------------------------------- */
     388             140 :     if( eType == wkbUnknown || eType == wkbLineString )
     389              50 :         nShapeType = SHPT_ARC;
     390              40 :     else if( eType == wkbPoint )
     391               2 :         nShapeType = SHPT_POINT;
     392              38 :     else if( eType == wkbPolygon )
     393              21 :         nShapeType = SHPT_POLYGON;
     394              17 :     else if( eType == wkbMultiPoint )
     395               2 :         nShapeType = SHPT_MULTIPOINT;
     396              15 :     else if( eType == wkbPoint25D )
     397               1 :         nShapeType = SHPT_POINTZ;
     398              14 :     else if( eType == wkbLineString25D )
     399               2 :         nShapeType = SHPT_ARCZ;
     400              12 :     else if( eType == wkbMultiLineString )
     401               2 :         nShapeType = SHPT_ARC;
     402              10 :     else if( eType == wkbMultiLineString25D )
     403               1 :         nShapeType = SHPT_ARCZ;
     404               9 :     else if( eType == wkbPolygon25D )
     405               2 :         nShapeType = SHPT_POLYGONZ;
     406               7 :     else if( eType == wkbMultiPolygon )
     407               3 :         nShapeType = SHPT_POLYGON;
     408               4 :     else if( eType == wkbMultiPolygon25D )
     409               1 :         nShapeType = SHPT_POLYGONZ;
     410               3 :     else if( eType == wkbMultiPoint25D )
     411               1 :         nShapeType = SHPT_MULTIPOINTZ;
     412               2 :     else if( eType == wkbNone )
     413               2 :         nShapeType = SHPT_NULL;
     414                 :     else
     415               0 :         nShapeType = -1;
     416                 : 
     417                 : /* -------------------------------------------------------------------- */
     418                 : /*      Has the application overridden this with a special creation     */
     419                 : /*      option?                                                         */
     420                 : /* -------------------------------------------------------------------- */
     421              90 :     const char *pszOverride = CSLFetchNameValue( papszOptions, "SHPT" );
     422                 : 
     423              90 :     if( pszOverride == NULL )
     424                 :         /* ignore */;
     425               1 :     else if( EQUAL(pszOverride,"POINT") )
     426                 :     {
     427               0 :         nShapeType = SHPT_POINT;
     428               0 :         eType = wkbPoint;
     429                 :     }
     430               1 :     else if( EQUAL(pszOverride,"ARC") )
     431                 :     {
     432               0 :         nShapeType = SHPT_ARC;
     433               0 :         eType = wkbLineString;
     434                 :     }
     435               1 :     else if( EQUAL(pszOverride,"POLYGON") )
     436                 :     {
     437               0 :         nShapeType = SHPT_POLYGON;
     438               0 :         eType = wkbPolygon;
     439                 :     }
     440               1 :     else if( EQUAL(pszOverride,"MULTIPOINT") )
     441                 :     {
     442               0 :         nShapeType = SHPT_MULTIPOINT;
     443               0 :         eType = wkbMultiPoint;
     444                 :     }
     445               1 :     else if( EQUAL(pszOverride,"POINTZ") )
     446                 :     {
     447               0 :         nShapeType = SHPT_POINTZ;
     448               0 :         eType = wkbPoint25D;
     449                 :     }
     450               1 :     else if( EQUAL(pszOverride,"ARCZ") )
     451                 :     {
     452               0 :         nShapeType = SHPT_ARCZ;
     453               0 :         eType = wkbLineString25D;
     454                 :     }
     455               1 :     else if( EQUAL(pszOverride,"POLYGONZ") )
     456                 :     {
     457               1 :         nShapeType = SHPT_POLYGONZ;
     458               1 :         eType = wkbPolygon25D;
     459                 :     }
     460               0 :     else if( EQUAL(pszOverride,"MULTIPOINTZ") )
     461                 :     {
     462               0 :         nShapeType = SHPT_MULTIPOINTZ;
     463               0 :         eType = wkbMultiPoint25D;
     464                 :     }
     465               0 :     else if( EQUAL(pszOverride,"NONE") )
     466                 :     {
     467               0 :         nShapeType = SHPT_NULL;
     468                 :     }
     469                 :     else
     470                 :     {
     471                 :         CPLError( CE_Failure, CPLE_NotSupported,
     472                 :                   "Unknown SHPT value of `%s' passed to Shapefile layer\n"
     473                 :                   "creation.  Creation aborted.\n",
     474               0 :                   pszOverride );
     475                 : 
     476               0 :         return NULL;
     477                 :     }
     478                 : 
     479              90 :     if( nShapeType == -1 )
     480                 :     {
     481                 :         CPLError( CE_Failure, CPLE_NotSupported,
     482                 :                   "Geometry type of `%s' not supported in shapefiles.\n"
     483                 :                   "Type can be overridden with a layer creation option\n"
     484                 :                   "of SHPT=POINT/ARC/POLYGON/MULTIPOINT/POINTZ/ARCZ/POLYGONZ/MULTIPOINTZ.\n",
     485               0 :                   OGRGeometryTypeToName(eType) );
     486               0 :         return NULL;
     487                 :     }
     488                 :     
     489                 : /* -------------------------------------------------------------------- */
     490                 : /*      What filename do we use, excluding the extension?               */
     491                 : /* -------------------------------------------------------------------- */
     492                 :     char *pszBasename;
     493                 : 
     494             119 :     if( bSingleNewFile && nLayers == 0 )
     495                 :     {
     496              29 :         char *pszPath = CPLStrdup(CPLGetPath(pszName));
     497              29 :         char *pszFBasename = CPLStrdup(CPLGetBasename(pszName));
     498                 : 
     499              29 :         pszBasename = CPLStrdup(CPLFormFilename(pszPath, pszFBasename, NULL));
     500                 : 
     501              29 :         CPLFree( pszFBasename );
     502              29 :         CPLFree( pszPath );
     503                 :     }
     504              61 :     else if( bSingleNewFile )
     505                 :     {
     506               0 :         char *pszPath = CPLStrdup(CPLGetPath(pszName));
     507               0 :         pszBasename = CPLStrdup(CPLFormFilename(pszPath,pszLayerName,NULL));
     508               0 :         CPLFree( pszPath );
     509                 :     }
     510                 :     else
     511              61 :         pszBasename = CPLStrdup(CPLFormFilename(pszName,pszLayerName,NULL));
     512                 : 
     513                 : /* -------------------------------------------------------------------- */
     514                 : /*      Create the shapefile.                                           */
     515                 : /* -------------------------------------------------------------------- */
     516                 :     char        *pszFilename;
     517                 : 
     518              90 :     if( nShapeType != SHPT_NULL )
     519                 :     {
     520              88 :         pszFilename = CPLStrdup(CPLFormFilename( NULL, pszBasename, "shp" ));
     521                 : 
     522              88 :         hSHP = SHPCreate( pszFilename, nShapeType );
     523                 :         
     524              88 :         if( hSHP == NULL )
     525                 :         {
     526                 :             CPLError( CE_Failure, CPLE_OpenFailed,
     527                 :                       "Failed to open Shapefile `%s'.\n",
     528               0 :                       pszFilename );
     529               0 :             CPLFree( pszFilename );
     530               0 :             CPLFree( pszBasename );
     531               0 :             return NULL;
     532                 :         }
     533              88 :         CPLFree( pszFilename );
     534                 :     }
     535                 :     else
     536               2 :         hSHP = NULL;
     537                 : 
     538                 : /* -------------------------------------------------------------------- */
     539                 : /*      Create a DBF file.                                              */
     540                 : /* -------------------------------------------------------------------- */
     541              90 :     pszFilename = CPLStrdup(CPLFormFilename( NULL, pszBasename, "dbf" ));
     542                 :     
     543              90 :     hDBF = DBFCreate( pszFilename );
     544                 : 
     545              90 :     if( hDBF == NULL )
     546                 :     {
     547                 :         CPLError( CE_Failure, CPLE_OpenFailed,
     548                 :                   "Failed to open Shape DBF file `%s'.\n",
     549               0 :                   pszFilename );
     550               0 :         CPLFree( pszFilename );
     551               0 :         CPLFree( pszBasename );
     552               0 :         return NULL;
     553                 :     }
     554                 : 
     555              90 :     CPLFree( pszFilename );
     556                 : 
     557                 : /* -------------------------------------------------------------------- */
     558                 : /*      Create the .prj file, if required.                              */
     559                 : /* -------------------------------------------------------------------- */
     560              90 :     if( poSRS != NULL )
     561                 :     {
     562              30 :         char    *pszWKT = NULL;
     563              30 :         CPLString osPrjFile = CPLFormFilename( NULL, pszBasename, "prj");
     564                 :         FILE    *fp;
     565                 : 
     566                 :         /* the shape layer needs it's own copy */
     567              30 :         poSRS = poSRS->Clone();
     568              30 :         poSRS->morphToESRI();
     569                 : 
     570              30 :         if( poSRS->exportToWkt( &pszWKT ) == OGRERR_NONE 
     571                 :             && (fp = VSIFOpen( osPrjFile, "wt" )) != NULL )
     572                 :         {
     573              30 :             VSIFWrite( pszWKT, strlen(pszWKT), 1, fp );
     574              30 :             VSIFClose( fp );
     575                 :         }
     576                 : 
     577              30 :         CPLFree( pszWKT );
     578                 : 
     579              30 :         poSRS->morphFromESRI();
     580                 :     }
     581                 : 
     582                 : /* -------------------------------------------------------------------- */
     583                 : /*      Create the layer object.                                        */
     584                 : /* -------------------------------------------------------------------- */
     585                 :     OGRShapeLayer       *poLayer;
     586                 : 
     587                 :     poLayer = new OGRShapeLayer( pszBasename, hSHP, hDBF, poSRS, TRUE,
     588              90 :                                  eType );
     589                 :     
     590              90 :     poLayer->InitializeIndexSupport( pszBasename );
     591                 : 
     592              90 :     CPLFree( pszBasename );
     593                 : 
     594                 : /* -------------------------------------------------------------------- */
     595                 : /*      Add layer to data source layer list.                            */
     596                 : /* -------------------------------------------------------------------- */
     597                 :     papoLayers = (OGRShapeLayer **)
     598              90 :         CPLRealloc( papoLayers,  sizeof(OGRShapeLayer *) * (nLayers+1) );
     599                 :     
     600              90 :     papoLayers[nLayers++] = poLayer;
     601                 : 
     602              90 :     return poLayer;
     603                 : }
     604                 : 
     605                 : /************************************************************************/
     606                 : /*                           TestCapability()                           */
     607                 : /************************************************************************/
     608                 : 
     609              19 : int OGRShapeDataSource::TestCapability( const char * pszCap )
     610                 : 
     611                 : {
     612              19 :     if( EQUAL(pszCap,ODsCCreateLayer) )
     613              19 :         return bDSUpdate;
     614               0 :     else if( EQUAL(pszCap,ODsCDeleteLayer) )
     615               0 :         return bDSUpdate;
     616                 :     else
     617               0 :         return FALSE;
     618                 : }
     619                 : 
     620                 : /************************************************************************/
     621                 : /*                              GetLayer()                              */
     622                 : /************************************************************************/
     623                 : 
     624           13856 : OGRLayer *OGRShapeDataSource::GetLayer( int iLayer )
     625                 : 
     626                 : {
     627           13856 :     if( iLayer < 0 || iLayer >= nLayers )
     628               0 :         return NULL;
     629                 :     else
     630           13856 :         return papoLayers[iLayer];
     631                 : }
     632                 : 
     633                 : /************************************************************************/
     634                 : /*                             ExecuteSQL()                             */
     635                 : /*                                                                      */
     636                 : /*      We override this to provide special handling of CREATE          */
     637                 : /*      SPATIAL INDEX commands.  Support forms are:                     */
     638                 : /*                                                                      */
     639                 : /*        CREATE SPATIAL INDEX ON layer_name [DEPTH n]                  */
     640                 : /*        DROP SPATIAL INDEX ON layer_name                              */
     641                 : /*        REPACK layer_name                                             */
     642                 : /************************************************************************/
     643                 : 
     644              45 : OGRLayer * OGRShapeDataSource::ExecuteSQL( const char *pszStatement,
     645                 :                                            OGRGeometry *poSpatialFilter,
     646                 :                                            const char *pszDialect )
     647                 : 
     648                 : {
     649                 : /* ==================================================================== */
     650                 : /*      Handle command to drop a spatial index.                         */
     651                 : /* ==================================================================== */
     652              45 :     if( EQUALN(pszStatement, "REPACK ", 7) )
     653                 :     {
     654                 :         OGRShapeLayer *poLayer = (OGRShapeLayer *) 
     655               3 :             GetLayerByName( pszStatement + 7 );
     656                 : 
     657               3 :         if( poLayer != NULL )
     658               3 :             poLayer->Repack();
     659                 :         else
     660                 :         {
     661                 :             CPLError( CE_Failure, CPLE_AppDefined, 
     662                 :                       "No such layer as '%s' in REPACK.", 
     663               0 :                       pszStatement + 7 );
     664                 :         }
     665               3 :         return NULL;
     666                 :     }
     667                 :     
     668                 : /* ==================================================================== */
     669                 : /*      Handle command to drop a spatial index.                         */
     670                 : /* ==================================================================== */
     671              42 :     if( EQUALN(pszStatement, "DROP SPATIAL INDEX ON ", 22) )
     672                 :     {
     673                 :         OGRShapeLayer *poLayer = (OGRShapeLayer *) 
     674               1 :             GetLayerByName( pszStatement + 22 );
     675                 : 
     676               1 :         if( poLayer != NULL )
     677               1 :             poLayer->DropSpatialIndex();
     678                 :         else
     679                 :         {
     680                 :             CPLError( CE_Failure, CPLE_AppDefined, 
     681                 :                       "No such layer as '%s' in DROP SPATIAL INDEX.", 
     682               0 :                       pszStatement + 19 );
     683                 :         }
     684               1 :         return NULL;
     685                 :     }
     686                 :     
     687                 : /* ==================================================================== */
     688                 : /*      Handle all comands except spatial index creation generically.   */
     689                 : /* ==================================================================== */
     690              41 :     if( !EQUALN(pszStatement,"CREATE SPATIAL INDEX ON ",24) )
     691                 :         return OGRDataSource::ExecuteSQL( pszStatement, poSpatialFilter, 
     692              38 :                                           pszDialect );
     693                 : 
     694                 : /* -------------------------------------------------------------------- */
     695                 : /*      Parse into keywords.                                            */
     696                 : /* -------------------------------------------------------------------- */
     697               3 :     char **papszTokens = CSLTokenizeString( pszStatement );
     698                 :     
     699              15 :     if( CSLCount(papszTokens) < 5
     700               3 :         || !EQUAL(papszTokens[0],"CREATE")
     701               3 :         || !EQUAL(papszTokens[1],"SPATIAL")
     702               3 :         || !EQUAL(papszTokens[2],"INDEX") 
     703               3 :         || !EQUAL(papszTokens[3],"ON") 
     704                 :         || CSLCount(papszTokens) > 7 
     705               0 :         || (CSLCount(papszTokens) == 7 && !EQUAL(papszTokens[5],"DEPTH")) )
     706                 :     {
     707               0 :         CSLDestroy( papszTokens );
     708                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     709                 :                   "Syntax error in CREATE SPATIAL INDEX command.\n"
     710                 :                   "Was '%s'\n"
     711                 :                   "Should be of form 'CREATE SPATIAL INDEX ON <table> [DEPTH <n>]'",
     712               0 :                   pszStatement );
     713               0 :         return NULL;
     714                 :     }
     715                 : 
     716                 : /* -------------------------------------------------------------------- */
     717                 : /*      Get depth if provided.                                          */
     718                 : /* -------------------------------------------------------------------- */
     719               3 :     int nDepth = 0;
     720               3 :     if( CSLCount(papszTokens) == 7 )
     721               0 :         nDepth = atoi(papszTokens[6]);
     722                 : 
     723                 : /* -------------------------------------------------------------------- */
     724                 : /*      What layer are we operating on.                                 */
     725                 : /* -------------------------------------------------------------------- */
     726               3 :     OGRShapeLayer *poLayer = (OGRShapeLayer *) GetLayerByName(papszTokens[4]);
     727               3 :     CSLDestroy( papszTokens );
     728                 : 
     729               3 :     if( poLayer == NULL )
     730                 :     {
     731                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     732                 :                   "Layer %s not recognised.", 
     733               0 :                   papszTokens[4] );
     734               0 :         return NULL;
     735                 :     }
     736                 : 
     737               3 :     poLayer->CreateSpatialIndex( nDepth );
     738               3 :     return NULL;
     739                 : }
     740                 : 
     741                 : 
     742                 : /************************************************************************/
     743                 : /*                            DeleteLayer()                             */
     744                 : /************************************************************************/
     745                 : 
     746               1 : OGRErr OGRShapeDataSource::DeleteLayer( int iLayer )
     747                 : 
     748                 : {
     749                 :     char *pszFilename;
     750                 : 
     751                 : /* -------------------------------------------------------------------- */
     752                 : /*      Verify we are in update mode.                                   */
     753                 : /* -------------------------------------------------------------------- */
     754               1 :     if( !bDSUpdate )
     755                 :     {
     756                 :         CPLError( CE_Failure, CPLE_NoWriteAccess,
     757                 :                   "Data source %s opened read-only.\n"
     758                 :                   "Layer %d cannot be deleted.\n",
     759               0 :                   pszName, iLayer );
     760                 : 
     761               0 :         return OGRERR_FAILURE;
     762                 :     }
     763                 : 
     764               1 :     if( iLayer < 0 || iLayer >= nLayers )
     765                 :     {
     766                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     767                 :                   "Layer %d not in legal range of 0 to %d.", 
     768               0 :                   iLayer, nLayers-1 );
     769               0 :         return OGRERR_FAILURE;
     770                 :     }
     771                 : 
     772               1 :     pszFilename = CPLStrdup(((OGRShapeLayer*) papoLayers[iLayer])->GetFullName());
     773                 : 
     774               1 :     delete papoLayers[iLayer];
     775                 : 
     776               2 :     while( iLayer < nLayers - 1 )
     777                 :     {
     778               0 :         papoLayers[iLayer] = papoLayers[iLayer+1];
     779               0 :         iLayer++;
     780                 :     }
     781                 : 
     782               1 :     nLayers--;
     783                 : 
     784               1 :     VSIUnlink( CPLResetExtension(pszFilename, "shp") );
     785               1 :     VSIUnlink( CPLResetExtension(pszFilename, "shx") );
     786               1 :     VSIUnlink( CPLResetExtension(pszFilename, "dbf") );
     787               1 :     VSIUnlink( CPLResetExtension(pszFilename, "prj") );
     788               1 :     VSIUnlink( CPLResetExtension(pszFilename, "qix") );
     789                 : 
     790               1 :     CPLFree( pszFilename );
     791                 : 
     792               1 :     return OGRERR_NONE;
     793                 : }

Generated by: LCOV version 1.7