LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/csv - ogrcsvlayer.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 299 277 92.6 %
Date: 2010-01-09 Functions: 12 12 100.0 %

       1                 : /******************************************************************************
       2                 :  * $Id: ogrcsvlayer.cpp 17496 2009-08-02 11:54:23Z rouault $
       3                 :  *
       4                 :  * Project:  CSV Translator
       5                 :  * Purpose:  Implements OGRCSVLayer 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 "ogr_p.h"
      35                 : 
      36                 : CPL_CVSID("$Id: ogrcsvlayer.cpp 17496 2009-08-02 11:54:23Z rouault $");
      37                 : 
      38                 : /************************************************************************/
      39                 : /*                            OGRCSVLayer()                             */
      40                 : /*                                                                      */
      41                 : /*      Note that the OGRCSVLayer assumes ownership of the passed       */
      42                 : /*      file pointer.                                                   */
      43                 : /************************************************************************/
      44                 : 
      45              51 : OGRCSVLayer::OGRCSVLayer( const char *pszLayerNameIn, 
      46                 :                           FILE * fp, const char *pszFilename, int bNew, int bInWriteMode,
      47              51 :                           char chDelimiter)
      48                 : 
      49                 : {
      50              51 :     fpCSV = fp;
      51                 : 
      52              51 :     iWktGeomReadField = -1;
      53              51 :     this->bInWriteMode = bInWriteMode;
      54              51 :     this->bNew = bNew;
      55              51 :     this->pszFilename = CPLStrdup(pszFilename);
      56              51 :     this->chDelimiter = chDelimiter;
      57                 : 
      58              51 :     bFirstFeatureAppendedDuringSession = TRUE;
      59              51 :     bUseCRLF = FALSE;
      60              51 :     bNeedRewindBeforeRead = FALSE;
      61              51 :     eGeometryFormat = OGR_CSV_GEOM_NONE;
      62                 : 
      63              51 :     nNextFID = 1;
      64                 : 
      65              51 :     poFeatureDefn = new OGRFeatureDefn( pszLayerNameIn );
      66              51 :     poFeatureDefn->Reference();
      67              51 :     poFeatureDefn->SetGeomType( wkbNone );
      68                 : 
      69              51 :     bCreateCSVT = FALSE;
      70                 : 
      71                 : /* -------------------------------------------------------------------- */
      72                 : /*      If this is not a new file, read ahead to establish if it is     */
      73                 : /*      already in CRLF (DOS) mode, or just a normal unix CR mode.      */
      74                 : /* -------------------------------------------------------------------- */
      75              51 :     if( !bNew )
      76                 :     {
      77              43 :         int nBytesRead = 0;
      78                 :         char chNewByte;
      79                 : 
      80            6015 :         while( nBytesRead < 10000 && VSIFRead( &chNewByte, 1, 1, fpCSV ) == 1 )
      81                 :         {
      82            5936 :             if( chNewByte == 13 )
      83                 :             {
      84               7 :                 bUseCRLF = TRUE;
      85               7 :                 break;
      86                 :             }
      87                 :         }
      88              43 :         VSIRewind( fpCSV );
      89                 :     }
      90                 : 
      91                 : /* -------------------------------------------------------------------- */
      92                 : /*      Check if the first record seems to be field definitions or      */
      93                 : /*      not.  We assume it is field definitions if none of the          */
      94                 : /*      values are strictly numeric.                                    */
      95                 : /* -------------------------------------------------------------------- */
      96              51 :     char **papszTokens = NULL;
      97              51 :     int nFieldCount=0, iField;
      98                 : 
      99              51 :     if( !bNew )
     100                 :     {
     101              43 :         papszTokens = CSVReadParseLine2( fpCSV, chDelimiter );
     102              43 :         nFieldCount = CSLCount( papszTokens );
     103              43 :         bHasFieldNames = TRUE;
     104                 :     }
     105                 :     else
     106               8 :         bHasFieldNames = FALSE;
     107                 : 
     108             247 :     for( iField = 0; iField < nFieldCount && bHasFieldNames; iField++ )
     109                 :     {
     110             196 :         const char *pszToken = papszTokens[iField];
     111             196 :         int bAllNumeric = TRUE;
     112                 : 
     113             196 :         if (*pszToken != '\0')
     114                 :         {
     115             588 :             while( *pszToken != '\0' && bAllNumeric )
     116                 :             {
     117             196 :                 if( *pszToken != '.' && *pszToken != '-'
     118                 :                     && (*pszToken < '0' || *pszToken > '9') )
     119             196 :                     bAllNumeric = FALSE;
     120             196 :                 pszToken++;
     121                 :             }
     122                 : 
     123             196 :             if( bAllNumeric )
     124               0 :                 bHasFieldNames = FALSE;
     125                 :         }
     126                 :     }
     127                 : 
     128              51 :     if( !bHasFieldNames )
     129               8 :         VSIRewind( fpCSV );
     130                 : 
     131                 : 
     132                 : /* -------------------------------------------------------------------- */
     133                 : /*      Search a csvt file for types                                */
     134                 : /* -------------------------------------------------------------------- */
     135              51 :     char** papszFieldTypes = NULL;
     136              51 :     if (!bNew) {
     137              43 :         char* dname = strdup(CPLGetDirname(pszFilename));
     138              43 :         char* fname = strdup(CPLGetBasename(pszFilename));
     139              43 :         FILE* fpCSVT = fopen(CPLFormFilename(dname, fname, ".csvt"), "r");
     140              43 :         free(dname);
     141              43 :         free(fname);
     142              43 :         if (fpCSVT!=NULL) {
     143              17 :             VSIRewind(fpCSVT);
     144              17 :             papszFieldTypes = CSVReadParseLine(fpCSVT);
     145              17 :             fclose(fpCSVT);
     146                 :         }
     147                 :     }
     148                 :     
     149                 : 
     150                 : /* -------------------------------------------------------------------- */
     151                 : /*      Build field definitions.                                        */
     152                 : /* -------------------------------------------------------------------- */
     153             247 :     for( iField = 0; iField < nFieldCount; iField++ )
     154                 :     {
     155             196 :         char *pszFieldName = NULL;
     156                 :         char szFieldNameBuffer[100];
     157                 : 
     158             196 :         if( bHasFieldNames )
     159                 :         {
     160             196 :             pszFieldName = papszTokens[iField];
     161                 : 
     162                 :             // trim white space. 
     163             392 :             while( *pszFieldName == ' ' )
     164               0 :                 pszFieldName++;
     165                 : 
     166             588 :             while( pszFieldName[0] != '\0' 
     167             196 :                 && pszFieldName[strlen(pszFieldName)-1] == ' ' )
     168               0 :                 pszFieldName[strlen(pszFieldName)-1] = '\0';
     169                 : 
     170             196 :             if (*pszFieldName == '\0')
     171               0 :                 pszFieldName = NULL;
     172                 :         }
     173                 : 
     174             196 :         if (pszFieldName == NULL)
     175                 :         {
     176               0 :             pszFieldName = szFieldNameBuffer;
     177               0 :             sprintf( szFieldNameBuffer, "field_%d", iField+1 );
     178                 :         }
     179                 : 
     180             196 :         OGRFieldDefn oField(pszFieldName, OFTString);
     181             196 :         if (papszFieldTypes!=NULL && iField<CSLCount(papszFieldTypes)) {
     182                 : 
     183              92 :             char* pszLeftParenthesis = strchr(papszFieldTypes[iField], '(');
     184             128 :             if (pszLeftParenthesis && pszLeftParenthesis != papszFieldTypes[iField] &&
     185              36 :                 pszLeftParenthesis[1] >= '0' && pszLeftParenthesis[1] <= '9')
     186                 :             {
     187              18 :                 int nWidth = 0;
     188              18 :                 int nPrecision = 0;
     189                 : 
     190              18 :                 char* pszDot = strchr(pszLeftParenthesis, '.');
     191              18 :                 if (pszDot) *pszDot = 0;
     192              18 :                 *pszLeftParenthesis = 0;
     193                 : 
     194              18 :                 if (pszLeftParenthesis[-1] == ' ')
     195               1 :                     pszLeftParenthesis[-1] = 0;
     196                 : 
     197              18 :                 nWidth = atoi(pszLeftParenthesis+1);
     198              18 :                 if (pszDot)
     199               6 :                     nPrecision = atoi(pszDot+1);
     200                 : 
     201              18 :                 oField.SetWidth(nWidth);
     202              18 :                 oField.SetPrecision(nPrecision);
     203                 :             }
     204                 : 
     205              92 :             if (EQUAL(papszFieldTypes[iField], "Integer"))
     206              12 :                 oField.SetType(OFTInteger);
     207              80 :             else if (EQUAL(papszFieldTypes[iField], "Real"))
     208              37 :                 oField.SetType(OFTReal);
     209              43 :             else if (EQUAL(papszFieldTypes[iField], "String"))
     210              25 :                 oField.SetType(OFTString);
     211              18 :             else if (EQUAL(papszFieldTypes[iField], "Date"))
     212               6 :                 oField.SetType(OFTDate); 
     213              12 :             else if (EQUAL(papszFieldTypes[iField], "Time"))
     214               6 :                 oField.SetType(OFTTime);
     215               6 :             else if (EQUAL(papszFieldTypes[iField], "DateTime"))
     216               6 :                 oField.SetType(OFTDateTime);
     217                 :             else
     218               0 :                 CPLError(CE_Warning, CPLE_NotSupported, "Unknown type : %s", papszFieldTypes[iField]);
     219                 :         }
     220                 : 
     221             196 :         poFeatureDefn->AddFieldDefn( &oField );
     222                 : 
     223             196 :         if( EQUAL(oField.GetNameRef(),"WKT")
     224                 :             && oField.GetType() == OFTString 
     225                 :             && iWktGeomReadField == -1 )
     226                 :         {
     227              10 :             iWktGeomReadField = iField;
     228              10 :             poFeatureDefn->SetGeomType( wkbUnknown );
     229                 :         }
     230                 :     }
     231                 : 
     232              51 :     CSLDestroy( papszTokens );
     233              51 :     CSLDestroy( papszFieldTypes );
     234              51 : }
     235                 : 
     236                 : /************************************************************************/
     237                 : /*                            ~OGRCSVLayer()                            */
     238                 : /************************************************************************/
     239                 : 
     240             102 : OGRCSVLayer::~OGRCSVLayer()
     241                 : 
     242                 : {
     243              51 :     if( m_nFeaturesRead > 0 && poFeatureDefn != NULL )
     244                 :     {
     245                 :         CPLDebug( "CSV", "%d features read on layer '%s'.",
     246                 :                   (int) m_nFeaturesRead, 
     247              29 :                   poFeatureDefn->GetName() );
     248                 :     }
     249                 : 
     250              51 :     poFeatureDefn->Release();
     251              51 :     CPLFree(pszFilename);
     252                 :     
     253              51 :     VSIFClose( fpCSV );
     254             102 : }
     255                 : 
     256                 : /************************************************************************/
     257                 : /*                            ResetReading()                            */
     258                 : /************************************************************************/
     259                 : 
     260              73 : void OGRCSVLayer::ResetReading()
     261                 : 
     262                 : {
     263              73 :     VSIRewind( fpCSV );
     264                 : 
     265              73 :     if( bHasFieldNames )
     266              73 :         CSLDestroy( CSVReadParseLine2( fpCSV, chDelimiter ) );
     267                 : 
     268              73 :     bNeedRewindBeforeRead = FALSE;
     269                 : 
     270              73 :     nNextFID = 1;
     271              73 : }
     272                 : 
     273                 : /************************************************************************/
     274                 : /*                      GetNextUnfilteredFeature()                      */
     275                 : /************************************************************************/
     276                 : 
     277             226 : OGRFeature * OGRCSVLayer::GetNextUnfilteredFeature()
     278                 : 
     279                 : {
     280                 : /* -------------------------------------------------------------------- */
     281                 : /*      Read the CSV record.                                            */
     282                 : /* -------------------------------------------------------------------- */
     283             226 :     char **papszTokens = CSVReadParseLine2( fpCSV, chDelimiter );
     284                 : 
     285             226 :     if( papszTokens == NULL )
     286              51 :         return NULL;
     287                 : 
     288                 : /* -------------------------------------------------------------------- */
     289                 : /*      Create the OGR feature.                                         */
     290                 : /* -------------------------------------------------------------------- */
     291                 :     OGRFeature *poFeature;
     292                 : 
     293             175 :     poFeature = new OGRFeature( poFeatureDefn );
     294                 : 
     295                 : /* -------------------------------------------------------------------- */
     296                 : /*      Set attributes for any indicated attribute records.             */
     297                 : /* -------------------------------------------------------------------- */
     298                 :     int         iAttr;
     299             175 :     int         nAttrCount = MIN(CSLCount(papszTokens),
     300                 :                                  poFeatureDefn->GetFieldCount() );
     301                 :     
     302            1010 :     for( iAttr = 0; iAttr < nAttrCount; iAttr++)
     303                 :     {
     304             835 :         if( iAttr == iWktGeomReadField && papszTokens[iAttr][0] != '\0' )
     305                 :         {
     306              15 :             char *pszWKT = papszTokens[iAttr];
     307              15 :             OGRGeometry *poGeom = NULL;
     308                 : 
     309              15 :             if( OGRGeometryFactory::createFromWkt( &pszWKT, NULL, &poGeom )
     310                 :                 == OGRERR_NONE )
     311              15 :                 poFeature->SetGeometryDirectly( poGeom );
     312                 :         }
     313                 : 
     314             835 :         if (poFeatureDefn->GetFieldDefn(iAttr)->GetType() != OFTString)
     315                 :         {
     316             281 :             if (papszTokens[iAttr][0] != '\0')
     317             184 :                 poFeature->SetField( iAttr, papszTokens[iAttr] );
     318                 :         }
     319                 :         else
     320             554 :             poFeature->SetField( iAttr, papszTokens[iAttr] );
     321                 : 
     322                 :     }
     323                 : 
     324             175 :     CSLDestroy( papszTokens );
     325                 : 
     326                 : /* -------------------------------------------------------------------- */
     327                 : /*      Translate the record id.                                        */
     328                 : /* -------------------------------------------------------------------- */
     329             175 :     poFeature->SetFID( nNextFID++ );
     330                 : 
     331             175 :     m_nFeaturesRead++;
     332                 : 
     333             175 :     return poFeature;
     334                 : }
     335                 : 
     336                 : 
     337                 : /************************************************************************/
     338                 : /*                           GetNextFeature()                           */
     339                 : /************************************************************************/
     340                 : 
     341             210 : OGRFeature *OGRCSVLayer::GetNextFeature()
     342                 : 
     343                 : {
     344             210 :     OGRFeature  *poFeature = NULL;
     345                 : 
     346             210 :     if( bNeedRewindBeforeRead )
     347               3 :         ResetReading();
     348                 :     
     349                 : /* -------------------------------------------------------------------- */
     350                 : /*      Read features till we find one that satisfies our current       */
     351                 : /*      spatial criteria.                                               */
     352                 : /* -------------------------------------------------------------------- */
     353              16 :     while( TRUE )
     354                 :     {
     355             226 :         poFeature = GetNextUnfilteredFeature();
     356             226 :         if( poFeature == NULL )
     357              51 :             break;
     358                 : 
     359             175 :         if( (m_poFilterGeom == NULL
     360                 :             || FilterGeometry( poFeature->GetGeometryRef() ) )
     361                 :             && (m_poAttrQuery == NULL
     362                 :                 || m_poAttrQuery->Evaluate( poFeature )) )
     363             159 :             break;
     364                 : 
     365              16 :         delete poFeature;
     366                 :     }
     367                 : 
     368             210 :     return poFeature;
     369                 : }
     370                 : 
     371                 : /************************************************************************/
     372                 : /*                           TestCapability()                           */
     373                 : /************************************************************************/
     374                 : 
     375               5 : int OGRCSVLayer::TestCapability( const char * pszCap )
     376                 : 
     377                 : {
     378               5 :     if( EQUAL(pszCap,OLCSequentialWrite) )
     379               2 :         return bInWriteMode;
     380               3 :     else if( EQUAL(pszCap,OLCCreateField) )
     381               0 :         return bNew && !bHasFieldNames;
     382                 :     else
     383               3 :         return FALSE;
     384                 : }
     385                 : 
     386                 : /************************************************************************/
     387                 : /*                            CreateField()                             */
     388                 : /************************************************************************/
     389                 : 
     390              19 : OGRErr OGRCSVLayer::CreateField( OGRFieldDefn *poNewField, int bApproxOK )
     391                 : 
     392                 : {
     393                 : /* -------------------------------------------------------------------- */
     394                 : /*      If we have already written our field names, then we are not     */
     395                 : /*      allowed to add new fields.                                      */
     396                 : /* -------------------------------------------------------------------- */
     397              19 :     if( bHasFieldNames || !bNew )
     398                 :     {
     399                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     400               0 :                   "Unable to create new fields after first feature written.");
     401               0 :         return OGRERR_FAILURE;
     402                 :     }
     403                 : 
     404                 : /* -------------------------------------------------------------------- */
     405                 : /*      Does this duplicate an existing field?                          */
     406                 : /* -------------------------------------------------------------------- */
     407              19 :     if( poFeatureDefn->GetFieldIndex( poNewField->GetNameRef() ) != -1 )
     408                 :     {
     409                 :         CPLError( CE_Failure, CPLE_AppDefined,
     410                 :                   "Attempt to create field %s, but a field with this name already exists.",
     411               0 :                   poNewField->GetNameRef() );
     412                 : 
     413               0 :         return OGRERR_FAILURE;
     414                 :     }
     415                 : 
     416                 : /* -------------------------------------------------------------------- */
     417                 : /*      Is this a legal field type for CSV?  For now we only allow      */
     418                 : /*      simple integer, real and string fields.                         */
     419                 : /* -------------------------------------------------------------------- */
     420              19 :     switch( poNewField->GetType() )
     421                 :     {
     422                 :       case OFTInteger:
     423                 :       case OFTReal:
     424                 :       case OFTString:
     425                 :         // these types are OK.
     426              16 :         break;
     427                 : 
     428                 :       default:
     429               3 :         if( bApproxOK )
     430                 :         {
     431                 :             CPLError( CE_Warning, CPLE_AppDefined, 
     432                 :                       "Attempt to create field of type %s, but this is not supported\n"
     433                 :                       "for .csv files.  Just treating as a plain string.",
     434               3 :                       poNewField->GetFieldTypeName( poNewField->GetType() ) );
     435                 :         }
     436                 :         else
     437                 :         {
     438                 :             CPLError( CE_Failure, CPLE_AppDefined, 
     439                 :                       "Attempt to create field of type %s, but this is not supported\n"
     440                 :                       "for .csv files.",
     441               0 :                       poNewField->GetFieldTypeName( poNewField->GetType() ) );
     442               0 :             return OGRERR_FAILURE;
     443                 :         }
     444                 :     }
     445                 :     
     446                 : /* -------------------------------------------------------------------- */
     447                 : /*      Seems ok, add to field list.                                    */
     448                 : /* -------------------------------------------------------------------- */
     449              19 :     poFeatureDefn->AddFieldDefn( poNewField );
     450                 : 
     451              19 :     return OGRERR_NONE;
     452                 : }
     453                 : 
     454                 : /************************************************************************/
     455                 : /*                           CreateFeature()                            */
     456                 : /************************************************************************/
     457                 : 
     458              23 : OGRErr OGRCSVLayer::CreateFeature( OGRFeature *poNewFeature )
     459                 : 
     460                 : {
     461                 :     int iField;
     462                 : 
     463              23 :     if( !bInWriteMode )
     464                 :     {
     465                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     466               0 :             "The CreateFeature() operation is not permitted on a read-only CSV." );
     467               0 :         return OGRERR_FAILURE;
     468                 :     }
     469                 : 
     470                 :     /* If we need rewind, it means that we have just written a feature before */
     471                 :     /* so there's no point seeking to the end of the file, as we're already */
     472                 :     /* at the end */
     473              23 :     int bNeedSeekEnd = !bNeedRewindBeforeRead;
     474                 : 
     475              23 :     bNeedRewindBeforeRead = TRUE;
     476                 : 
     477                 : /* -------------------------------------------------------------------- */
     478                 : /*      Write field names if we haven't written them yet.               */
     479                 : /*      Write .csvt file if needed                                      */
     480                 : /* -------------------------------------------------------------------- */
     481              23 :     if( !bHasFieldNames )
     482                 :     {
     483               8 :         FILE* fpCSVT = NULL;
     484               8 :         if (bCreateCSVT)
     485                 :         {
     486               4 :             char* pszDirName = CPLStrdup(CPLGetDirname(pszFilename));
     487               4 :             char* pszBaseName = CPLStrdup(CPLGetBasename(pszFilename));
     488               4 :             fpCSVT = fopen(CPLFormFilename(pszDirName, pszBaseName, ".csvt"), "wt");
     489               4 :             CPLFree(pszDirName);
     490               4 :             CPLFree(pszBaseName);
     491                 :         }
     492                 : 
     493               8 :         if (eGeometryFormat == OGR_CSV_GEOM_AS_WKT)
     494                 :         {
     495               1 :             VSIFPrintf( fpCSV, "%s", "WKT");
     496               1 :             if (fpCSVT) VSIFPrintf( fpCSVT, "%s", "String");
     497               1 :             if (poFeatureDefn->GetFieldCount() > 0)
     498                 :             {
     499               1 :                 VSIFPrintf( fpCSV, "%c", chDelimiter );
     500               1 :                 if (fpCSVT) VSIFPrintf( fpCSVT, "%s", ",");
     501                 :             }
     502                 :         }
     503               7 :         else if (eGeometryFormat == OGR_CSV_GEOM_AS_XYZ)
     504                 :         {
     505               1 :             VSIFPrintf( fpCSV, "X%cY%cZ", chDelimiter, chDelimiter);
     506               1 :             if (fpCSVT) VSIFPrintf( fpCSVT, "%s", "Real,Real,Real");
     507               1 :             if (poFeatureDefn->GetFieldCount() > 0)
     508                 :             {
     509               1 :                 VSIFPrintf( fpCSV, "%c", chDelimiter );
     510               1 :                 if (fpCSVT) VSIFPrintf( fpCSVT, "%s", ",");
     511                 :             }
     512                 :         }
     513               6 :         else if (eGeometryFormat == OGR_CSV_GEOM_AS_XY)
     514                 :         {
     515               1 :             VSIFPrintf( fpCSV, "X%cY", chDelimiter);
     516               1 :             if (fpCSVT) VSIFPrintf( fpCSVT, "%s", "Real,Real");
     517               1 :             if (poFeatureDefn->GetFieldCount() > 0)
     518                 :             {
     519               1 :                 VSIFPrintf( fpCSV, "%c", chDelimiter );
     520               1 :                 if (fpCSVT) VSIFPrintf( fpCSVT, "%s", ",");
     521                 :             }
     522                 :         }
     523               5 :         else if (eGeometryFormat == OGR_CSV_GEOM_AS_YX)
     524                 :         {
     525               1 :             VSIFPrintf( fpCSV, "Y%cX", chDelimiter);
     526               1 :             if (fpCSVT) VSIFPrintf( fpCSVT, "%s", "Real,Real");
     527               1 :             if (poFeatureDefn->GetFieldCount() > 0)
     528                 :             {
     529               1 :                 VSIFPrintf( fpCSV, "%c", chDelimiter );
     530               1 :                 if (fpCSVT) VSIFPrintf( fpCSVT, "%s", ",");
     531                 :             }
     532                 :         }
     533                 : 
     534              27 :         for( iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
     535                 :         {
     536                 :             char *pszEscaped;
     537                 : 
     538              19 :             if( iField > 0 )
     539                 :             {
     540              11 :                 VSIFPrintf( fpCSV, "%c", chDelimiter );
     541              11 :                 if (fpCSVT) VSIFPrintf( fpCSVT, "%s", ",");
     542                 :             }
     543                 : 
     544                 :             pszEscaped = 
     545                 :                 CPLEscapeString( poFeatureDefn->GetFieldDefn(iField)->GetNameRef(), 
     546              19 :                                  -1, CPLES_CSV );
     547                 : 
     548              19 :             VSIFPrintf( fpCSV, "%s", pszEscaped );
     549              19 :             CPLFree( pszEscaped );
     550                 : 
     551              19 :             if (fpCSVT)
     552                 :             {
     553              12 :                 switch( poFeatureDefn->GetFieldDefn(iField)->GetType() )
     554                 :                 {
     555               2 :                     case OFTInteger:  VSIFPrintf( fpCSVT, "%s", "Integer"); break;
     556               2 :                     case OFTReal:     VSIFPrintf( fpCSVT, "%s", "Real"); break;
     557               1 :                     case OFTDate:     VSIFPrintf( fpCSVT, "%s", "Date"); break;
     558               1 :                     case OFTTime:     VSIFPrintf( fpCSVT, "%s", "Time"); break;
     559               1 :                     case OFTDateTime: VSIFPrintf( fpCSVT, "%s", "DateTime"); break;
     560               5 :                     default:          VSIFPrintf( fpCSVT, "%s", "String"); break;
     561                 :                 }
     562                 : 
     563              12 :                 int nWidth = poFeatureDefn->GetFieldDefn(iField)->GetWidth();
     564              12 :                 int nPrecision = poFeatureDefn->GetFieldDefn(iField)->GetPrecision();
     565              12 :                 if (nWidth != 0)
     566                 :                 {
     567               3 :                     if (nPrecision != 0)
     568               1 :                         VSIFPrintf( fpCSVT, "(%d.%d)", nWidth, nPrecision);
     569                 :                     else
     570               2 :                         VSIFPrintf( fpCSVT, "(%d)", nWidth);
     571                 :                 }
     572                 :             }
     573                 :         }
     574               8 :         if( bUseCRLF )
     575                 :         {
     576               1 :             VSIFPutc( 13, fpCSV );
     577               1 :             if (fpCSVT) VSIFPutc( 13, fpCSVT );
     578                 :         }
     579               8 :         VSIFPutc( '\n', fpCSV );
     580               8 :         if (fpCSVT) VSIFPutc( '\n', fpCSVT );
     581               8 :         if (fpCSVT) VSIFClose(fpCSVT);
     582                 : 
     583               8 :         bHasFieldNames = TRUE;
     584               8 :         bNeedSeekEnd = FALSE;
     585                 :     }
     586                 : 
     587                 : /* -------------------------------------------------------------------- */
     588                 : /*      Make sure we are at the end of the file.                        */
     589                 : /* -------------------------------------------------------------------- */
     590              23 :     if (bNeedSeekEnd)
     591                 :     {
     592               4 :         if (bFirstFeatureAppendedDuringSession)
     593                 :         {
     594                 :             /* Add a newline character to the end of the file if necessary */
     595               4 :             bFirstFeatureAppendedDuringSession = FALSE;
     596               4 :             VSIFSeek( fpCSV, 0, SEEK_END );
     597               4 :             VSIFSeek( fpCSV, VSIFTell(fpCSV) - 1, SEEK_SET);
     598               4 :             char chLast = VSIFGetc( fpCSV );
     599               4 :             VSIFSeek( fpCSV, 0, SEEK_END );
     600               4 :             if (chLast != '\n')
     601                 :             {
     602               0 :                 if( bUseCRLF )
     603               0 :                     VSIFPutc( 13, fpCSV );
     604               0 :                 VSIFPutc( '\n', fpCSV );
     605                 :             }
     606                 :         }
     607                 :         else
     608                 :         {
     609               0 :             VSIFSeek( fpCSV, 0, SEEK_END );
     610                 :         }
     611                 :     }
     612                 : 
     613                 : /* -------------------------------------------------------------------- */
     614                 : /*      Write out the geometry                                          */
     615                 : /* -------------------------------------------------------------------- */
     616              23 :     if (eGeometryFormat == OGR_CSV_GEOM_AS_WKT)
     617                 :     {
     618               1 :         OGRGeometry     *poGeom = poNewFeature->GetGeometryRef();
     619               1 :         char* pszWKT = NULL;
     620               1 :         if (poGeom && poGeom->exportToWkt(&pszWKT) == OGRERR_NONE)
     621                 :         {
     622               1 :             VSIFPrintf( fpCSV, "\"%s\"", pszWKT);
     623                 :         }
     624                 :         else
     625                 :         {
     626               0 :             VSIFPrintf( fpCSV, "\"\"");
     627                 :         }
     628               1 :         CPLFree(pszWKT);
     629               1 :         if (poFeatureDefn->GetFieldCount() > 0)
     630               1 :             VSIFPrintf( fpCSV, "%c", chDelimiter);
     631                 :     }
     632              22 :     else if (eGeometryFormat == OGR_CSV_GEOM_AS_XYZ ||
     633                 :              eGeometryFormat == OGR_CSV_GEOM_AS_XY ||
     634                 :              eGeometryFormat == OGR_CSV_GEOM_AS_YX)
     635                 :     {
     636               4 :         OGRGeometry     *poGeom = poNewFeature->GetGeometryRef();
     637               4 :         if (poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbPoint)
     638                 :         {
     639               3 :             OGRPoint* poPoint = (OGRPoint*) poGeom;
     640                 :             char szBuffer[75];
     641               3 :             if (eGeometryFormat == OGR_CSV_GEOM_AS_XYZ )
     642               1 :                 OGRMakeWktCoordinate(szBuffer, poPoint->getX(), poPoint->getY(), poPoint->getZ(), 3);
     643               2 :             else if (eGeometryFormat == OGR_CSV_GEOM_AS_XY )
     644               1 :                 OGRMakeWktCoordinate(szBuffer, poPoint->getX(), poPoint->getY(), 0, 2);
     645                 :             else
     646               1 :                 OGRMakeWktCoordinate(szBuffer, poPoint->getY(), poPoint->getX(), 0, 2);
     647               3 :             char* pc = szBuffer;
     648              17 :             while(*pc != '\0')
     649                 :             {
     650              11 :                 if (*pc == ' ')
     651               4 :                     *pc = chDelimiter;
     652              11 :                 pc ++;
     653                 :             }
     654               3 :             VSIFPrintf( fpCSV, "%s", szBuffer );
     655                 :         }
     656                 :         else
     657                 :         {
     658               1 :             VSIFPrintf( fpCSV, "%c", chDelimiter );
     659               1 :             if (eGeometryFormat == OGR_CSV_GEOM_AS_XYZ)
     660               0 :                 VSIFPrintf( fpCSV, "%c", chDelimiter );
     661                 :         }
     662               4 :         if (poFeatureDefn->GetFieldCount() > 0)
     663               4 :             VSIFPrintf( fpCSV, "%c", chDelimiter );
     664                 :     }
     665                 : 
     666                 : /* -------------------------------------------------------------------- */
     667                 : /*      Write out all the field values.                                 */
     668                 : /* -------------------------------------------------------------------- */
     669              82 :     for( iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
     670                 :     {
     671                 :         char *pszEscaped;
     672                 :         
     673              59 :         if( iField > 0 )
     674              36 :             fprintf( fpCSV, "%c", chDelimiter );
     675                 :         
     676                 :         pszEscaped = 
     677                 :             CPLEscapeString( poNewFeature->GetFieldAsString(iField),
     678              59 :                              -1, CPLES_CSV );
     679                 :         
     680              59 :         VSIFWrite( pszEscaped, 1, strlen(pszEscaped), fpCSV );
     681              59 :         CPLFree( pszEscaped );
     682                 :     }
     683                 :     
     684              23 :     if( bUseCRLF )
     685               5 :         VSIFPutc( 13, fpCSV );
     686              23 :     VSIFPutc( '\n', fpCSV );
     687                 : 
     688              23 :     return OGRERR_NONE;
     689                 : }
     690                 : 
     691                 : /************************************************************************/
     692                 : /*                              SetCRLF()                               */
     693                 : /************************************************************************/
     694                 : 
     695               8 : void OGRCSVLayer::SetCRLF( int bNewValue )
     696                 : 
     697                 : {
     698               8 :     bUseCRLF = bNewValue;
     699               8 : }
     700                 : 
     701                 : /************************************************************************/
     702                 : /*                       SetWriteGeometry()                             */
     703                 : /************************************************************************/
     704                 : 
     705               4 : void OGRCSVLayer::SetWriteGeometry(OGRCSVGeometryFormat eGeometryFormat)
     706                 : {
     707               4 :     this->eGeometryFormat = eGeometryFormat;
     708               4 : }
     709                 : 
     710                 : /************************************************************************/
     711                 : /*                          SetCreateCSVT()                             */
     712                 : /************************************************************************/
     713                 : 
     714               4 : void OGRCSVLayer::SetCreateCSVT(int bCreateCSVT)
     715                 : {
     716               4 :     this->bCreateCSVT = bCreateCSVT;
     717               4 : }

Generated by: LCOV version 1.7