OGRErr OGRShapeDataSource::DeleteLayer( int iLayer ) { char *pszFilename; /* -------------------------------------------------------------------- */ /* Verify we are in update mode. */ /* -------------------------------------------------------------------- */ if( !bDSUpdate ) { CPLError( CE_Failure, CPLE_NoWriteAccess, "Data source %s opened read-only.\n" "Layer %d cannot be deleted.\n", pszName, iLayer ); return OGRERR_FAILURE; } if( iLayer < 0 || iLayer >= nLayers ) { CPLError( CE_Failure, CPLE_AppDefined, "Layer %d not in legal range of 0 to %d.", iLayer, nLayers-1 ); return OGRERR_FAILURE; } OGRShapeLayer* poLayerToDelete = (OGRShapeLayer*) papoLayers[iLayer]; pszFilename = CPLStrdup(poLayerToDelete->GetFullName()); delete poLayerToDelete; while( iLayer < nLayers - 1 ) { papoLayers[iLayer] = papoLayers[iLayer+1]; iLayer++; } nLayers--; VSIUnlink( CPLResetExtension(pszFilename, "shp") ); VSIUnlink( CPLResetExtension(pszFilename, "shx") ); VSIUnlink( CPLResetExtension(pszFilename, "dbf") ); VSIUnlink( CPLResetExtension(pszFilename, "prj") ); VSIUnlink( CPLResetExtension(pszFilename, "qix") ); CPLFree( pszFilename ); return OGRERR_NONE; }
OGRLayer * OGRShapeDataSource::ExecuteSQL( const char *pszStatement, OGRGeometry *poSpatialFilter, const char *pszDialect ) { /* ==================================================================== */ /* Handle command to drop a spatial index. */ /* ==================================================================== */ if( EQUALN(pszStatement, "REPACK ", 7) ) { OGRShapeLayer *poLayer = (OGRShapeLayer *) GetLayerByName( pszStatement + 7 ); if( poLayer != NULL ) { if( poLayer->Repack() != OGRERR_NONE ) { CPLError( CE_Failure, CPLE_AppDefined, "REPACK of layer '%s' failed.", pszStatement + 7 ); } } else { CPLError( CE_Failure, CPLE_AppDefined, "No such layer as '%s' in REPACK.", pszStatement + 7 ); } return NULL; } /* ==================================================================== */ /* Handle command to shrink columns to their minimum size. */ /* ==================================================================== */ if( EQUALN(pszStatement, "RESIZE ", 7) ) { OGRShapeLayer *poLayer = (OGRShapeLayer *) GetLayerByName( pszStatement + 7 ); if( poLayer != NULL ) poLayer->ResizeDBF(); else { CPLError( CE_Failure, CPLE_AppDefined, "No such layer as '%s' in RESIZE.", pszStatement + 7 ); } return NULL; } /* ==================================================================== */ /* Handle command to recompute extent */ /* ==================================================================== */ if( EQUALN(pszStatement, "RECOMPUTE EXTENT ON ", 20) ) { OGRShapeLayer *poLayer = (OGRShapeLayer *) GetLayerByName( pszStatement + 20 ); if( poLayer != NULL ) poLayer->RecomputeExtent(); else { CPLError( CE_Failure, CPLE_AppDefined, "No such layer as '%s' in RECOMPUTE EXTENT.", pszStatement + 20 ); } return NULL; } /* ==================================================================== */ /* Handle command to drop a spatial index. */ /* ==================================================================== */ if( EQUALN(pszStatement, "DROP SPATIAL INDEX ON ", 22) ) { OGRShapeLayer *poLayer = (OGRShapeLayer *) GetLayerByName( pszStatement + 22 ); if( poLayer != NULL ) poLayer->DropSpatialIndex(); else { CPLError( CE_Failure, CPLE_AppDefined, "No such layer as '%s' in DROP SPATIAL INDEX.", pszStatement + 22 ); } return NULL; } /* ==================================================================== */ /* Handle all comands except spatial index creation generically. */ /* ==================================================================== */ if( !EQUALN(pszStatement,"CREATE SPATIAL INDEX ON ",24) ) { char **papszTokens = CSLTokenizeString( pszStatement ); if( CSLCount(papszTokens) >=4 && (EQUAL(papszTokens[0],"CREATE") || EQUAL(papszTokens[0],"DROP")) && EQUAL(papszTokens[1],"INDEX") && EQUAL(papszTokens[2],"ON") ) { OGRShapeLayer *poLayer = (OGRShapeLayer *) GetLayerByName(papszTokens[3]); if (poLayer != NULL) poLayer->InitializeIndexSupport( poLayer->GetFullName() ); } CSLDestroy( papszTokens ); return OGRDataSource::ExecuteSQL( pszStatement, poSpatialFilter, pszDialect ); } /* -------------------------------------------------------------------- */ /* Parse into keywords. */ /* -------------------------------------------------------------------- */ char **papszTokens = CSLTokenizeString( pszStatement ); if( CSLCount(papszTokens) < 5 || !EQUAL(papszTokens[0],"CREATE") || !EQUAL(papszTokens[1],"SPATIAL") || !EQUAL(papszTokens[2],"INDEX") || !EQUAL(papszTokens[3],"ON") || CSLCount(papszTokens) > 7 || (CSLCount(papszTokens) == 7 && !EQUAL(papszTokens[5],"DEPTH")) ) { CSLDestroy( papszTokens ); CPLError( CE_Failure, CPLE_AppDefined, "Syntax error in CREATE SPATIAL INDEX command.\n" "Was '%s'\n" "Should be of form 'CREATE SPATIAL INDEX ON <table> [DEPTH <n>]'", pszStatement ); return NULL; } /* -------------------------------------------------------------------- */ /* Get depth if provided. */ /* -------------------------------------------------------------------- */ int nDepth = 0; if( CSLCount(papszTokens) == 7 ) nDepth = atoi(papszTokens[6]); /* -------------------------------------------------------------------- */ /* What layer are we operating on. */ /* -------------------------------------------------------------------- */ OGRShapeLayer *poLayer = (OGRShapeLayer *) GetLayerByName(papszTokens[4]); if( poLayer == NULL ) { CPLError( CE_Failure, CPLE_AppDefined, "Layer %s not recognised.", papszTokens[4] ); CSLDestroy( papszTokens ); return NULL; } CSLDestroy( papszTokens ); poLayer->CreateSpatialIndex( nDepth ); return NULL; }
OGRLayer * OGRShapeDataSource::ICreateLayer( const char * pszLayerName, OGRSpatialReference *poSRS, OGRwkbGeometryType eType, char ** papszOptions ) { SHPHandle hSHP; DBFHandle hDBF; int nShapeType; /* To ensure that existing layers are created */ GetLayerCount(); /* -------------------------------------------------------------------- */ /* Check that the layer doesn't already exist. */ /* -------------------------------------------------------------------- */ if (GetLayerByName(pszLayerName) != NULL) { CPLError( CE_Failure, CPLE_AppDefined, "Layer '%s' already exists", pszLayerName); return NULL; } /* -------------------------------------------------------------------- */ /* Verify we are in update mode. */ /* -------------------------------------------------------------------- */ if( !bDSUpdate ) { CPLError( CE_Failure, CPLE_NoWriteAccess, "Data source %s opened read-only.\n" "New layer %s cannot be created.\n", pszName, pszLayerName ); return NULL; } /* -------------------------------------------------------------------- */ /* Figure out what type of layer we need. */ /* -------------------------------------------------------------------- */ if( eType == wkbUnknown || eType == wkbLineString ) nShapeType = SHPT_ARC; else if( eType == wkbPoint ) nShapeType = SHPT_POINT; else if( eType == wkbPolygon ) nShapeType = SHPT_POLYGON; else if( eType == wkbMultiPoint ) nShapeType = SHPT_MULTIPOINT; else if( eType == wkbPoint25D ) nShapeType = SHPT_POINTZ; else if( eType == wkbLineString25D ) nShapeType = SHPT_ARCZ; else if( eType == wkbMultiLineString ) nShapeType = SHPT_ARC; else if( eType == wkbMultiLineString25D ) nShapeType = SHPT_ARCZ; else if( eType == wkbPolygon25D ) nShapeType = SHPT_POLYGONZ; else if( eType == wkbMultiPolygon ) nShapeType = SHPT_POLYGON; else if( eType == wkbMultiPolygon25D ) nShapeType = SHPT_POLYGONZ; else if( eType == wkbMultiPoint25D ) nShapeType = SHPT_MULTIPOINTZ; else if( eType == wkbNone ) nShapeType = SHPT_NULL; else nShapeType = -1; /* -------------------------------------------------------------------- */ /* Has the application overridden this with a special creation */ /* option? */ /* -------------------------------------------------------------------- */ const char *pszOverride = CSLFetchNameValue( papszOptions, "SHPT" ); if( pszOverride == NULL ) /* ignore */; else if( EQUAL(pszOverride,"POINT") ) { nShapeType = SHPT_POINT; eType = wkbPoint; } else if( EQUAL(pszOverride,"ARC") ) { nShapeType = SHPT_ARC; eType = wkbLineString; } else if( EQUAL(pszOverride,"POLYGON") ) { nShapeType = SHPT_POLYGON; eType = wkbPolygon; } else if( EQUAL(pszOverride,"MULTIPOINT") ) { nShapeType = SHPT_MULTIPOINT; eType = wkbMultiPoint; } else if( EQUAL(pszOverride,"POINTZ") ) { nShapeType = SHPT_POINTZ; eType = wkbPoint25D; } else if( EQUAL(pszOverride,"ARCZ") ) { nShapeType = SHPT_ARCZ; eType = wkbLineString25D; } else if( EQUAL(pszOverride,"POLYGONZ") ) { nShapeType = SHPT_POLYGONZ; eType = wkbPolygon25D; } else if( EQUAL(pszOverride,"MULTIPOINTZ") ) { nShapeType = SHPT_MULTIPOINTZ; eType = wkbMultiPoint25D; } else if( EQUAL(pszOverride,"NONE") || EQUAL(pszOverride,"NULL") ) { nShapeType = SHPT_NULL; eType = wkbNone; } else { CPLError( CE_Failure, CPLE_NotSupported, "Unknown SHPT value of `%s' passed to Shapefile layer\n" "creation. Creation aborted.\n", pszOverride ); return NULL; } if( nShapeType == -1 ) { CPLError( CE_Failure, CPLE_NotSupported, "Geometry type of `%s' not supported in shapefiles.\n" "Type can be overridden with a layer creation option\n" "of SHPT=POINT/ARC/POLYGON/MULTIPOINT/POINTZ/ARCZ/POLYGONZ/MULTIPOINTZ.\n", OGRGeometryTypeToName(eType) ); return NULL; } /* -------------------------------------------------------------------- */ /* What filename do we use, excluding the extension? */ /* -------------------------------------------------------------------- */ char *pszFilenameWithoutExt; if( bSingleFileDataSource && nLayers == 0 ) { char *pszPath = CPLStrdup(CPLGetPath(pszName)); char *pszFBasename = CPLStrdup(CPLGetBasename(pszName)); pszFilenameWithoutExt = CPLStrdup(CPLFormFilename(pszPath, pszFBasename, NULL)); CPLFree( pszFBasename ); CPLFree( pszPath ); } else if( bSingleFileDataSource ) { /* This is a very weird use case : the user creates/open a datasource */ /* made of a single shapefile 'foo.shp' and wants to add a new layer */ /* to it, 'bar'. So we create a new shapefile 'bar.shp' in the same */ /* directory as 'foo.shp' */ /* So technically, we will not be any longer a single file */ /* datasource ... Ahem ahem */ char *pszPath = CPLStrdup(CPLGetPath(pszName)); pszFilenameWithoutExt = CPLStrdup(CPLFormFilename(pszPath,pszLayerName,NULL)); CPLFree( pszPath ); } else pszFilenameWithoutExt = CPLStrdup(CPLFormFilename(pszName,pszLayerName,NULL)); /* -------------------------------------------------------------------- */ /* Create the shapefile. */ /* -------------------------------------------------------------------- */ char *pszFilename; int b2GBLimit = CSLTestBoolean(CSLFetchNameValueDef( papszOptions, "2GB_LIMIT", "FALSE" )); if( nShapeType != SHPT_NULL ) { pszFilename = CPLStrdup(CPLFormFilename( NULL, pszFilenameWithoutExt, "shp" )); hSHP = SHPCreateLL( pszFilename, nShapeType, (SAHooks*) VSI_SHP_GetHook(b2GBLimit) ); if( hSHP == NULL ) { CPLError( CE_Failure, CPLE_OpenFailed, "Failed to open Shapefile `%s'.\n", pszFilename ); CPLFree( pszFilename ); CPLFree( pszFilenameWithoutExt ); return NULL; } SHPSetFastModeReadObject( hSHP, TRUE ); CPLFree( pszFilename ); } else hSHP = NULL; /* -------------------------------------------------------------------- */ /* Has a specific LDID been specified by the caller? */ /* -------------------------------------------------------------------- */ const char *pszLDID = CSLFetchNameValue( papszOptions, "ENCODING" ); /* -------------------------------------------------------------------- */ /* Create a DBF file. */ /* -------------------------------------------------------------------- */ pszFilename = CPLStrdup(CPLFormFilename( NULL, pszFilenameWithoutExt, "dbf" )); if( pszLDID != NULL ) hDBF = DBFCreateLL( pszFilename, pszLDID, (SAHooks*) VSI_SHP_GetHook(b2GBLimit) ); else hDBF = DBFCreateLL( pszFilename, "LDID/87",(SAHooks*) VSI_SHP_GetHook(b2GBLimit) ); if( hDBF == NULL ) { CPLError( CE_Failure, CPLE_OpenFailed, "Failed to open Shape DBF file `%s'.\n", pszFilename ); CPLFree( pszFilename ); CPLFree( pszFilenameWithoutExt ); SHPClose(hSHP); return NULL; } CPLFree( pszFilename ); /* -------------------------------------------------------------------- */ /* Create the .prj file, if required. */ /* -------------------------------------------------------------------- */ if( poSRS != NULL ) { char *pszWKT = NULL; CPLString osPrjFile = CPLFormFilename( NULL, pszFilenameWithoutExt, "prj"); VSILFILE *fp; /* the shape layer needs it's own copy */ poSRS = poSRS->Clone(); poSRS->morphToESRI(); if( poSRS->exportToWkt( &pszWKT ) == OGRERR_NONE && (fp = VSIFOpenL( osPrjFile, "wt" )) != NULL ) { VSIFWriteL( pszWKT, strlen(pszWKT), 1, fp ); VSIFCloseL( fp ); } CPLFree( pszWKT ); poSRS->morphFromESRI(); } /* -------------------------------------------------------------------- */ /* Create the layer object. */ /* -------------------------------------------------------------------- */ OGRShapeLayer *poLayer; /* OGRShapeLayer constructor expects a filename with an extension (that could be */ /* random actually), otherwise this is going to cause problems with layer */ /* names that have a dot (not speaking about the one before the shp) */ pszFilename = CPLStrdup(CPLFormFilename( NULL, pszFilenameWithoutExt, "shp" )); poLayer = new OGRShapeLayer( this, pszFilename, hSHP, hDBF, poSRS, TRUE, TRUE, eType ); CPLFree( pszFilenameWithoutExt ); CPLFree( pszFilename ); poLayer->SetResizeAtClose( CSLFetchBoolean( papszOptions, "RESIZE", FALSE ) ); poLayer->CreateSpatialIndexAtClose( CSLFetchBoolean( papszOptions, "SPATIAL_INDEX", FALSE ) ); poLayer->SetModificationDate( CSLFetchNameValue( papszOptions, "DBF_DATE_LAST_UPDATE" ) ); /* -------------------------------------------------------------------- */ /* Add layer to data source layer list. */ /* -------------------------------------------------------------------- */ AddLayer(poLayer); return poLayer; }
int OGRShapeDataSource::OpenFile( const char *pszNewName, int bUpdate, int bTestOpen ) { SHPHandle hSHP; DBFHandle hDBF; const char *pszExtension = CPLGetExtension( pszNewName ); (void) bTestOpen; if( !EQUAL(pszExtension,"shp") && !EQUAL(pszExtension,"shx") && !EQUAL(pszExtension,"dbf") ) return FALSE; /* -------------------------------------------------------------------- */ /* SHPOpen() should include better (CPL based) error reporting, */ /* and we should be trying to distinquish at this point whether */ /* failure is a result of trying to open a non-shapefile, or */ /* whether it was a shapefile and we want to report the error */ /* up. */ /* */ /* Care is taken to suppress the error and only reissue it if */ /* we think it is appropriate. */ /* -------------------------------------------------------------------- */ CPLPushErrorHandler( CPLQuietErrorHandler ); if( bUpdate ) hSHP = DS_SHPOpen( pszNewName, "r+" ); else hSHP = DS_SHPOpen( pszNewName, "r" ); CPLPopErrorHandler(); if( hSHP == NULL && (!EQUAL(CPLGetExtension(pszNewName),"dbf") || strstr(CPLGetLastErrorMsg(),".shp") == NULL) ) { CPLString osMsg = CPLGetLastErrorMsg(); CPLError( CE_Failure, CPLE_OpenFailed, "%s", osMsg.c_str() ); return FALSE; } CPLErrorReset(); /* -------------------------------------------------------------------- */ /* Open the .dbf file, if it exists. To open a dbf file, the */ /* filename has to either refer to a successfully opened shp */ /* file or has to refer to the actual .dbf file. */ /* -------------------------------------------------------------------- */ if( hSHP != NULL || EQUAL(CPLGetExtension(pszNewName),"dbf") ) { if( bUpdate ) { hDBF = DS_DBFOpen( pszNewName, "r+" ); if( hSHP != NULL && hDBF == NULL ) { for(int i=0;i<2;i++) { VSIStatBufL sStat; const char* pszDBFName = CPLResetExtension(pszNewName, (i == 0 ) ? "dbf" : "DBF"); VSILFILE* fp = NULL; if( VSIStatExL( pszDBFName, &sStat, VSI_STAT_EXISTS_FLAG) == 0 ) { fp = VSIFOpenL(pszDBFName, "r+"); if (fp == NULL) { CPLError( CE_Failure, CPLE_OpenFailed, "%s exists, but cannot be opened in update mode", pszDBFName ); SHPClose(hSHP); return FALSE; } VSIFCloseL(fp); break; } } } } else hDBF = DS_DBFOpen( pszNewName, "r" ); } else hDBF = NULL; if( hDBF == NULL && hSHP == NULL ) return FALSE; /* -------------------------------------------------------------------- */ /* Create the layer object. */ /* -------------------------------------------------------------------- */ OGRShapeLayer *poLayer; poLayer = new OGRShapeLayer( this, pszNewName, hSHP, hDBF, NULL, FALSE, bUpdate, wkbNone ); poLayer->SetModificationDate( CSLFetchNameValue( papszOpenOptions, "DBF_DATE_LAST_UPDATE" ) ); /* -------------------------------------------------------------------- */ /* Add layer to data source layer list. */ /* -------------------------------------------------------------------- */ AddLayer(poLayer); return TRUE; }
OGRLayer * OGRShapeDataSource::ExecuteSQL( const char *pszStatement, OGRGeometry *poSpatialFilter, const char *pszDialect ) { /* ==================================================================== */ /* Handle command to drop a spatial index. */ /* ==================================================================== */ if( EQUALN(pszStatement, "REPACK ", 7) ) { OGRShapeLayer *poLayer = (OGRShapeLayer *) GetLayerByName( pszStatement + 7 ); if( poLayer != NULL ) poLayer->Repack(); else { CPLError( CE_Failure, CPLE_AppDefined, "No such layer as '%s' in REPACK.", pszStatement + 7 ); } return NULL; } /* ==================================================================== */ /* Handle command to drop a spatial index. */ /* ==================================================================== */ if( EQUALN(pszStatement, "DROP SPATIAL INDEX ON ", 22) ) { OGRShapeLayer *poLayer = (OGRShapeLayer *) GetLayerByName( pszStatement + 22 ); if( poLayer != NULL ) poLayer->DropSpatialIndex(); else { CPLError( CE_Failure, CPLE_AppDefined, "No such layer as '%s' in DROP SPATIAL INDEX.", pszStatement + 19 ); } return NULL; } /* ==================================================================== */ /* Handle all comands except spatial index creation generically. */ /* ==================================================================== */ if( !EQUALN(pszStatement,"CREATE SPATIAL INDEX ON ",24) ) return OGRDataSource::ExecuteSQL( pszStatement, poSpatialFilter, pszDialect ); /* -------------------------------------------------------------------- */ /* Parse into keywords. */ /* -------------------------------------------------------------------- */ char **papszTokens = CSLTokenizeString( pszStatement ); if( CSLCount(papszTokens) < 5 || !EQUAL(papszTokens[0],"CREATE") || !EQUAL(papszTokens[1],"SPATIAL") || !EQUAL(papszTokens[2],"INDEX") || !EQUAL(papszTokens[3],"ON") || CSLCount(papszTokens) > 7 || (CSLCount(papszTokens) == 7 && !EQUAL(papszTokens[5],"DEPTH")) ) { CSLDestroy( papszTokens ); CPLError( CE_Failure, CPLE_AppDefined, "Syntax error in CREATE SPATIAL INDEX command.\n" "Was '%s'\n" "Should be of form 'CREATE SPATIAL INDEX ON <table> [DEPTH <n>]'", pszStatement ); return NULL; } /* -------------------------------------------------------------------- */ /* Get depth if provided. */ /* -------------------------------------------------------------------- */ int nDepth = 0; if( CSLCount(papszTokens) == 7 ) nDepth = atoi(papszTokens[6]); /* -------------------------------------------------------------------- */ /* What layer are we operating on. */ /* -------------------------------------------------------------------- */ OGRShapeLayer *poLayer = (OGRShapeLayer *) GetLayerByName(papszTokens[4]); CSLDestroy( papszTokens ); if( poLayer == NULL ) { CPLError( CE_Failure, CPLE_AppDefined, "Layer %s not recognised.", papszTokens[4] ); return NULL; } poLayer->CreateSpatialIndex( nDepth ); return NULL; }
OGRLayer * OGRShapeDataSource::CreateLayer( const char * pszLayerName, OGRSpatialReference *poSRS, OGRwkbGeometryType eType, char ** papszOptions ) { SHPHandle hSHP; DBFHandle hDBF; int nShapeType; /* -------------------------------------------------------------------- */ /* Verify we are in update mode. */ /* -------------------------------------------------------------------- */ if( !bDSUpdate ) { CPLError( CE_Failure, CPLE_NoWriteAccess, "Data source %s opened read-only.\n" "New layer %s cannot be created.\n", pszName, pszLayerName ); return NULL; } /* -------------------------------------------------------------------- */ /* Figure out what type of layer we need. */ /* -------------------------------------------------------------------- */ if( eType == wkbUnknown || eType == wkbLineString ) nShapeType = SHPT_ARC; else if( eType == wkbPoint ) nShapeType = SHPT_POINT; else if( eType == wkbPolygon ) nShapeType = SHPT_POLYGON; else if( eType == wkbMultiPoint ) nShapeType = SHPT_MULTIPOINT; else if( eType == wkbPoint25D ) nShapeType = SHPT_POINTZ; else if( eType == wkbLineString25D ) nShapeType = SHPT_ARCZ; else if( eType == wkbMultiLineString ) nShapeType = SHPT_ARC; else if( eType == wkbMultiLineString25D ) nShapeType = SHPT_ARCZ; else if( eType == wkbPolygon25D ) nShapeType = SHPT_POLYGONZ; else if( eType == wkbMultiPolygon ) nShapeType = SHPT_POLYGON; else if( eType == wkbMultiPolygon25D ) nShapeType = SHPT_POLYGONZ; else if( eType == wkbMultiPoint25D ) nShapeType = SHPT_MULTIPOINTZ; else if( eType == wkbNone ) nShapeType = SHPT_NULL; else nShapeType = -1; /* -------------------------------------------------------------------- */ /* Has the application overridden this with a special creation */ /* option? */ /* -------------------------------------------------------------------- */ const char *pszOverride = CSLFetchNameValue( papszOptions, "SHPT" ); if( pszOverride == NULL ) /* ignore */; else if( EQUAL(pszOverride,"POINT") ) { nShapeType = SHPT_POINT; eType = wkbPoint; } else if( EQUAL(pszOverride,"ARC") ) { nShapeType = SHPT_ARC; eType = wkbLineString; } else if( EQUAL(pszOverride,"POLYGON") ) { nShapeType = SHPT_POLYGON; eType = wkbPolygon; } else if( EQUAL(pszOverride,"MULTIPOINT") ) { nShapeType = SHPT_MULTIPOINT; eType = wkbMultiPoint; } else if( EQUAL(pszOverride,"POINTZ") ) { nShapeType = SHPT_POINTZ; eType = wkbPoint25D; } else if( EQUAL(pszOverride,"ARCZ") ) { nShapeType = SHPT_ARCZ; eType = wkbLineString25D; } else if( EQUAL(pszOverride,"POLYGONZ") ) { nShapeType = SHPT_POLYGONZ; eType = wkbPolygon25D; } else if( EQUAL(pszOverride,"MULTIPOINTZ") ) { nShapeType = SHPT_MULTIPOINTZ; eType = wkbMultiPoint25D; } else if( EQUAL(pszOverride,"NONE") ) { nShapeType = SHPT_NULL; } else { CPLError( CE_Failure, CPLE_NotSupported, "Unknown SHPT value of `%s' passed to Shapefile layer\n" "creation. Creation aborted.\n", pszOverride ); return NULL; } if( nShapeType == -1 ) { CPLError( CE_Failure, CPLE_NotSupported, "Geometry type of `%s' not supported in shapefiles.\n" "Type can be overridden with a layer creation option\n" "of SHPT=POINT/ARC/POLYGON/MULTIPOINT/POINTZ/ARCZ/POLYGONZ/MULTIPOINTZ.\n", OGRGeometryTypeToName(eType) ); return NULL; } /* -------------------------------------------------------------------- */ /* What filename do we use, excluding the extension? */ /* -------------------------------------------------------------------- */ char *pszBasename; if( bSingleNewFile && nLayers == 0 ) { char *pszPath = CPLStrdup(CPLGetPath(pszName)); char *pszFBasename = CPLStrdup(CPLGetBasename(pszName)); pszBasename = CPLStrdup(CPLFormFilename(pszPath, pszFBasename, NULL)); CPLFree( pszFBasename ); CPLFree( pszPath ); } else if( bSingleNewFile ) { char *pszPath = CPLStrdup(CPLGetPath(pszName)); pszBasename = CPLStrdup(CPLFormFilename(pszPath,pszLayerName,NULL)); CPLFree( pszPath ); } else pszBasename = CPLStrdup(CPLFormFilename(pszName,pszLayerName,NULL)); /* -------------------------------------------------------------------- */ /* Create the shapefile. */ /* -------------------------------------------------------------------- */ char *pszFilename; if( nShapeType != SHPT_NULL ) { pszFilename = CPLStrdup(CPLFormFilename( NULL, pszBasename, "shp" )); hSHP = SHPCreate( pszFilename, nShapeType ); if( hSHP == NULL ) { CPLError( CE_Failure, CPLE_OpenFailed, "Failed to open Shapefile `%s'.\n", pszFilename ); CPLFree( pszFilename ); CPLFree( pszBasename ); return NULL; } CPLFree( pszFilename ); } else hSHP = NULL; /* -------------------------------------------------------------------- */ /* Create a DBF file. */ /* -------------------------------------------------------------------- */ pszFilename = CPLStrdup(CPLFormFilename( NULL, pszBasename, "dbf" )); hDBF = DBFCreate( pszFilename ); if( hDBF == NULL ) { CPLError( CE_Failure, CPLE_OpenFailed, "Failed to open Shape DBF file `%s'.\n", pszFilename ); CPLFree( pszFilename ); CPLFree( pszBasename ); return NULL; } CPLFree( pszFilename ); /* -------------------------------------------------------------------- */ /* Create the .prj file, if required. */ /* -------------------------------------------------------------------- */ if( poSRS != NULL ) { char *pszWKT = NULL; CPLString osPrjFile = CPLFormFilename( NULL, pszBasename, "prj"); FILE *fp; /* the shape layer needs it's own copy */ poSRS = poSRS->Clone(); poSRS->morphToESRI(); if( poSRS->exportToWkt( &pszWKT ) == OGRERR_NONE && (fp = VSIFOpen( osPrjFile, "wt" )) != NULL ) { VSIFWrite( pszWKT, strlen(pszWKT), 1, fp ); VSIFClose( fp ); } CPLFree( pszWKT ); poSRS->morphFromESRI(); } /* -------------------------------------------------------------------- */ /* Create the layer object. */ /* -------------------------------------------------------------------- */ OGRShapeLayer *poLayer; poLayer = new OGRShapeLayer( pszBasename, hSHP, hDBF, poSRS, TRUE, eType ); poLayer->InitializeIndexSupport( pszBasename ); CPLFree( pszBasename ); /* -------------------------------------------------------------------- */ /* Add layer to data source layer list. */ /* -------------------------------------------------------------------- */ papoLayers = (OGRShapeLayer **) CPLRealloc( papoLayers, sizeof(OGRShapeLayer *) * (nLayers+1) ); papoLayers[nLayers++] = poLayer; return poLayer; }
int OGRShapeDataSource::OpenFile( const char *pszNewName, int bUpdate, int bTestOpen ) { SHPHandle hSHP; DBFHandle hDBF; const char *pszExtension = CPLGetExtension( pszNewName ); (void) bTestOpen; if( !EQUAL(pszExtension,"shp") && !EQUAL(pszExtension,"shx") && !EQUAL(pszExtension,"dbf") ) return FALSE; /* -------------------------------------------------------------------- */ /* SHPOpen() should include better (CPL based) error reporting, */ /* and we should be trying to distinquish at this point whether */ /* failure is a result of trying to open a non-shapefile, or */ /* whether it was a shapefile and we want to report the error */ /* up. */ /* */ /* Care is taken to suppress the error and only reissue it if */ /* we think it is appropriate. */ /* -------------------------------------------------------------------- */ CPLPushErrorHandler( CPLQuietErrorHandler ); if( bUpdate ) hSHP = SHPOpen( pszNewName, "r+" ); else hSHP = SHPOpen( pszNewName, "r" ); CPLPopErrorHandler(); if( hSHP == NULL && (!EQUAL(CPLGetExtension(pszNewName),"dbf") || strstr(CPLGetLastErrorMsg(),".shp") == NULL) ) { CPLString osMsg = CPLGetLastErrorMsg(); CPLError( CE_Failure, CPLE_OpenFailed, "%s", osMsg.c_str() ); return FALSE; } CPLErrorReset(); /* -------------------------------------------------------------------- */ /* Open the .dbf file, if it exists. To open a dbf file, the */ /* filename has to either refer to a successfully opened shp */ /* file or has to refer to the actual .dbf file. */ /* -------------------------------------------------------------------- */ if( hSHP != NULL || EQUAL(CPLGetExtension(pszNewName),"dbf") ) { if( bUpdate ) hDBF = DBFOpen( pszNewName, "r+" ); else hDBF = DBFOpen( pszNewName, "r" ); } else hDBF = NULL; if( hDBF == NULL && hSHP == NULL ) return FALSE; /* -------------------------------------------------------------------- */ /* Is there an associated .prj file we can read? */ /* -------------------------------------------------------------------- */ OGRSpatialReference *poSRS = NULL; const char *pszPrjFile = CPLResetExtension( pszNewName, "prj" ); FILE *fp = NULL; fp = VSIFOpenL( pszPrjFile, "r" ); #ifndef WIN32 if( NULL == fp ) { pszPrjFile = CPLResetExtension( pszNewName, "PRJ" ); fp = VSIFOpenL( pszPrjFile, "r" ); } #endif if( fp != NULL ) { char **papszLines; VSIFCloseL( fp ); papszLines = CSLLoad( pszPrjFile ); poSRS = new OGRSpatialReference(); if( poSRS->importFromESRI( papszLines ) != OGRERR_NONE ) { delete poSRS; poSRS = NULL; } CSLDestroy( papszLines ); } /* -------------------------------------------------------------------- */ /* Create the layer object. */ /* -------------------------------------------------------------------- */ OGRShapeLayer *poLayer; poLayer = new OGRShapeLayer( pszNewName, hSHP, hDBF, poSRS, bUpdate, wkbNone ); poLayer->InitializeIndexSupport( pszNewName ); /* -------------------------------------------------------------------- */ /* Add layer to data source layer list. */ /* -------------------------------------------------------------------- */ papoLayers = (OGRShapeLayer **) CPLRealloc( papoLayers, sizeof(OGRShapeLayer *) * (nLayers+1) ); papoLayers[nLayers++] = poLayer; return TRUE; }
OGRLayer * OGRShapeDataSource::CreateLayer( const char * pszLayerName, OGRSpatialReference *poSRS, OGRwkbGeometryType eType, char ** papszOptions ) { SHPHandle hSHP; DBFHandle hDBF; int nShapeType; int iLayer; /* -------------------------------------------------------------------- */ /* Check that the layer doesn't already exist. */ /* -------------------------------------------------------------------- */ for( iLayer = 0; iLayer < nLayers; iLayer++ ) { OGRLayer *poLayer = papoLayers[iLayer]; if( poLayer != NULL && EQUAL(poLayer->GetLayerDefn()->GetName(),pszLayerName) ) { CPLError( CE_Failure, CPLE_AppDefined, "Layer '%s' already exists", pszLayerName); return NULL; } } /* -------------------------------------------------------------------- */ /* Verify we are in update mode. */ /* -------------------------------------------------------------------- */ if( !bDSUpdate ) { CPLError( CE_Failure, CPLE_NoWriteAccess, "Data source %s opened read-only.\n" "New layer %s cannot be created.\n", pszName, pszLayerName ); return NULL; } /* -------------------------------------------------------------------- */ /* Figure out what type of layer we need. */ /* -------------------------------------------------------------------- */ if( eType == wkbUnknown || eType == wkbLineString ) nShapeType = SHPT_ARC; else if( eType == wkbPoint ) nShapeType = SHPT_POINT; else if( eType == wkbPolygon ) nShapeType = SHPT_POLYGON; else if( eType == wkbMultiPoint ) nShapeType = SHPT_MULTIPOINT; else if( eType == wkbPoint25D ) nShapeType = SHPT_POINTZ; else if( eType == wkbLineString25D ) nShapeType = SHPT_ARCZ; else if( eType == wkbMultiLineString ) nShapeType = SHPT_ARC; else if( eType == wkbMultiLineString25D ) nShapeType = SHPT_ARCZ; else if( eType == wkbPolygon25D ) nShapeType = SHPT_POLYGONZ; else if( eType == wkbMultiPolygon ) nShapeType = SHPT_POLYGON; else if( eType == wkbMultiPolygon25D ) nShapeType = SHPT_POLYGONZ; else if( eType == wkbMultiPoint25D ) nShapeType = SHPT_MULTIPOINTZ; else if( eType == wkbNone ) nShapeType = SHPT_NULL; else nShapeType = -1; /* -------------------------------------------------------------------- */ /* Has the application overridden this with a special creation */ /* option? */ /* -------------------------------------------------------------------- */ const char *pszOverride = CSLFetchNameValue( papszOptions, "SHPT" ); if( pszOverride == NULL ) /* ignore */; else if( EQUAL(pszOverride,"POINT") ) { nShapeType = SHPT_POINT; eType = wkbPoint; } else if( EQUAL(pszOverride,"ARC") ) { nShapeType = SHPT_ARC; eType = wkbLineString; } else if( EQUAL(pszOverride,"POLYGON") ) { nShapeType = SHPT_POLYGON; eType = wkbPolygon; } else if( EQUAL(pszOverride,"MULTIPOINT") ) { nShapeType = SHPT_MULTIPOINT; eType = wkbMultiPoint; } else if( EQUAL(pszOverride,"POINTZ") ) { nShapeType = SHPT_POINTZ; eType = wkbPoint25D; } else if( EQUAL(pszOverride,"ARCZ") ) { nShapeType = SHPT_ARCZ; eType = wkbLineString25D; } else if( EQUAL(pszOverride,"POLYGONZ") ) { nShapeType = SHPT_POLYGONZ; eType = wkbPolygon25D; } else if( EQUAL(pszOverride,"MULTIPOINTZ") ) { nShapeType = SHPT_MULTIPOINTZ; eType = wkbMultiPoint25D; } else if( EQUAL(pszOverride,"NONE") ) { nShapeType = SHPT_NULL; } else { CPLError( CE_Failure, CPLE_NotSupported, "Unknown SHPT value of `%s' passed to Shapefile layer\n" "creation. Creation aborted.\n", pszOverride ); return NULL; } if( nShapeType == -1 ) { CPLError( CE_Failure, CPLE_NotSupported, "Geometry type of `%s' not supported in shapefiles.\n" "Type can be overridden with a layer creation option\n" "of SHPT=POINT/ARC/POLYGON/MULTIPOINT/POINTZ/ARCZ/POLYGONZ/MULTIPOINTZ.\n", OGRGeometryTypeToName(eType) ); return NULL; } /* -------------------------------------------------------------------- */ /* What filename do we use, excluding the extension? */ /* -------------------------------------------------------------------- */ char *pszBasename; if( bSingleFileDataSource && nLayers == 0 ) { char *pszPath = CPLStrdup(CPLGetPath(pszName)); char *pszFBasename = CPLStrdup(CPLGetBasename(pszName)); pszBasename = CPLStrdup(CPLFormFilename(pszPath, pszFBasename, NULL)); CPLFree( pszFBasename ); CPLFree( pszPath ); } else if( bSingleFileDataSource ) { /* This is a very weird use case : the user creates/open a datasource */ /* made of a single shapefile 'foo.shp' and wants to add a new layer */ /* to it, 'bar'. So we create a new shapefile 'bar.shp' in the same */ /* directory as 'foo.shp' */ /* So technically, we will not be any longer a single file */ /* datasource ... Ahem ahem */ char *pszPath = CPLStrdup(CPLGetPath(pszName)); pszBasename = CPLStrdup(CPLFormFilename(pszPath,pszLayerName,NULL)); CPLFree( pszPath ); } else pszBasename = CPLStrdup(CPLFormFilename(pszName,pszLayerName,NULL)); /* -------------------------------------------------------------------- */ /* Create the shapefile. */ /* -------------------------------------------------------------------- */ char *pszFilename; if( nShapeType != SHPT_NULL ) { pszFilename = CPLStrdup(CPLFormFilename( NULL, pszBasename, "shp" )); hSHP = SHPCreate( pszFilename, nShapeType ); if( hSHP == NULL ) { CPLError( CE_Failure, CPLE_OpenFailed, "Failed to open Shapefile `%s'.\n", pszFilename ); CPLFree( pszFilename ); CPLFree( pszBasename ); return NULL; } CPLFree( pszFilename ); } else hSHP = NULL; /* -------------------------------------------------------------------- */ /* Has a specific LDID been specified by the caller? */ /* -------------------------------------------------------------------- */ const char *pszLDID = CSLFetchNameValue( papszOptions, "ENCODING" ); /* -------------------------------------------------------------------- */ /* Create a DBF file. */ /* -------------------------------------------------------------------- */ pszFilename = CPLStrdup(CPLFormFilename( NULL, pszBasename, "dbf" )); if( pszLDID != NULL ) hDBF = DBFCreateEx( pszFilename, pszLDID ); else hDBF = DBFCreate( pszFilename ); if( hDBF == NULL ) { CPLError( CE_Failure, CPLE_OpenFailed, "Failed to open Shape DBF file `%s'.\n", pszFilename ); CPLFree( pszFilename ); CPLFree( pszBasename ); SHPClose(hSHP); return NULL; } CPLFree( pszFilename ); /* -------------------------------------------------------------------- */ /* Create the .prj file, if required. */ /* -------------------------------------------------------------------- */ if( poSRS != NULL ) { char *pszWKT = NULL; CPLString osPrjFile = CPLFormFilename( NULL, pszBasename, "prj"); VSILFILE *fp; /* the shape layer needs it's own copy */ poSRS = poSRS->Clone(); poSRS->morphToESRI(); if( poSRS->exportToWkt( &pszWKT ) == OGRERR_NONE && (fp = VSIFOpenL( osPrjFile, "wt" )) != NULL ) { VSIFWriteL( pszWKT, strlen(pszWKT), 1, fp ); VSIFCloseL( fp ); } CPLFree( pszWKT ); poSRS->morphFromESRI(); } /* -------------------------------------------------------------------- */ /* Create the layer object. */ /* -------------------------------------------------------------------- */ OGRShapeLayer *poLayer; poLayer = new OGRShapeLayer( pszBasename, hSHP, hDBF, poSRS, TRUE, TRUE, eType ); poLayer->InitializeIndexSupport( pszBasename ); CPLFree( pszBasename ); /* -------------------------------------------------------------------- */ /* Add layer to data source layer list. */ /* -------------------------------------------------------------------- */ papoLayers = (OGRShapeLayer **) CPLRealloc( papoLayers, sizeof(OGRShapeLayer *) * (nLayers+1) ); papoLayers[nLayers++] = poLayer; return poLayer; }