LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/csv - ogrcsvdatasource.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 144 110 76.4 %
Date: 2010-01-09 Functions: 9 9 100.0 %

       1                 : /******************************************************************************
       2                 :  * $Id: ogrcsvdatasource.cpp 17806 2009-10-13 17:27:54Z rouault $
       3                 :  *
       4                 :  * Project:  CSV Translator
       5                 :  * Purpose:  Implements OGRCSVDataSource class
       6                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2004, Frank Warmerdam <warmerdam@pobox.com>
      10                 :  *
      11                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      12                 :  * copy of this software and associated documentation files (the "Software"),
      13                 :  * to deal in the Software without restriction, including without limitation
      14                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15                 :  * and/or sell copies of the Software, and to permit persons to whom the
      16                 :  * Software is furnished to do so, subject to the following conditions:
      17                 :  *
      18                 :  * The above copyright notice and this permission notice shall be included
      19                 :  * in all copies or substantial portions of the Software.
      20                 :  *
      21                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      22                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      24                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      27                 :  * DEALINGS IN THE SOFTWARE.
      28                 :  ****************************************************************************/
      29                 : 
      30                 : #include "ogr_csv.h"
      31                 : #include "cpl_conv.h"
      32                 : #include "cpl_string.h"
      33                 : #include "cpl_csv.h"
      34                 : 
      35                 : CPL_CVSID("$Id: ogrcsvdatasource.cpp 17806 2009-10-13 17:27:54Z rouault $");
      36                 : 
      37                 : /************************************************************************/
      38                 : /*                          OGRCSVDataSource()                          */
      39                 : /************************************************************************/
      40                 : 
      41             164 : OGRCSVDataSource::OGRCSVDataSource()
      42                 : 
      43                 : {
      44             164 :     papoLayers = NULL;
      45             164 :     nLayers = 0;
      46                 : 
      47             164 :     pszName = NULL;
      48                 : 
      49             164 :     bUpdate = FALSE;
      50             164 : }
      51                 : 
      52                 : /************************************************************************/
      53                 : /*                         ~OGRCSVDataSource()                          */
      54                 : /************************************************************************/
      55                 : 
      56             328 : OGRCSVDataSource::~OGRCSVDataSource()
      57                 : 
      58                 : {
      59             214 :     for( int i = 0; i < nLayers; i++ )
      60              50 :         delete papoLayers[i];
      61             164 :     CPLFree( papoLayers );
      62                 : 
      63             164 :     CPLFree( pszName );
      64             328 : }
      65                 : 
      66                 : /************************************************************************/
      67                 : /*                           TestCapability()                           */
      68                 : /************************************************************************/
      69                 : 
      70               4 : int OGRCSVDataSource::TestCapability( const char * pszCap )
      71                 : 
      72                 : {
      73               4 :     if( EQUAL(pszCap,ODsCCreateLayer) )
      74               2 :         return bUpdate;
      75               2 :     else if( EQUAL(pszCap,ODsCDeleteLayer) )
      76               2 :         return bUpdate;
      77                 :     else
      78               0 :         return FALSE;
      79                 : }
      80                 : 
      81                 : /************************************************************************/
      82                 : /*                              GetLayer()                              */
      83                 : /************************************************************************/
      84                 : 
      85              51 : OGRLayer *OGRCSVDataSource::GetLayer( int iLayer )
      86                 : 
      87                 : {
      88              51 :     if( iLayer < 0 || iLayer >= nLayers )
      89               0 :         return NULL;
      90                 :     else
      91              51 :         return papoLayers[iLayer];
      92                 : }
      93                 : 
      94                 : /************************************************************************/
      95                 : /*                                Open()                                */
      96                 : /************************************************************************/
      97                 : 
      98             164 : int OGRCSVDataSource::Open( const char * pszFilename, int bUpdateIn,
      99                 :                             int bForceOpen )
     100                 : 
     101                 : {
     102             164 :     pszName = CPLStrdup( pszFilename );
     103             164 :     bUpdate = bUpdateIn;
     104                 : 
     105                 : /* -------------------------------------------------------------------- */
     106                 : /*      Determine what sort of object this is.                          */
     107                 : /* -------------------------------------------------------------------- */
     108                 :     VSIStatBufL sStatBuf;
     109                 : 
     110             164 :     if( VSIStatL( pszFilename, &sStatBuf ) != 0 )
     111              60 :         return FALSE;
     112                 : 
     113                 : /* -------------------------------------------------------------------- */
     114                 : /*      Is this a single CSV file?                                      */
     115                 : /* -------------------------------------------------------------------- */
     116             104 :     if( VSI_ISREG(sStatBuf.st_mode)
     117                 :         && strlen(pszFilename) > 4
     118                 :         && EQUAL(pszFilename+strlen(pszFilename)-4,".csv") )
     119              20 :         return OpenTable( pszFilename );
     120                 : 
     121                 : /* -------------------------------------------------------------------- */
     122                 : /*      Otherwise it has to be a directory.                             */
     123                 : /* -------------------------------------------------------------------- */
     124              84 :     if( !VSI_ISDIR(sStatBuf.st_mode) )
     125              76 :         return FALSE;
     126                 : 
     127                 : /* -------------------------------------------------------------------- */
     128                 : /*      Scan through for entries ending in .csv.                        */
     129                 : /* -------------------------------------------------------------------- */
     130               8 :     int nNotCSVCount = 0, i;
     131               8 :     char **papszNames = CPLReadDir( pszFilename );
     132                 : 
     133               8 :     for( i = 0; papszNames != NULL && papszNames[i] != NULL; i++ )
     134                 :     {
     135                 :         CPLString oSubFilename = 
     136              60 :             CPLFormFilename( pszFilename, papszNames[i], NULL );
     137                 : 
     138              60 :         if( EQUAL(papszNames[i],".") || EQUAL(papszNames[i],"..") )
     139              16 :             continue;
     140                 : 
     141              44 :         if (EQUAL(CPLGetExtension(oSubFilename),"csvt"))
     142              13 :             continue;
     143                 : 
     144              31 :         if( VSIStatL( oSubFilename, &sStatBuf ) != 0 
     145                 :             || !VSI_ISREG(sStatBuf.st_mode) 
     146                 :             || !EQUAL(CPLGetExtension(oSubFilename),"csv") )
     147                 :         {
     148               8 :             nNotCSVCount++;
     149               8 :             continue;
     150                 :         }
     151                 : 
     152              23 :         if( !OpenTable( oSubFilename ) )
     153                 :         {
     154               0 :             CSLDestroy( papszNames );
     155               0 :             nNotCSVCount++;
     156               0 :             return FALSE;
     157                 :         }
     158                 :     }
     159                 : 
     160               8 :     CSLDestroy( papszNames );
     161                 : 
     162                 : /* -------------------------------------------------------------------- */
     163                 : /*      We presume that this is indeed intended to be a CSV             */
     164                 : /*      datasource if over half the files were .csv files.              */
     165                 : /* -------------------------------------------------------------------- */
     166               8 :     return bForceOpen || nNotCSVCount < nLayers;
     167                 : }
     168                 : 
     169                 : /************************************************************************/
     170                 : /*                              OpenTable()                             */
     171                 : /************************************************************************/
     172                 : 
     173              43 : int OGRCSVDataSource::OpenTable( const char * pszFilename )
     174                 : 
     175                 : {
     176                 : /* -------------------------------------------------------------------- */
     177                 : /*      Open the file.                                                  */
     178                 : /* -------------------------------------------------------------------- */
     179                 :     FILE       * fp;
     180                 : 
     181              43 :     if( bUpdate )
     182              14 :         fp = VSIFOpen( pszFilename, "rb+" );
     183                 :     else
     184              29 :         fp = VSIFOpen( pszFilename, "rb" );
     185              43 :     if( fp == NULL )
     186                 :     {
     187                 :         CPLError( CE_Warning, CPLE_OpenFailed, 
     188                 :                   "Failed to open %s, %s.", 
     189               0 :                   pszFilename, VSIStrerror( errno ) );
     190               0 :         return FALSE;
     191                 :     }
     192                 : 
     193                 : /* -------------------------------------------------------------------- */
     194                 : /*      Read and parse a line.  Did we get multiple fields?             */
     195                 : /* -------------------------------------------------------------------- */
     196                 : 
     197              43 :     const char* pszLine = CPLReadLine( fp );
     198              43 :     if (pszLine == NULL)
     199                 :     {
     200               0 :         VSIFClose( fp );
     201               0 :         return FALSE;
     202                 :     }
     203              43 :     char chDelimiter = CSVDetectSeperator(pszLine);
     204              43 :     VSIRewind( fp );
     205                 : 
     206              43 :     char **papszFields = CSVReadParseLine2( fp, chDelimiter );
     207                 :             
     208              43 :     if( CSLCount(papszFields) < 2 )
     209                 :     {
     210               0 :         VSIFClose( fp );
     211               0 :         CSLDestroy( papszFields );
     212               0 :         return FALSE;
     213                 :     }
     214                 : 
     215              43 :     VSIRewind( fp );
     216              43 :     CSLDestroy( papszFields );
     217                 : 
     218                 : /* -------------------------------------------------------------------- */
     219                 : /*      Create a layer.                                                 */
     220                 : /* -------------------------------------------------------------------- */
     221              43 :     nLayers++;
     222                 :     papoLayers = (OGRCSVLayer **) CPLRealloc(papoLayers, 
     223              43 :                                              sizeof(void*) * nLayers);
     224                 :     
     225              43 :     papoLayers[nLayers-1] = 
     226              86 :         new OGRCSVLayer( CPLGetBasename(pszFilename), fp, pszFilename, FALSE, bUpdate, chDelimiter );
     227                 : 
     228              43 :     return TRUE;
     229                 : }
     230                 : 
     231                 : /************************************************************************/
     232                 : /*                            CreateLayer()                             */
     233                 : /************************************************************************/
     234                 : 
     235                 : OGRLayer *
     236               8 : OGRCSVDataSource::CreateLayer( const char *pszLayerName, 
     237                 :                                OGRSpatialReference *poSpatialRef,
     238                 :                                OGRwkbGeometryType eGType,
     239                 :                                char ** papszOptions  )
     240                 : 
     241                 : {
     242                 : /* -------------------------------------------------------------------- */
     243                 : /*      Verify we are in update mode.                                   */
     244                 : /* -------------------------------------------------------------------- */
     245               8 :     if (!bUpdate)
     246                 :     {
     247                 :         CPLError( CE_Failure, CPLE_NoWriteAccess,
     248                 :                   "Data source %s opened read-only.\n"
     249                 :                   "New layer %s cannot be created.\n",
     250               0 :                   pszName, pszLayerName );
     251                 : 
     252               0 :         return NULL;
     253                 :     }
     254                 : 
     255                 : /* -------------------------------------------------------------------- */
     256                 : /*      Verify that the datasource is a directory.                      */
     257                 : /* -------------------------------------------------------------------- */
     258                 :     VSIStatBuf sStatBuf;
     259                 : 
     260               8 :     if( VSIStat( pszName, &sStatBuf ) != 0 
     261                 :         || !VSI_ISDIR( sStatBuf.st_mode ) )
     262                 :     {
     263                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     264               0 :                   "Attempt to create csv layer (file) against a non-directory datasource." );
     265               0 :         return NULL;
     266                 :     }
     267                 : 
     268                 : /* -------------------------------------------------------------------- */
     269                 : /*      What filename would we use?                                     */
     270                 : /* -------------------------------------------------------------------- */
     271                 :     const char *pszFilename;
     272                 : 
     273               8 :     pszFilename = CPLFormFilename( pszName, pszLayerName, "csv" );
     274                 : 
     275                 : /* -------------------------------------------------------------------- */
     276                 : /*      does this file already exist?                                   */
     277                 : /* -------------------------------------------------------------------- */
     278                 :     
     279               8 :     if( VSIStat( pszName, &sStatBuf ) != 0 )
     280                 :     {
     281                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     282                 :                   "Attempt to create layer %s, but file %s already exists.",
     283               0 :                   pszLayerName, pszFilename );
     284               0 :         return NULL;
     285                 :     }
     286                 : 
     287                 : /* -------------------------------------------------------------------- */
     288                 : /*      Create the empty file.                                          */
     289                 : /* -------------------------------------------------------------------- */
     290                 :     FILE *fp;
     291                 : 
     292               8 :     fp = VSIFOpen( pszFilename, "w+b" );
     293                 : 
     294               8 :     if( fp == NULL )
     295                 :     {
     296                 :         CPLError( CE_Failure, CPLE_OpenFailed, 
     297                 :                   "Failed to create %s:\n%s", 
     298               0 :                   pszFilename, VSIStrerror( errno ) );
     299                 :                   
     300                 :                   
     301               0 :         return NULL;
     302                 :     }
     303                 : 
     304                 : 
     305               8 :     const char *pszDelimiter = CSLFetchNameValue( papszOptions, "SEPARATOR");
     306               8 :     char chDelimiter = ',';
     307               8 :     if (pszDelimiter != NULL)
     308                 :     {
     309               1 :         if (EQUAL(pszDelimiter, "COMMA"))
     310               0 :             chDelimiter = ',';
     311               1 :         else if (EQUAL(pszDelimiter, "SEMICOLON"))
     312               1 :             chDelimiter = ';';
     313               0 :         else if (EQUAL(pszDelimiter, "TAB"))
     314               0 :             chDelimiter = '\t';
     315                 :         else
     316                 :         {
     317                 :             CPLError( CE_Warning, CPLE_AppDefined, 
     318                 :                   "SEPARATOR=%s not understood, use one of COMMA, SEMICOLON or TAB.",
     319               0 :                   pszDelimiter );
     320                 :         }
     321                 :     }
     322                 : 
     323                 : /* -------------------------------------------------------------------- */
     324                 : /*      Create a layer.                                                 */
     325                 : /* -------------------------------------------------------------------- */
     326               8 :     nLayers++;
     327                 :     papoLayers = (OGRCSVLayer **) CPLRealloc(papoLayers, 
     328               8 :                                              sizeof(void*) * nLayers);
     329                 :     
     330               8 :     papoLayers[nLayers-1] = new OGRCSVLayer( pszLayerName, fp, pszFilename, TRUE, TRUE, chDelimiter );
     331                 : 
     332                 : /* -------------------------------------------------------------------- */
     333                 : /*      Was a partiuclar CRLF order requested?                          */
     334                 : /* -------------------------------------------------------------------- */
     335               8 :     const char *pszCRLFFormat = CSLFetchNameValue( papszOptions, "LINEFORMAT");
     336                 :     int bUseCRLF;
     337                 : 
     338               8 :     if( pszCRLFFormat == NULL )
     339                 :     {
     340                 : #ifdef WIN32
     341                 :         bUseCRLF = TRUE;
     342                 : #else
     343               7 :         bUseCRLF = FALSE;
     344                 : #endif
     345                 :     }
     346               1 :     else if( EQUAL(pszCRLFFormat,"CRLF") )
     347               1 :         bUseCRLF = TRUE;
     348               0 :     else if( EQUAL(pszCRLFFormat,"LF") )
     349               0 :         bUseCRLF = FALSE;
     350                 :     else
     351                 :     {
     352                 :         CPLError( CE_Warning, CPLE_AppDefined, 
     353                 :                   "LINEFORMAT=%s not understood, use one of CRLF or LF.",
     354               0 :                   pszCRLFFormat );
     355                 : #ifdef WIN32
     356                 :         bUseCRLF = TRUE;
     357                 : #else
     358               0 :         bUseCRLF = FALSE;
     359                 : #endif
     360                 :     }
     361                 :     
     362               8 :     papoLayers[nLayers-1]->SetCRLF( bUseCRLF );
     363                 : 
     364                 : /* -------------------------------------------------------------------- */
     365                 : /*      Should we write the geometry ?                                  */
     366                 : /* -------------------------------------------------------------------- */
     367               8 :     const char *pszGeometry = CSLFetchNameValue( papszOptions, "GEOMETRY");
     368               8 :     if (pszGeometry != NULL)
     369                 :     {
     370               4 :         if (EQUAL(pszGeometry, "AS_WKT"))
     371                 :         {
     372               1 :             papoLayers[nLayers-1]->SetWriteGeometry(OGR_CSV_GEOM_AS_WKT);
     373                 :         }
     374               6 :         else if (EQUAL(pszGeometry, "AS_XYZ") ||
     375                 :                  EQUAL(pszGeometry, "AS_XY") ||
     376                 :                  EQUAL(pszGeometry, "AS_YX"))
     377                 :         {
     378               6 :             if (eGType == wkbUnknown || wkbFlatten(eGType) == wkbPoint)
     379                 :             {
     380               3 :                 papoLayers[nLayers-1]->SetWriteGeometry(EQUAL(pszGeometry, "AS_XYZ") ? OGR_CSV_GEOM_AS_XYZ :
     381                 :                                                         EQUAL(pszGeometry, "AS_XY") ?  OGR_CSV_GEOM_AS_XY :
     382               6 :                                                                                        OGR_CSV_GEOM_AS_YX);
     383                 :             }
     384                 :             else
     385                 :             {
     386                 :                 CPLError( CE_Warning, CPLE_AppDefined, 
     387                 :                           "Geometry type %s is not compatible with GEOMETRY=AS_XYZ.",
     388               0 :                           OGRGeometryTypeToName(eGType) );
     389                 :             }
     390                 :         }
     391                 :         else
     392                 :         {
     393                 :             CPLError( CE_Warning, CPLE_AppDefined, 
     394                 :                       "Unsupported value %s for creation option GEOMETRY",
     395               0 :                        pszGeometry );
     396                 :         }
     397                 :     }
     398                 : 
     399                 : /* -------------------------------------------------------------------- */
     400                 : /*      Should we create a CSVT file ?                                  */
     401                 : /* -------------------------------------------------------------------- */
     402                 : 
     403               8 :     const char *pszCreateCSVT = CSLFetchNameValue( papszOptions, "CREATE_CSVT");
     404               8 :     if (pszCreateCSVT)
     405               4 :         papoLayers[nLayers-1]->SetCreateCSVT(CSLTestBoolean(pszCreateCSVT));
     406                 : 
     407               8 :     return papoLayers[nLayers-1];
     408                 : }
     409                 : 
     410                 : /************************************************************************/
     411                 : /*                            DeleteLayer()                             */
     412                 : /************************************************************************/
     413                 : 
     414               1 : OGRErr OGRCSVDataSource::DeleteLayer( int iLayer )
     415                 : 
     416                 : {
     417                 :     char *pszFilename;
     418                 :     char *pszFilenameCSVT;
     419                 : 
     420                 : /* -------------------------------------------------------------------- */
     421                 : /*      Verify we are in update mode.                                   */
     422                 : /* -------------------------------------------------------------------- */
     423               1 :     if( !bUpdate )
     424                 :     {
     425                 :         CPLError( CE_Failure, CPLE_NoWriteAccess,
     426                 :                   "Data source %s opened read-only.\n"
     427                 :                   "Layer %d cannot be deleted.\n",
     428               0 :                   pszName, iLayer );
     429                 : 
     430               0 :         return OGRERR_FAILURE;
     431                 :     }
     432                 : 
     433               1 :     if( iLayer < 0 || iLayer >= nLayers )
     434                 :     {
     435                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     436                 :                   "Layer %d not in legal range of 0 to %d.", 
     437               0 :                   iLayer, nLayers-1 );
     438               0 :         return OGRERR_FAILURE;
     439                 :     }
     440                 : 
     441                 :     pszFilename = 
     442               1 :         CPLStrdup(CPLFormFilename(pszName,papoLayers[iLayer]->GetLayerDefn()->GetName(),"csv"));
     443                 :     pszFilenameCSVT = 
     444               1 :         CPLStrdup(CPLFormFilename(pszName,papoLayers[iLayer]->GetLayerDefn()->GetName(),"csvt"));
     445                 : 
     446               1 :     delete papoLayers[iLayer];
     447                 : 
     448               3 :     while( iLayer < nLayers - 1 )
     449                 :     {
     450               1 :         papoLayers[iLayer] = papoLayers[iLayer+1];
     451               1 :         iLayer++;
     452                 :     }
     453                 : 
     454               1 :     nLayers--;
     455                 : 
     456               1 :     VSIUnlink( pszFilename );
     457               1 :     CPLFree( pszFilename );
     458               1 :     VSIUnlink( pszFilenameCSVT );
     459               1 :     CPLFree( pszFilenameCSVT );
     460                 : 
     461               1 :     return OGRERR_NONE;
     462                 : }

Generated by: LCOV version 1.7