LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/csv - ogrcsvdatasource.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 255 163 63.9 %
Date: 2013-03-30 Functions: 12 9 75.0 %

       1                 : /******************************************************************************
       2                 :  * $Id: ogrcsvdatasource.cpp 25354 2012-12-27 10:26:34Z 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                 : #include "cpl_vsi_virtual.h"
      35                 : 
      36                 : CPL_CVSID("$Id: ogrcsvdatasource.cpp 25354 2012-12-27 10:26:34Z rouault $");
      37                 : 
      38                 : /************************************************************************/
      39                 : /*                          OGRCSVDataSource()                          */
      40                 : /************************************************************************/
      41                 : 
      42             871 : OGRCSVDataSource::OGRCSVDataSource()
      43                 : 
      44                 : {
      45             871 :     papoLayers = NULL;
      46             871 :     nLayers = 0;
      47                 : 
      48             871 :     pszName = NULL;
      49                 : 
      50             871 :     bUpdate = FALSE;
      51             871 : }
      52                 : 
      53                 : /************************************************************************/
      54                 : /*                         ~OGRCSVDataSource()                          */
      55                 : /************************************************************************/
      56                 : 
      57             871 : OGRCSVDataSource::~OGRCSVDataSource()
      58                 : 
      59                 : {
      60            1092 :     for( int i = 0; i < nLayers; i++ )
      61             221 :         delete papoLayers[i];
      62             871 :     CPLFree( papoLayers );
      63                 : 
      64             871 :     CPLFree( pszName );
      65             871 : }
      66                 : 
      67                 : /************************************************************************/
      68                 : /*                           TestCapability()                           */
      69                 : /************************************************************************/
      70                 : 
      71               5 : int OGRCSVDataSource::TestCapability( const char * pszCap )
      72                 : 
      73                 : {
      74               5 :     if( EQUAL(pszCap,ODsCCreateLayer) )
      75               3 :         return bUpdate;
      76               2 :     else if( EQUAL(pszCap,ODsCDeleteLayer) )
      77               2 :         return bUpdate;
      78                 :     else
      79               0 :         return FALSE;
      80                 : }
      81                 : 
      82                 : /************************************************************************/
      83                 : /*                              GetLayer()                              */
      84                 : /************************************************************************/
      85                 : 
      86             212 : OGRLayer *OGRCSVDataSource::GetLayer( int iLayer )
      87                 : 
      88                 : {
      89             212 :     if( iLayer < 0 || iLayer >= nLayers )
      90               0 :         return NULL;
      91                 :     else
      92             212 :         return papoLayers[iLayer];
      93                 : }
      94                 : 
      95                 : /************************************************************************/
      96                 : /*                          GetRealExtension()                          */
      97                 : /************************************************************************/
      98                 : 
      99            1066 : CPLString OGRCSVDataSource::GetRealExtension(CPLString osFilename)
     100                 : {
     101            1066 :     CPLString osExt = CPLGetExtension(osFilename);
     102            1066 :     if( strncmp(osFilename, "/vsigzip/", 9) == 0 && EQUAL(osExt, "gz") )
     103                 :     {
     104               0 :         if( strlen(osFilename) > 7 && EQUAL(osFilename + strlen(osFilename) - 7, ".csv.gz") )
     105               0 :             osExt = "csv";
     106               0 :         else if( strlen(osFilename) > 7 && EQUAL(osFilename + strlen(osFilename) - 7, ".tsv.gz") )
     107               0 :             osExt = "tsv";
     108                 :     }
     109               0 :     return osExt;
     110                 : }
     111                 : 
     112                 : /************************************************************************/
     113                 : /*                                Open()                                */
     114                 : /************************************************************************/
     115                 : 
     116             871 : int OGRCSVDataSource::Open( const char * pszFilename, int bUpdateIn,
     117                 :                             int bForceOpen )
     118                 : 
     119                 : {
     120             871 :     pszName = CPLStrdup( pszFilename );
     121             871 :     bUpdate = bUpdateIn;
     122                 : 
     123             871 :     if (bUpdateIn && bForceOpen && EQUAL(pszFilename, "/vsistdout/"))
     124               1 :         return TRUE;
     125                 : 
     126                 :     /* For writable /vsizip/, do nothing more */
     127             870 :     if (bUpdateIn && bForceOpen && strncmp(pszFilename, "/vsizip/", 8) == 0)
     128               0 :         return TRUE;
     129                 : 
     130             870 :     CPLString osFilename(pszFilename);
     131             870 :     CPLString osBaseFilename = CPLGetFilename(pszFilename);
     132             870 :     CPLString osExt = GetRealExtension(osFilename);
     133             870 :     pszFilename = NULL;
     134                 : 
     135             870 :     int bIgnoreExtension = EQUALN(osFilename, "CSV:", 4);
     136             870 :     int bUSGeonamesFile = FALSE;
     137             870 :     int bGeonamesOrgFile = FALSE;
     138             870 :     if (bIgnoreExtension)
     139                 :     {
     140               0 :         osFilename = osFilename + 4;
     141                 :     }
     142                 : 
     143                 :     /* Those are *not* real .XLS files, but text file with tab as column separator */
     144             870 :     if (EQUAL(osBaseFilename, "NfdcFacilities.xls") ||
     145                 :         EQUAL(osBaseFilename, "NfdcRunways.xls") ||
     146                 :         EQUAL(osBaseFilename, "NfdcRemarks.xls") ||
     147                 :         EQUAL(osBaseFilename, "NfdcSchedules.xls"))
     148                 :     {
     149               0 :         if (bUpdateIn)
     150               0 :             return FALSE;
     151               0 :         bIgnoreExtension = TRUE;
     152                 :     }
     153             870 :     else if ((EQUALN(osBaseFilename, "NationalFile_", 13) ||
     154                 :               EQUALN(osBaseFilename, "POP_PLACES_", 11) ||
     155                 :               EQUALN(osBaseFilename, "HIST_FEATURES_", 14) ||
     156                 :               EQUALN(osBaseFilename, "US_CONCISE_", 11) ||
     157                 :               EQUALN(osBaseFilename, "AllNames_", 9) ||
     158                 :               EQUALN(osBaseFilename, "Feature_Description_History_", 28) ||
     159                 :               EQUALN(osBaseFilename, "ANTARCTICA_", 11) ||
     160                 :               EQUALN(osBaseFilename, "GOVT_UNITS_", 11) ||
     161                 :               EQUALN(osBaseFilename, "NationalFedCodes_", 17) ||
     162                 :               EQUALN(osBaseFilename, "AllStates_", 10) ||
     163                 :               EQUALN(osBaseFilename, "AllStatesFedCodes_", 18) ||
     164                 :               (strlen(osBaseFilename) > 2 && EQUALN(osBaseFilename+2, "_Features_", 10)) ||
     165                 :               (strlen(osBaseFilename) > 2 && EQUALN(osBaseFilename+2, "_FedCodes_", 10))) &&
     166                 :              (EQUAL(osExt, "txt") || EQUAL(osExt, "zip")) )
     167                 :     {
     168               0 :         if (bUpdateIn)
     169               0 :             return FALSE;
     170               0 :         bIgnoreExtension = TRUE;
     171               0 :         bUSGeonamesFile = TRUE;
     172                 : 
     173               0 :         if (EQUAL(osExt, "zip") &&
     174                 :             strstr(osFilename, "/vsizip/") == NULL )
     175                 :         {
     176               0 :             osFilename = "/vsizip/" + osFilename;
     177                 :         }
     178                 :     }
     179             870 :     else if (EQUAL(osBaseFilename, "allCountries.txt") ||
     180                 :              EQUAL(osBaseFilename, "allCountries.zip"))
     181                 :     {
     182               0 :         if (bUpdateIn)
     183               0 :             return FALSE;
     184               0 :         bIgnoreExtension = TRUE;
     185               0 :         bGeonamesOrgFile = TRUE;
     186                 : 
     187               0 :         if (EQUAL(osExt, "zip") &&
     188                 :             strstr(osFilename, "/vsizip/") == NULL )
     189                 :         {
     190               0 :             osFilename = "/vsizip/" + osFilename;
     191                 :         }
     192                 :     }
     193                 : 
     194                 : /* -------------------------------------------------------------------- */
     195                 : /*      Determine what sort of object this is.                          */
     196                 : /* -------------------------------------------------------------------- */
     197                 :     VSIStatBufL sStatBuf;
     198                 : 
     199             870 :     if( VSIStatExL( osFilename, &sStatBuf, VSI_STAT_NATURE_FLAG ) != 0 )
     200             233 :         return FALSE;
     201                 : 
     202                 : /* -------------------------------------------------------------------- */
     203                 : /*      Is this a single CSV file?                                      */
     204                 : /* -------------------------------------------------------------------- */
     205             637 :     if( VSI_ISREG(sStatBuf.st_mode)
     206                 :         && (bIgnoreExtension || EQUAL(osExt,"csv") || EQUAL(osExt,"tsv")) )
     207                 :     {
     208             139 :         if (EQUAL(CPLGetFilename(osFilename), "NfdcFacilities.xls"))
     209                 :         {
     210               0 :             return OpenTable( osFilename, "ARP");
     211                 :         }
     212             139 :         else if (EQUAL(CPLGetFilename(osFilename), "NfdcRunways.xls"))
     213                 :         {
     214               0 :             OpenTable( osFilename, "BaseEndPhysical");
     215               0 :             OpenTable( osFilename, "BaseEndDisplaced");
     216               0 :             OpenTable( osFilename, "ReciprocalEndPhysical");
     217               0 :             OpenTable( osFilename, "ReciprocalEndDisplaced");
     218               0 :             return nLayers != 0;
     219                 :         }
     220             139 :         else if (bUSGeonamesFile)
     221                 :         {
     222                 :             /* GNIS specific */
     223               0 :             if (EQUALN(osBaseFilename, "NationalFedCodes_", 17) ||
     224                 :                 EQUALN(osBaseFilename, "AllStatesFedCodes_", 18) ||
     225                 :                 EQUALN(osBaseFilename, "ANTARCTICA_", 11) ||
     226                 :                 (strlen(osBaseFilename) > 2 && EQUALN(osBaseFilename+2, "_FedCodes_", 10)))
     227                 :             {
     228               0 :                 OpenTable( osFilename, NULL, "PRIMARY");
     229                 :             }
     230               0 :             else if (EQUALN(osBaseFilename, "GOVT_UNITS_", 11) ||
     231                 :                      EQUALN(osBaseFilename, "Feature_Description_History_", 28))
     232                 :             {
     233               0 :                 OpenTable( osFilename, NULL, "");
     234                 :             }
     235                 :             else
     236                 :             {
     237               0 :                 OpenTable( osFilename, NULL, "PRIM");
     238               0 :                 OpenTable( osFilename, NULL, "SOURCE");
     239                 :             }
     240               0 :             return nLayers != 0;
     241                 :         }
     242                 : 
     243             139 :         return OpenTable( osFilename );
     244                 :     }
     245                 : 
     246                 : /* -------------------------------------------------------------------- */
     247                 : /*      Is this a single a ZIP file with only a CSV file inside ?       */
     248                 : /* -------------------------------------------------------------------- */
     249             498 :     if( strncmp(osFilename, "/vsizip/", 8) == 0 &&
     250                 :         EQUAL(osExt, "zip") &&
     251                 :         VSI_ISREG(sStatBuf.st_mode) )
     252                 :     {
     253               0 :         char** papszFiles = VSIReadDir(osFilename);
     254               0 :         if (CSLCount(papszFiles) != 1 ||
     255               0 :             !EQUAL(CPLGetExtension(papszFiles[0]), "CSV"))
     256                 :         {
     257               0 :             CSLDestroy(papszFiles);
     258               0 :             return FALSE;
     259                 :         }
     260               0 :         osFilename = CPLFormFilename(osFilename, papszFiles[0], NULL);
     261               0 :         CSLDestroy(papszFiles);
     262               0 :         return OpenTable( osFilename );
     263                 :     }
     264                 : 
     265                 : /* -------------------------------------------------------------------- */
     266                 : /*      Otherwise it has to be a directory.                             */
     267                 : /* -------------------------------------------------------------------- */
     268             498 :     if( !VSI_ISDIR(sStatBuf.st_mode) )
     269             457 :         return FALSE;
     270                 : 
     271                 : /* -------------------------------------------------------------------- */
     272                 : /*      Scan through for entries ending in .csv.                        */
     273                 : /* -------------------------------------------------------------------- */
     274              41 :     int nNotCSVCount = 0, i;
     275              41 :     char **papszNames = CPLReadDir( osFilename );
     276                 : 
     277              41 :     for( i = 0; papszNames != NULL && papszNames[i] != NULL; i++ )
     278                 :     {
     279                 :         CPLString oSubFilename = 
     280            1497 :             CPLFormFilename( osFilename, papszNames[i], NULL );
     281                 : 
     282            1497 :         if( EQUAL(papszNames[i],".") || EQUAL(papszNames[i],"..") )
     283              74 :             continue;
     284                 : 
     285            1423 :         if (EQUAL(CPLGetExtension(oSubFilename),"csvt"))
     286              29 :             continue;
     287                 : 
     288            1394 :         if( VSIStatL( oSubFilename, &sStatBuf ) != 0 
     289                 :             || !VSI_ISREG(sStatBuf.st_mode) )
     290                 :         {
     291              26 :             nNotCSVCount++;
     292              26 :             continue;
     293                 :         }
     294                 : 
     295            1368 :         if (EQUAL(CPLGetExtension(oSubFilename),"csv"))
     296                 :         {
     297              58 :             if( !OpenTable( oSubFilename ) )
     298                 :             {
     299               1 :                 CPLDebug("CSV", "Cannot open %s", oSubFilename.c_str());
     300               1 :                 nNotCSVCount++;
     301               1 :                 continue;
     302                 :             }
     303                 :         }
     304                 : 
     305                 :         /* GNIS specific */
     306            2620 :         else if ( strlen(papszNames[i]) > 2 &&
     307            1310 :                   EQUALN(papszNames[i]+2, "_Features_", 10) &&
     308               0 :                   EQUAL(CPLGetExtension(papszNames[i]), "txt") )
     309                 :         {
     310               0 :             int bRet = OpenTable( oSubFilename, NULL, "PRIM");
     311               0 :             bRet |= OpenTable( oSubFilename, NULL, "SOURCE");
     312               0 :             if ( !bRet )
     313                 :             {
     314               0 :                 CPLDebug("CSV", "Cannot open %s", oSubFilename.c_str());
     315               0 :                 nNotCSVCount++;
     316               0 :                 continue;
     317                 :             }
     318                 :         }
     319                 :         /* GNIS specific */
     320            2620 :         else if ( strlen(papszNames[i]) > 2 &&
     321            1310 :                   EQUALN(papszNames[i]+2, "_FedCodes_", 10) &&
     322               0 :                   EQUAL(CPLGetExtension(papszNames[i]), "txt") )
     323                 :         {
     324               0 :             if ( !OpenTable( oSubFilename, NULL, "PRIMARY") )
     325                 :             {
     326               0 :                 CPLDebug("CSV", "Cannot open %s", oSubFilename.c_str());
     327               0 :                 nNotCSVCount++;
     328               0 :                 continue;
     329                 :             }
     330                 :         }
     331                 :         else
     332                 :         {
     333            1310 :             nNotCSVCount++;
     334            1310 :             continue;
     335                 :         }
     336                 :     }
     337                 : 
     338              41 :     CSLDestroy( papszNames );
     339                 : 
     340                 : /* -------------------------------------------------------------------- */
     341                 : /*      We presume that this is indeed intended to be a CSV             */
     342                 : /*      datasource if over half the files were .csv files.              */
     343                 : /* -------------------------------------------------------------------- */
     344              41 :     return bForceOpen || nNotCSVCount < nLayers;
     345                 : }
     346                 : 
     347                 : /************************************************************************/
     348                 : /*                              OpenTable()                             */
     349                 : /************************************************************************/
     350                 : 
     351             197 : int OGRCSVDataSource::OpenTable( const char * pszFilename,
     352                 :                                  const char* pszNfdcRunwaysGeomField,
     353                 :                                  const char* pszGeonamesGeomFieldPrefix)
     354                 : 
     355                 : {
     356                 : /* -------------------------------------------------------------------- */
     357                 : /*      Open the file.                                                  */
     358                 : /* -------------------------------------------------------------------- */
     359                 :     VSILFILE       * fp;
     360                 : 
     361             197 :     if( bUpdate )
     362              97 :         fp = VSIFOpenL( pszFilename, "rb+" );
     363                 :     else
     364             100 :         fp = VSIFOpenL( pszFilename, "rb" );
     365             197 :     if( fp == NULL )
     366                 :     {
     367                 :         CPLError( CE_Warning, CPLE_OpenFailed, 
     368                 :                   "Failed to open %s, %s.", 
     369               0 :                   pszFilename, VSIStrerror( errno ) );
     370               0 :         return FALSE;
     371                 :     }
     372                 : 
     373             197 :     if( !bUpdate && strstr(pszFilename, "/vsigzip/") == NULL &&
     374                 :         strstr(pszFilename, "/vsizip/") == NULL )
     375             100 :         fp = (VSILFILE*) VSICreateBufferedReaderHandle((VSIVirtualHandle*)fp);
     376                 : 
     377             197 :     CPLString osLayerName = CPLGetBasename(pszFilename);
     378             197 :     CPLString osExt = CPLGetExtension(pszFilename);
     379             197 :     if( strncmp(pszFilename, "/vsigzip/", 9) == 0 && EQUAL(osExt, "gz") )
     380                 :     {
     381               0 :         if( strlen(pszFilename) > 7 && EQUAL(pszFilename + strlen(pszFilename) - 7, ".csv.gz") )
     382                 :         {
     383               0 :             osLayerName = osLayerName.substr(0, osLayerName.size() - 4);
     384               0 :             osExt = "csv";
     385                 :         }
     386               0 :         else if( strlen(pszFilename) > 7 && EQUAL(pszFilename + strlen(pszFilename) - 7, ".tsv.gz") )
     387                 :         {
     388               0 :             osLayerName = osLayerName.substr(0, osLayerName.size() - 4);
     389               0 :             osExt = "tsv";
     390                 :         }
     391                 :     }
     392                 : 
     393                 : /* -------------------------------------------------------------------- */
     394                 : /*      Read and parse a line.  Did we get multiple fields?             */
     395                 : /* -------------------------------------------------------------------- */
     396                 : 
     397             197 :     const char* pszLine = CPLReadLineL( fp );
     398             197 :     if (pszLine == NULL)
     399                 :     {
     400               1 :         VSIFCloseL( fp );
     401               1 :         return FALSE;
     402                 :     }
     403             196 :     char chDelimiter = CSVDetectSeperator(pszLine);
     404                 : 
     405                 :     /* Force the delimiter to be TAB for a .tsv file that has a tabulation */
     406                 :     /* in its first line */
     407             196 :     if( EQUAL(osExt, "tsv") && chDelimiter != '\t' &&
     408                 :         strchr(pszLine, '\t') != NULL )
     409                 :     {
     410               1 :         chDelimiter = '\t';
     411                 :     }
     412                 : 
     413             196 :     VSIRewindL( fp );
     414                 : 
     415                 :     /* GNIS specific */
     416             196 :     if (pszGeonamesGeomFieldPrefix != NULL &&
     417                 :         strchr(pszLine, '|') != NULL)
     418               0 :         chDelimiter = '|';
     419                 : 
     420             196 :     char **papszFields = OGRCSVReadParseLineL( fp, chDelimiter, FALSE );
     421                 :             
     422             196 :     if( CSLCount(papszFields) < 2 )
     423                 :     {
     424               0 :         VSIFCloseL( fp );
     425               0 :         CSLDestroy( papszFields );
     426               0 :         return FALSE;
     427                 :     }
     428                 : 
     429             196 :     VSIRewindL( fp );
     430             196 :     CSLDestroy( papszFields );
     431                 : 
     432                 : /* -------------------------------------------------------------------- */
     433                 : /*      Create a layer.                                                 */
     434                 : /* -------------------------------------------------------------------- */
     435             196 :     nLayers++;
     436                 :     papoLayers = (OGRCSVLayer **) CPLRealloc(papoLayers, 
     437             196 :                                              sizeof(void*) * nLayers);
     438                 : 
     439             196 :     if (pszNfdcRunwaysGeomField != NULL)
     440                 :     {
     441               0 :         osLayerName += "_";
     442               0 :         osLayerName += pszNfdcRunwaysGeomField;
     443                 :     }
     444             196 :     else if (pszGeonamesGeomFieldPrefix != NULL &&
     445                 :              !EQUAL(pszGeonamesGeomFieldPrefix, ""))
     446                 :     {
     447               0 :         osLayerName += "_";
     448               0 :         osLayerName += pszGeonamesGeomFieldPrefix;
     449                 :     }
     450             196 :     if (EQUAL(pszFilename, "/vsistdin/"))
     451               0 :         osLayerName = "layer";
     452             196 :     papoLayers[nLayers-1] = 
     453                 :         new OGRCSVLayer( osLayerName, fp, pszFilename, FALSE, bUpdate,
     454             392 :                          chDelimiter, pszNfdcRunwaysGeomField, pszGeonamesGeomFieldPrefix );
     455                 : 
     456             196 :     return TRUE;
     457                 : }
     458                 : 
     459                 : /************************************************************************/
     460                 : /*                            CreateLayer()                             */
     461                 : /************************************************************************/
     462                 : 
     463                 : OGRLayer *
     464              26 : OGRCSVDataSource::CreateLayer( const char *pszLayerName, 
     465                 :                                OGRSpatialReference *poSpatialRef,
     466                 :                                OGRwkbGeometryType eGType,
     467                 :                                char ** papszOptions  )
     468                 : 
     469                 : {
     470                 : /* -------------------------------------------------------------------- */
     471                 : /*      Verify we are in update mode.                                   */
     472                 : /* -------------------------------------------------------------------- */
     473              26 :     if (!bUpdate)
     474                 :     {
     475                 :         CPLError( CE_Failure, CPLE_NoWriteAccess,
     476                 :                   "Data source %s opened read-only.\n"
     477                 :                   "New layer %s cannot be created.\n",
     478               0 :                   pszName, pszLayerName );
     479                 : 
     480               0 :         return NULL;
     481                 :     }
     482                 : 
     483                 : /* -------------------------------------------------------------------- */
     484                 : /*      Verify that the datasource is a directory.                      */
     485                 : /* -------------------------------------------------------------------- */
     486                 :     VSIStatBufL sStatBuf;
     487                 : 
     488              26 :     if( strncmp(pszName, "/vsizip/", 8) == 0)
     489                 :     {
     490                 :         /* Do nothing */
     491                 :     }
     492              26 :     else if( !EQUAL(pszName, "/vsistdout/") &&
     493                 :         (VSIStatL( pszName, &sStatBuf ) != 0
     494                 :         || !VSI_ISDIR( sStatBuf.st_mode )) )
     495                 :     {
     496                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     497               0 :                   "Attempt to create csv layer (file) against a non-directory datasource." );
     498               0 :         return NULL;
     499                 :     }
     500                 : 
     501                 : /* -------------------------------------------------------------------- */
     502                 : /*      What filename would we use?                                     */
     503                 : /* -------------------------------------------------------------------- */
     504              26 :     CPLString osFilename;
     505                 : 
     506              26 :     if( osDefaultCSVName != "" )
     507                 :     {
     508              10 :         osFilename = CPLFormFilename( pszName, osDefaultCSVName, NULL );
     509              10 :         osDefaultCSVName = "";
     510                 :     }
     511                 :     else
     512                 :     {
     513              16 :         osFilename = CPLFormFilename( pszName, pszLayerName, "csv" );
     514                 :     }
     515                 : 
     516                 : /* -------------------------------------------------------------------- */
     517                 : /*      Does this directory/file already exist?                         */
     518                 : /* -------------------------------------------------------------------- */
     519              26 :     if( VSIStatL( osFilename, &sStatBuf ) == 0 )
     520                 :     {
     521                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     522                 :                   "Attempt to create layer %s, but %s already exists.",
     523               0 :                   pszLayerName, osFilename.c_str() );
     524               0 :         return NULL;
     525                 :     }
     526                 : 
     527                 : /* -------------------------------------------------------------------- */
     528                 : /*      Create the empty file.                                          */
     529                 : /* -------------------------------------------------------------------- */
     530                 : 
     531              26 :     const char *pszDelimiter = CSLFetchNameValue( papszOptions, "SEPARATOR");
     532              26 :     char chDelimiter = ',';
     533              26 :     if (pszDelimiter != NULL)
     534                 :     {
     535               1 :         if (EQUAL(pszDelimiter, "COMMA"))
     536               0 :             chDelimiter = ',';
     537               1 :         else if (EQUAL(pszDelimiter, "SEMICOLON"))
     538               1 :             chDelimiter = ';';
     539               0 :         else if (EQUAL(pszDelimiter, "TAB"))
     540               0 :             chDelimiter = '\t';
     541                 :         else
     542                 :         {
     543                 :             CPLError( CE_Warning, CPLE_AppDefined, 
     544                 :                   "SEPARATOR=%s not understood, use one of COMMA, SEMICOLON or TAB.",
     545               0 :                   pszDelimiter );
     546                 :         }
     547                 :     }
     548                 : 
     549                 : /* -------------------------------------------------------------------- */
     550                 : /*      Create a layer.                                                 */
     551                 : /* -------------------------------------------------------------------- */
     552              26 :     nLayers++;
     553                 :     papoLayers = (OGRCSVLayer **) CPLRealloc(papoLayers, 
     554              26 :                                              sizeof(void*) * nLayers);
     555                 :     
     556              26 :     papoLayers[nLayers-1] = new OGRCSVLayer( pszLayerName, NULL, osFilename,
     557              52 :                                              TRUE, TRUE, chDelimiter, NULL, NULL );
     558                 : 
     559                 : /* -------------------------------------------------------------------- */
     560                 : /*      Was a partiuclar CRLF order requested?                          */
     561                 : /* -------------------------------------------------------------------- */
     562              52 :     const char *pszCRLFFormat = CSLFetchNameValue( papszOptions, "LINEFORMAT");
     563                 :     int bUseCRLF;
     564                 : 
     565              26 :     if( pszCRLFFormat == NULL )
     566                 :     {
     567                 : #ifdef WIN32
     568                 :         bUseCRLF = TRUE;
     569                 : #else
     570              23 :         bUseCRLF = FALSE;
     571                 : #endif
     572                 :     }
     573               3 :     else if( EQUAL(pszCRLFFormat,"CRLF") )
     574               1 :         bUseCRLF = TRUE;
     575               2 :     else if( EQUAL(pszCRLFFormat,"LF") )
     576               2 :         bUseCRLF = FALSE;
     577                 :     else
     578                 :     {
     579                 :         CPLError( CE_Warning, CPLE_AppDefined, 
     580                 :                   "LINEFORMAT=%s not understood, use one of CRLF or LF.",
     581               0 :                   pszCRLFFormat );
     582                 : #ifdef WIN32
     583                 :         bUseCRLF = TRUE;
     584                 : #else
     585               0 :         bUseCRLF = FALSE;
     586                 : #endif
     587                 :     }
     588                 :     
     589              26 :     papoLayers[nLayers-1]->SetCRLF( bUseCRLF );
     590                 : 
     591                 : /* -------------------------------------------------------------------- */
     592                 : /*      Should we write the geometry ?                                  */
     593                 : /* -------------------------------------------------------------------- */
     594              26 :     const char *pszGeometry = CSLFetchNameValue( papszOptions, "GEOMETRY");
     595              26 :     if (pszGeometry != NULL)
     596                 :     {
     597               7 :         if (EQUAL(pszGeometry, "AS_WKT"))
     598                 :         {
     599               4 :             papoLayers[nLayers-1]->SetWriteGeometry(OGR_CSV_GEOM_AS_WKT);
     600                 :         }
     601               6 :         else if (EQUAL(pszGeometry, "AS_XYZ") ||
     602                 :                  EQUAL(pszGeometry, "AS_XY") ||
     603                 :                  EQUAL(pszGeometry, "AS_YX"))
     604                 :         {
     605               6 :             if (eGType == wkbUnknown || wkbFlatten(eGType) == wkbPoint)
     606                 :             {
     607               3 :                 papoLayers[nLayers-1]->SetWriteGeometry(EQUAL(pszGeometry, "AS_XYZ") ? OGR_CSV_GEOM_AS_XYZ :
     608                 :                                                         EQUAL(pszGeometry, "AS_XY") ?  OGR_CSV_GEOM_AS_XY :
     609               6 :                                                                                        OGR_CSV_GEOM_AS_YX);
     610                 :             }
     611                 :             else
     612                 :             {
     613                 :                 CPLError( CE_Warning, CPLE_AppDefined, 
     614                 :                           "Geometry type %s is not compatible with GEOMETRY=AS_XYZ.",
     615               0 :                           OGRGeometryTypeToName(eGType) );
     616                 :             }
     617                 :         }
     618                 :         else
     619                 :         {
     620                 :             CPLError( CE_Warning, CPLE_AppDefined, 
     621                 :                       "Unsupported value %s for creation option GEOMETRY",
     622               0 :                        pszGeometry );
     623                 :         }
     624                 :     }
     625                 : 
     626                 : /* -------------------------------------------------------------------- */
     627                 : /*      Should we create a CSVT file ?                                  */
     628                 : /* -------------------------------------------------------------------- */
     629                 : 
     630              26 :     const char *pszCreateCSVT = CSLFetchNameValue( papszOptions, "CREATE_CSVT");
     631              26 :     if (pszCreateCSVT)
     632               4 :         papoLayers[nLayers-1]->SetCreateCSVT(CSLTestBoolean(pszCreateCSVT));
     633                 : 
     634                 : /* -------------------------------------------------------------------- */
     635                 : /*      Should we write a UTF8 BOM ?                                    */
     636                 : /* -------------------------------------------------------------------- */
     637                 : 
     638              26 :     const char *pszWriteBOM = CSLFetchNameValue( papszOptions, "WRITE_BOM");
     639              26 :     if (pszWriteBOM)
     640               2 :         papoLayers[nLayers-1]->SetWriteBOM(CSLTestBoolean(pszWriteBOM));
     641                 : 
     642              26 :     return papoLayers[nLayers-1];
     643                 : }
     644                 : 
     645                 : /************************************************************************/
     646                 : /*                            DeleteLayer()                             */
     647                 : /************************************************************************/
     648                 : 
     649               1 : OGRErr OGRCSVDataSource::DeleteLayer( int iLayer )
     650                 : 
     651                 : {
     652                 :     char *pszFilename;
     653                 :     char *pszFilenameCSVT;
     654                 : 
     655                 : /* -------------------------------------------------------------------- */
     656                 : /*      Verify we are in update mode.                                   */
     657                 : /* -------------------------------------------------------------------- */
     658               1 :     if( !bUpdate )
     659                 :     {
     660                 :         CPLError( CE_Failure, CPLE_NoWriteAccess,
     661                 :                   "Data source %s opened read-only.\n"
     662                 :                   "Layer %d cannot be deleted.\n",
     663               0 :                   pszName, iLayer );
     664                 : 
     665               0 :         return OGRERR_FAILURE;
     666                 :     }
     667                 : 
     668               1 :     if( iLayer < 0 || iLayer >= nLayers )
     669                 :     {
     670                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     671                 :                   "Layer %d not in legal range of 0 to %d.", 
     672               0 :                   iLayer, nLayers-1 );
     673               0 :         return OGRERR_FAILURE;
     674                 :     }
     675                 : 
     676                 :     pszFilename = 
     677               1 :         CPLStrdup(CPLFormFilename(pszName,papoLayers[iLayer]->GetLayerDefn()->GetName(),"csv"));
     678                 :     pszFilenameCSVT = 
     679               1 :         CPLStrdup(CPLFormFilename(pszName,papoLayers[iLayer]->GetLayerDefn()->GetName(),"csvt"));
     680                 : 
     681               1 :     delete papoLayers[iLayer];
     682                 : 
     683               3 :     while( iLayer < nLayers - 1 )
     684                 :     {
     685               1 :         papoLayers[iLayer] = papoLayers[iLayer+1];
     686               1 :         iLayer++;
     687                 :     }
     688                 : 
     689               1 :     nLayers--;
     690                 : 
     691               1 :     VSIUnlink( pszFilename );
     692               1 :     CPLFree( pszFilename );
     693               1 :     VSIUnlink( pszFilenameCSVT );
     694               1 :     CPLFree( pszFilenameCSVT );
     695                 : 
     696               1 :     return OGRERR_NONE;
     697                 : }

Generated by: LCOV version 1.7