LTP GCOV extension - code coverage report
Current view: directory - ogr/ogrsf_frmts/csv - ogrcsvlayer.cpp
Test: gdal_filtered.info
Date: 2010-07-12 Instrumented lines: 303
Code covered: 92.4 % Executed lines: 280

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

Generated by: LTP GCOV extension version 1.5