LCOV - code coverage report
Current view: directory - apps - ogr2ogr.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 1027 735 71.6 %
Date: 2012-04-28 Functions: 26 15 57.7 %

       1                 : /******************************************************************************
       2                 :  * $Id: ogr2ogr.cpp 24202 2012-04-06 19:10:22Z rouault $
       3                 :  *
       4                 :  * Project:  OpenGIS Simple Features Reference Implementation
       5                 :  * Purpose:  Simple client for translating between formats.
       6                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 1999, Frank Warmerdam
      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 "ogrsf_frmts.h"
      31                 : #include "ogr_p.h"
      32                 : #include "cpl_conv.h"
      33                 : #include "cpl_string.h"
      34                 : #include "ogr_api.h"
      35                 : #include "gdal.h"
      36                 : 
      37                 : CPL_CVSID("$Id: ogr2ogr.cpp 24202 2012-04-06 19:10:22Z rouault $");
      38                 : 
      39                 : static int bSkipFailures = FALSE;
      40                 : static int nGroupTransactions = 200;
      41                 : static int bPreserveFID = FALSE;
      42                 : static int nFIDToFetch = OGRNullFID;
      43                 : 
      44                 : static void Usage(int bShort = TRUE);
      45                 : 
      46                 : typedef enum
      47                 : {
      48                 :     NONE,
      49                 :     SEGMENTIZE,
      50                 :     SIMPLIFY_PRESERVE_TOPOLOGY,
      51                 : } GeomOperation;
      52                 : 
      53                 : static int TranslateLayer( OGRDataSource *poSrcDS, 
      54                 :                            OGRLayer * poSrcLayer,
      55                 :                            OGRDataSource *poDstDS,
      56                 :                            char ** papszLSCO,
      57                 :                            const char *pszNewLayerName,
      58                 :                            int bTransform, 
      59                 :                            OGRSpatialReference *poOutputSRS,
      60                 :                            int bNullifyOutputSRS,
      61                 :                            OGRSpatialReference *poSourceSRS,
      62                 :                            char **papszSelFields,
      63                 :                            int bAppend, int eGType,
      64                 :                            int bOverwrite,
      65                 :                            GeomOperation eGeomOp,
      66                 :                            double dfGeomOpParam,
      67                 :                            char** papszFieldTypesToString,
      68                 :                            long nCountLayerFeatures,
      69                 :                            int bWrapDateline,
      70                 :                            OGRGeometry* poClipSrc,
      71                 :                            OGRGeometry *poClipDst,
      72                 :                            int bExplodeCollections,
      73                 :                            const char* pszZField,
      74                 :                            const char* pszWHERE,
      75                 :                            GDALProgressFunc pfnProgress,
      76                 :                            void *pProgressArg);
      77                 : 
      78                 : 
      79                 : /* -------------------------------------------------------------------- */
      80                 : /*                  CheckDestDataSourceNameConsistency()                */
      81                 : /* -------------------------------------------------------------------- */
      82                 : 
      83                 : static
      84              72 : void CheckDestDataSourceNameConsistency(const char* pszDestFilename,
      85                 :                                         const char* pszDriverName)
      86                 : {
      87                 :     int i;
      88              72 :     char* pszDestExtension = CPLStrdup(CPLGetExtension(pszDestFilename));
      89                 : 
      90                 :     /* TODO: Would be good to have driver metadata like for GDAL drivers ! */
      91                 :     static const char* apszExtensions[][2] = { { "shp"    , "ESRI Shapefile" },
      92                 :                                                { "dbf"    , "ESRI Shapefile" },
      93                 :                                                { "sqlite" , "SQLite" },
      94                 :                                                { "db"     , "SQLite" },
      95                 :                                                { "mif"    , "MapInfo File" },
      96                 :                                                { "tab"    , "MapInfo File" },
      97                 :                                                { "s57"    , "S57" },
      98                 :                                                { "bna"    , "BNA" },
      99                 :                                                { "csv"    , "CSV" },
     100                 :                                                { "gml"    , "GML" },
     101                 :                                                { "kml"    , "KML/LIBKML" },
     102                 :                                                { "kmz"    , "LIBKML" },
     103                 :                                                { "json"   , "GeoJSON" },
     104                 :                                                { "geojson", "GeoJSON" },
     105                 :                                                { "dxf"    , "DXF" },
     106                 :                                                { "gdb"    , "FileGDB" },
     107                 :                                                { "pix"    , "PCIDSK" },
     108                 :                                                { "sql"    , "PGDump" },
     109                 :                                                { "gtm"    , "GPSTrackMaker" },
     110                 :                                                { "gmt"    , "GMT" },
     111                 :                                                { NULL, NULL }
     112                 :                                               };
     113                 :     static const char* apszBeginName[][2] =  { { "PG:"      , "PG" },
     114                 :                                                { "MySQL:"   , "MySQL" },
     115                 :                                                { "CouchDB:" , "CouchDB" },
     116                 :                                                { "GFT:"     , "GFT" },
     117                 :                                                { "MSSQL:"   , "MSSQLSpatial" },
     118                 :                                                { "ODBC:"    , "ODBC" },
     119                 :                                                { "OCI:"     , "OCI" },
     120                 :                                                { "SDE:"     , "SDE" },
     121                 :                                                { "WFS:"     , "WFS" },
     122                 :                                                { NULL, NULL }
     123                 :                                              };
     124                 : 
     125            1512 :     for(i=0; apszExtensions[i][0] != NULL; i++)
     126                 :     {
     127            1440 :         if (EQUAL(pszDestExtension, apszExtensions[i][0]) && !EQUAL(pszDriverName, apszExtensions[i][1]))
     128                 :         {
     129                 :             fprintf(stderr,
     130                 :                     "Warning: The target file has a '%s' extension, which is normally used by the %s driver,\n"
     131                 :                     "but the requested output driver is %s. Is it really what you want ?\n",
     132                 :                     pszDestExtension,
     133                 :                     apszExtensions[i][1],
     134               0 :                     pszDriverName);
     135               0 :             break;
     136                 :         }
     137                 :     }
     138                 : 
     139             720 :     for(i=0; apszBeginName[i][0] != NULL; i++)
     140                 :     {
     141             648 :         if (EQUALN(pszDestFilename, apszBeginName[i][0], strlen(apszBeginName[i][0])) &&
     142                 :             !EQUAL(pszDriverName, apszBeginName[i][1]))
     143                 :         {
     144                 :             fprintf(stderr,
     145                 :                     "Warning: The target file has a name which is normally recognized by the %s driver,\n"
     146                 :                     "but the requested output driver is %s. Is it really what you want ?\n",
     147                 :                     apszBeginName[i][1],
     148               0 :                     pszDriverName);
     149               0 :             break;
     150                 :         }
     151                 :     }
     152                 : 
     153              72 :     CPLFree(pszDestExtension);
     154              72 : }
     155                 : 
     156                 : /************************************************************************/
     157                 : /*                            IsNumber()                               */
     158                 : /************************************************************************/
     159                 : 
     160              10 : static int IsNumber(const char* pszStr)
     161                 : {
     162              10 :     if (*pszStr == '-' || *pszStr == '+')
     163               0 :         pszStr ++;
     164              10 :     if (*pszStr == '.')
     165               0 :         pszStr ++;
     166              10 :     return (*pszStr >= '0' && *pszStr <= '9');
     167                 : }
     168                 : 
     169                 : /************************************************************************/
     170                 : /*                           LoadGeometry()                             */
     171                 : /************************************************************************/
     172                 : 
     173               4 : static OGRGeometry* LoadGeometry( const char* pszDS,
     174                 :                                   const char* pszSQL,
     175                 :                                   const char* pszLyr,
     176                 :                                   const char* pszWhere)
     177                 : {
     178                 :     OGRDataSource       *poDS;
     179                 :     OGRLayer            *poLyr;
     180                 :     OGRFeature          *poFeat;
     181               4 :     OGRGeometry         *poGeom = NULL;
     182                 :         
     183               4 :     poDS = OGRSFDriverRegistrar::Open( pszDS, FALSE );
     184               4 :     if (poDS == NULL)
     185               0 :         return NULL;
     186                 : 
     187               4 :     if (pszSQL != NULL)
     188               2 :         poLyr = poDS->ExecuteSQL( pszSQL, NULL, NULL ); 
     189               2 :     else if (pszLyr != NULL)
     190               0 :         poLyr = poDS->GetLayerByName(pszLyr);
     191                 :     else
     192               2 :         poLyr = poDS->GetLayer(0);
     193                 :         
     194               4 :     if (poLyr == NULL)
     195                 :     {
     196               0 :         fprintf( stderr, "Failed to identify source layer from datasource.\n" );
     197               0 :         OGRDataSource::DestroyDataSource(poDS);
     198               0 :         return NULL;
     199                 :     }
     200                 :     
     201               4 :     if (pszWhere)
     202               2 :         poLyr->SetAttributeFilter(pszWhere);
     203                 :         
     204              12 :     while ((poFeat = poLyr->GetNextFeature()) != NULL)
     205                 :     {
     206               4 :         OGRGeometry* poSrcGeom = poFeat->GetGeometryRef();
     207               4 :         if (poSrcGeom)
     208                 :         {
     209               4 :             OGRwkbGeometryType eType = wkbFlatten( poSrcGeom->getGeometryType() );
     210                 :             
     211               4 :             if (poGeom == NULL)
     212               4 :                 poGeom = OGRGeometryFactory::createGeometry( wkbMultiPolygon );
     213                 : 
     214               4 :             if( eType == wkbPolygon )
     215               4 :                 ((OGRGeometryCollection*)poGeom)->addGeometry( poSrcGeom );
     216               0 :             else if( eType == wkbMultiPolygon )
     217                 :             {
     218                 :                 int iGeom;
     219               0 :                 int nGeomCount = OGR_G_GetGeometryCount( (OGRGeometryH)poSrcGeom );
     220                 : 
     221               0 :                 for( iGeom = 0; iGeom < nGeomCount; iGeom++ )
     222                 :                 {
     223                 :                     ((OGRGeometryCollection*)poGeom)->addGeometry(
     224               0 :                                 ((OGRGeometryCollection*)poSrcGeom)->getGeometryRef(iGeom) );
     225                 :                 }
     226                 :             }
     227                 :             else
     228                 :             {
     229               0 :                 fprintf( stderr, "ERROR: Geometry not of polygon type.\n" );
     230               0 :                 OGRGeometryFactory::destroyGeometry(poGeom);
     231               0 :                 OGRFeature::DestroyFeature(poFeat);
     232               0 :                 if( pszSQL != NULL )
     233               0 :                     poDS->ReleaseResultSet( poLyr );
     234               0 :                 OGRDataSource::DestroyDataSource(poDS);
     235               0 :                 return NULL;
     236                 :             }
     237                 :         }
     238                 :     
     239               4 :         OGRFeature::DestroyFeature(poFeat);
     240                 :     }
     241                 :     
     242               4 :     if( pszSQL != NULL )
     243               2 :         poDS->ReleaseResultSet( poLyr );
     244               4 :     OGRDataSource::DestroyDataSource(poDS);
     245                 :     
     246               4 :     return poGeom;
     247                 : }
     248                 : 
     249                 : 
     250                 : /************************************************************************/
     251                 : /*                     OGRSplitListFieldLayer                           */
     252                 : /************************************************************************/
     253                 : 
     254                 : typedef struct
     255                 : {
     256                 :     int          iSrcIndex;
     257                 :     OGRFieldType eType;
     258                 :     int          nMaxOccurences;
     259                 :     int          nWidth;
     260                 : } ListFieldDesc;
     261                 : 
     262                 : class OGRSplitListFieldLayer : public OGRLayer
     263                 : {
     264                 :     OGRLayer                    *poSrcLayer;
     265                 :     OGRFeatureDefn              *poFeatureDefn;
     266                 :     ListFieldDesc               *pasListFields;
     267                 :     int                          nListFieldCount;
     268                 :     int                          nMaxSplitListSubFields;
     269                 : 
     270                 :     OGRFeature                  *TranslateFeature(OGRFeature* poSrcFeature);
     271                 : 
     272                 :   public:
     273                 :                                  OGRSplitListFieldLayer(OGRLayer* poSrcLayer,
     274                 :                                                         int nMaxSplitListSubFields);
     275                 :                                 ~OGRSplitListFieldLayer();
     276                 : 
     277                 :     int                          BuildLayerDefn(GDALProgressFunc pfnProgress,
     278                 :                                                 void *pProgressArg);
     279                 : 
     280                 :     virtual OGRFeature          *GetNextFeature();
     281                 :     virtual OGRFeature          *GetFeature(long nFID);
     282                 :     virtual OGRFeatureDefn      *GetLayerDefn();
     283                 : 
     284               2 :     virtual void                 ResetReading() { poSrcLayer->ResetReading(); }
     285               0 :     virtual int                  TestCapability(const char*) { return FALSE; }
     286                 : 
     287               0 :     virtual int                  GetFeatureCount( int bForce = TRUE )
     288                 :     {
     289               0 :         return poSrcLayer->GetFeatureCount(bForce);
     290                 :     }
     291                 : 
     292               2 :     virtual OGRSpatialReference *GetSpatialRef()
     293                 :     {
     294               2 :         return poSrcLayer->GetSpatialRef();
     295                 :     }
     296                 : 
     297               0 :     virtual OGRGeometry         *GetSpatialFilter()
     298                 :     {
     299               0 :         return poSrcLayer->GetSpatialFilter();
     300                 :     }
     301                 : 
     302               2 :     virtual OGRStyleTable       *GetStyleTable()
     303                 :     {
     304               2 :         return poSrcLayer->GetStyleTable();
     305                 :     }
     306                 : 
     307               0 :     virtual void                 SetSpatialFilter( OGRGeometry *poGeom )
     308                 :     {
     309               0 :         poSrcLayer->SetSpatialFilter(poGeom);
     310               0 :     }
     311                 : 
     312               0 :     virtual void                 SetSpatialFilterRect( double dfMinX, double dfMinY,
     313                 :                                                        double dfMaxX, double dfMaxY )
     314                 :     {
     315               0 :         poSrcLayer->SetSpatialFilterRect(dfMinX, dfMinY, dfMaxX, dfMaxY);
     316               0 :     }
     317                 : 
     318               0 :     virtual OGRErr               SetAttributeFilter( const char *pszFilter )
     319                 :     {
     320               0 :         return poSrcLayer->SetAttributeFilter(pszFilter);
     321                 :     }
     322                 : };
     323                 : 
     324                 : /************************************************************************/
     325                 : /*                    OGRSplitListFieldLayer()                          */
     326                 : /************************************************************************/
     327                 : 
     328               2 : OGRSplitListFieldLayer::OGRSplitListFieldLayer(OGRLayer* poSrcLayer,
     329               2 :                                                int nMaxSplitListSubFields)
     330                 : {
     331               2 :     this->poSrcLayer = poSrcLayer;
     332               2 :     if (nMaxSplitListSubFields < 0)
     333               2 :         nMaxSplitListSubFields = INT_MAX;
     334               2 :     this->nMaxSplitListSubFields = nMaxSplitListSubFields;
     335               2 :     poFeatureDefn = NULL;
     336               2 :     pasListFields = NULL;
     337               2 :     nListFieldCount = 0;
     338               2 : }
     339                 : 
     340                 : /************************************************************************/
     341                 : /*                   ~OGRSplitListFieldLayer()                          */
     342                 : /************************************************************************/
     343                 : 
     344               2 : OGRSplitListFieldLayer::~OGRSplitListFieldLayer()
     345                 : {
     346               2 :     if( poFeatureDefn )
     347               2 :         poFeatureDefn->Release();
     348                 : 
     349               2 :     CPLFree(pasListFields);
     350               2 : }
     351                 : 
     352                 : /************************************************************************/
     353                 : /*                       BuildLayerDefn()                               */
     354                 : /************************************************************************/
     355                 : 
     356               2 : int  OGRSplitListFieldLayer::BuildLayerDefn(GDALProgressFunc pfnProgress,
     357                 :                                             void *pProgressArg)
     358                 : {
     359               2 :     CPLAssert(poFeatureDefn == NULL);
     360                 :     
     361               2 :     OGRFeatureDefn* poSrcFieldDefn = poSrcLayer->GetLayerDefn();
     362                 :     
     363               2 :     int nSrcFields = poSrcFieldDefn->GetFieldCount();
     364                 :     pasListFields =
     365               2 :             (ListFieldDesc*)CPLCalloc(sizeof(ListFieldDesc), nSrcFields);
     366               2 :     nListFieldCount = 0;
     367                 :     int i;
     368                 :     
     369                 :     /* Establish the list of fields of list type */
     370              12 :     for(i=0;i<nSrcFields;i++)
     371                 :     {
     372              10 :         OGRFieldType eType = poSrcFieldDefn->GetFieldDefn(i)->GetType();
     373              10 :         if (eType == OFTIntegerList ||
     374                 :             eType == OFTRealList ||
     375                 :             eType == OFTStringList)
     376                 :         {
     377               6 :             pasListFields[nListFieldCount].iSrcIndex = i;
     378               6 :             pasListFields[nListFieldCount].eType = eType;
     379               6 :             if (nMaxSplitListSubFields == 1)
     380               0 :                 pasListFields[nListFieldCount].nMaxOccurences = 1;
     381               6 :             nListFieldCount++;
     382                 :         }
     383                 :     }
     384                 : 
     385               2 :     if (nListFieldCount == 0)
     386               0 :         return FALSE;
     387                 : 
     388                 :     /* No need for full scan if the limit is 1. We just to have to create */
     389                 :     /* one and a single one field */
     390               2 :     if (nMaxSplitListSubFields != 1)
     391                 :     {
     392               2 :         poSrcLayer->ResetReading();
     393                 :         OGRFeature* poSrcFeature;
     394                 : 
     395               2 :         int nFeatureCount = 0;
     396               2 :         if (poSrcLayer->TestCapability(OLCFastFeatureCount))
     397               2 :             nFeatureCount = poSrcLayer->GetFeatureCount();
     398               2 :         int nFeatureIndex = 0;
     399                 : 
     400                 :         /* Scan the whole layer to compute the maximum number of */
     401                 :         /* items for each field of list type */
     402               6 :         while( (poSrcFeature = poSrcLayer->GetNextFeature()) != NULL )
     403                 :         {
     404               8 :             for(i=0;i<nListFieldCount;i++)
     405                 :             {
     406               6 :                 int nCount = 0;
     407                 :                 OGRField* psField =
     408               6 :                         poSrcFeature->GetRawFieldRef(pasListFields[i].iSrcIndex);
     409               6 :                 switch(pasListFields[i].eType)
     410                 :                 {
     411                 :                     case OFTIntegerList:
     412               2 :                         nCount = psField->IntegerList.nCount;
     413               2 :                         break;
     414                 :                     case OFTRealList:
     415               2 :                         nCount = psField->RealList.nCount;
     416               2 :                         break;
     417                 :                     case OFTStringList:
     418                 :                     {
     419               2 :                         nCount = psField->StringList.nCount;
     420               2 :                         char** paList = psField->StringList.paList;
     421                 :                         int j;
     422               6 :                         for(j=0;j<nCount;j++)
     423                 :                         {
     424               4 :                             int nWidth = strlen(paList[j]);
     425               4 :                             if (nWidth > pasListFields[i].nWidth)
     426               2 :                                 pasListFields[i].nWidth = nWidth;
     427                 :                         }
     428               2 :                         break;
     429                 :                     }
     430                 :                     default:
     431               0 :                         CPLAssert(0);
     432                 :                         break;
     433                 :                 }
     434               6 :                 if (nCount > pasListFields[i].nMaxOccurences)
     435                 :                 {
     436               6 :                     if (nCount > nMaxSplitListSubFields)
     437               0 :                         nCount = nMaxSplitListSubFields;
     438               6 :                     pasListFields[i].nMaxOccurences = nCount;
     439                 :                 }
     440                 :             }
     441               2 :             OGRFeature::DestroyFeature(poSrcFeature);
     442                 : 
     443               2 :             nFeatureIndex ++;
     444               2 :             if (pfnProgress != NULL && nFeatureCount != 0)
     445               0 :                 pfnProgress(nFeatureIndex * 1.0 / nFeatureCount, "", pProgressArg);
     446                 :         }
     447                 :     }
     448                 : 
     449                 :     /* Now let's build the target feature definition */
     450                 : 
     451                 :     poFeatureDefn =
     452               2 :             OGRFeatureDefn::CreateFeatureDefn( poSrcFieldDefn->GetName() );
     453               2 :     poFeatureDefn->Reference();
     454               2 :     poFeatureDefn->SetGeomType( poSrcFieldDefn->GetGeomType() );
     455                 : 
     456               2 :     int iListField = 0;
     457              12 :     for(i=0;i<nSrcFields;i++)
     458                 :     {
     459              10 :         OGRFieldType eType = poSrcFieldDefn->GetFieldDefn(i)->GetType();
     460              16 :         if (eType == OFTIntegerList ||
     461                 :             eType == OFTRealList ||
     462                 :             eType == OFTStringList)
     463                 :         {
     464               6 :             int nMaxOccurences = pasListFields[iListField].nMaxOccurences;
     465               6 :             int nWidth = pasListFields[iListField].nWidth;
     466               6 :             iListField ++;
     467                 :             int j;
     468               6 :             if (nMaxOccurences == 1)
     469                 :             {
     470                 :                 OGRFieldDefn oFieldDefn(poSrcFieldDefn->GetFieldDefn(i)->GetNameRef(),
     471                 :                                             (eType == OFTIntegerList) ? OFTInteger :
     472                 :                                             (eType == OFTRealList) ?    OFTReal :
     473               0 :                                                                         OFTString);
     474               0 :                 poFeatureDefn->AddFieldDefn(&oFieldDefn);
     475                 :             }
     476                 :             else
     477                 :             {
     478              18 :                 for(j=0;j<nMaxOccurences;j++)
     479                 :                 {
     480              12 :                     CPLString osFieldName;
     481                 :                     osFieldName.Printf("%s%d",
     482              12 :                         poSrcFieldDefn->GetFieldDefn(i)->GetNameRef(), j+1);
     483                 :                     OGRFieldDefn oFieldDefn(osFieldName.c_str(),
     484                 :                                             (eType == OFTIntegerList) ? OFTInteger :
     485                 :                                             (eType == OFTRealList) ?    OFTReal :
     486              12 :                                                                         OFTString);
     487              12 :                     oFieldDefn.SetWidth(nWidth);
     488              12 :                     poFeatureDefn->AddFieldDefn(&oFieldDefn);
     489                 :                 }
     490                 :             }
     491                 :         }
     492                 :         else
     493                 :         {
     494               4 :             poFeatureDefn->AddFieldDefn(poSrcFieldDefn->GetFieldDefn(i));
     495                 :         }
     496                 :     }
     497                 : 
     498               2 :     return TRUE;
     499                 : }
     500                 : 
     501                 : 
     502                 : /************************************************************************/
     503                 : /*                       TranslateFeature()                             */
     504                 : /************************************************************************/
     505                 : 
     506               4 : OGRFeature *OGRSplitListFieldLayer::TranslateFeature(OGRFeature* poSrcFeature)
     507                 : {
     508               4 :     if (poSrcFeature == NULL)
     509               2 :         return NULL;
     510               2 :     if (poFeatureDefn == NULL)
     511               0 :         return poSrcFeature;
     512                 : 
     513               2 :     OGRFeature* poFeature = OGRFeature::CreateFeature(poFeatureDefn);
     514               2 :     poFeature->SetFID(poSrcFeature->GetFID());
     515               2 :     poFeature->SetGeometryDirectly(poSrcFeature->StealGeometry());
     516               2 :     poFeature->SetStyleString(poFeature->GetStyleString());
     517                 : 
     518               2 :     OGRFeatureDefn* poSrcFieldDefn = poSrcLayer->GetLayerDefn();
     519               2 :     int nSrcFields = poSrcFeature->GetFieldCount();
     520                 :     int iSrcField;
     521               2 :     int iDstField = 0;
     522               2 :     int iListField = 0;
     523                 :     int j;
     524              12 :     for(iSrcField=0;iSrcField<nSrcFields;iSrcField++)
     525                 :     {
     526              10 :         OGRFieldType eType = poSrcFieldDefn->GetFieldDefn(iSrcField)->GetType();
     527              10 :         OGRField* psField = poSrcFeature->GetRawFieldRef(iSrcField);
     528              10 :         switch(eType)
     529                 :         {
     530                 :             case OFTIntegerList:
     531                 :             {
     532               2 :                 int nCount = psField->IntegerList.nCount;
     533               2 :                 if (nCount > nMaxSplitListSubFields)
     534               0 :                     nCount = nMaxSplitListSubFields;
     535               2 :                 int* paList = psField->IntegerList.paList;
     536               6 :                 for(j=0;j<nCount;j++)
     537               4 :                     poFeature->SetField(iDstField + j, paList[j]);
     538               2 :                 iDstField += pasListFields[iListField].nMaxOccurences;
     539               2 :                 iListField++;
     540               2 :                 break;
     541                 :             }
     542                 :             case OFTRealList:
     543                 :             {
     544               2 :                 int nCount = psField->RealList.nCount;
     545               2 :                 if (nCount > nMaxSplitListSubFields)
     546               0 :                     nCount = nMaxSplitListSubFields;
     547               2 :                 double* paList = psField->RealList.paList;
     548               6 :                 for(j=0;j<nCount;j++)
     549               4 :                     poFeature->SetField(iDstField + j, paList[j]);
     550               2 :                 iDstField += pasListFields[iListField].nMaxOccurences;
     551               2 :                 iListField++;
     552               2 :                 break;
     553                 :             }
     554                 :             case OFTStringList:
     555                 :             {
     556               2 :                 int nCount = psField->StringList.nCount;
     557               2 :                 if (nCount > nMaxSplitListSubFields)
     558               0 :                     nCount = nMaxSplitListSubFields;
     559               2 :                 char** paList = psField->StringList.paList;
     560               6 :                 for(j=0;j<nCount;j++)
     561               4 :                     poFeature->SetField(iDstField + j, paList[j]);
     562               2 :                 iDstField += pasListFields[iListField].nMaxOccurences;
     563               2 :                 iListField++;
     564               2 :                 break;
     565                 :             }
     566                 :             default:
     567               4 :                 poFeature->SetField(iDstField, psField);
     568               4 :                 iDstField ++;
     569                 :                 break;
     570                 :         }
     571                 :     }
     572                 : 
     573               2 :     OGRFeature::DestroyFeature(poSrcFeature);
     574                 : 
     575               2 :     return poFeature;
     576                 : }
     577                 : 
     578                 : /************************************************************************/
     579                 : /*                       GetNextFeature()                               */
     580                 : /************************************************************************/
     581                 : 
     582               4 : OGRFeature *OGRSplitListFieldLayer::GetNextFeature()
     583                 : {
     584               4 :     return TranslateFeature(poSrcLayer->GetNextFeature());
     585                 : }
     586                 : 
     587                 : /************************************************************************/
     588                 : /*                           GetFeature()                               */
     589                 : /************************************************************************/
     590                 : 
     591               0 : OGRFeature *OGRSplitListFieldLayer::GetFeature(long nFID)
     592                 : {
     593               0 :     return TranslateFeature(poSrcLayer->GetFeature(nFID));
     594                 : }
     595                 : 
     596                 : /************************************************************************/
     597                 : /*                        GetLayerDefn()                                */
     598                 : /************************************************************************/
     599                 : 
     600               4 : OGRFeatureDefn* OGRSplitListFieldLayer::GetLayerDefn()
     601                 : {
     602               4 :     if (poFeatureDefn == NULL)
     603               0 :         return poSrcLayer->GetLayerDefn();
     604               4 :     return poFeatureDefn;
     605                 : }
     606                 : 
     607                 : /************************************************************************/
     608                 : /*                                main()                                */
     609                 : /************************************************************************/
     610                 : 
     611             144 : int main( int nArgc, char ** papszArgv )
     612                 : 
     613                 : {
     614             144 :     int          bQuiet = FALSE;
     615             144 :     int          bFormatExplicitelySet = FALSE;
     616             144 :     const char  *pszFormat = "ESRI Shapefile";
     617             144 :     const char  *pszDataSource = NULL;
     618             144 :     const char  *pszDestDataSource = NULL;
     619             144 :     char        **papszLayers = NULL;
     620             144 :     char        **papszDSCO = NULL, **papszLCO = NULL;
     621             144 :     int         bTransform = FALSE;
     622             144 :     int         bAppend = FALSE, bUpdate = FALSE, bOverwrite = FALSE;
     623             144 :     const char  *pszOutputSRSDef = NULL;
     624             144 :     const char  *pszSourceSRSDef = NULL;
     625             144 :     OGRSpatialReference *poOutputSRS = NULL;
     626             144 :     int         bNullifyOutputSRS = FALSE;
     627             144 :     OGRSpatialReference *poSourceSRS = NULL;
     628             144 :     char        *pszNewLayerName = NULL;
     629             144 :     const char  *pszWHERE = NULL;
     630             144 :     OGRGeometry *poSpatialFilter = NULL;
     631                 :     const char  *pszSelect;
     632             144 :     char        **papszSelFields = NULL;
     633             144 :     const char  *pszSQLStatement = NULL;
     634             144 :     const char  *pszDialect = NULL;
     635             144 :     int         eGType = -2;
     636             144 :     GeomOperation eGeomOp = NONE;
     637             144 :     double       dfGeomOpParam = 0;
     638             144 :     char        **papszFieldTypesToString = NULL;
     639             144 :     int          bDisplayProgress = FALSE;
     640             144 :     GDALProgressFunc pfnProgress = NULL;
     641             144 :     void        *pProgressArg = NULL;
     642             144 :     int          bWrapDateline = FALSE;
     643             144 :     int          bClipSrc = FALSE;
     644             144 :     OGRGeometry* poClipSrc = NULL;
     645             144 :     const char  *pszClipSrcDS = NULL;
     646             144 :     const char  *pszClipSrcSQL = NULL;
     647             144 :     const char  *pszClipSrcLayer = NULL;
     648             144 :     const char  *pszClipSrcWhere = NULL;
     649             144 :     OGRGeometry *poClipDst = NULL;
     650             144 :     const char  *pszClipDstDS = NULL;
     651             144 :     const char  *pszClipDstSQL = NULL;
     652             144 :     const char  *pszClipDstLayer = NULL;
     653             144 :     const char  *pszClipDstWhere = NULL;
     654             144 :     int          bSplitListFields = FALSE;
     655             144 :     int          nMaxSplitListSubFields = -1;
     656             144 :     int          bExplodeCollections = FALSE;
     657             144 :     const char  *pszZField = NULL;
     658                 : 
     659                 :     /* Check strict compilation and runtime library version as we use C++ API */
     660             144 :     if (! GDAL_CHECK_VERSION(papszArgv[0]))
     661               0 :         exit(1);
     662                 : /* -------------------------------------------------------------------- */
     663                 : /*      Register format(s).                                             */
     664                 : /* -------------------------------------------------------------------- */
     665             144 :     OGRRegisterAll();
     666                 : 
     667                 : /* -------------------------------------------------------------------- */
     668                 : /*      Processing command line arguments.                              */
     669                 : /* -------------------------------------------------------------------- */
     670             144 :     nArgc = OGRGeneralCmdLineProcessor( nArgc, &papszArgv, 0 );
     671                 :     
     672             144 :     if( nArgc < 1 )
     673               0 :         exit( -nArgc );
     674                 : 
     675             662 :     for( int iArg = 1; iArg < nArgc; iArg++ )
     676                 :     {
     677             520 :         if( EQUAL(papszArgv[iArg], "--utility_version") )
     678                 :         {
     679                 :             printf("%s was compiled against GDAL %s and is running against GDAL %s\n",
     680               2 :                    papszArgv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME"));
     681               2 :             return 0;
     682                 :         }
     683             518 :         else if ( EQUAL(papszArgv[iArg], "--long-usage") )
     684                 :         {
     685               0 :             Usage(FALSE);
     686                 :         }
     687                 : 
     688             518 :         else if( EQUAL(papszArgv[iArg],"-q") || EQUAL(papszArgv[iArg],"-quiet") )
     689                 :         {
     690               0 :             bQuiet = TRUE;
     691                 :         }
     692             568 :         else if( EQUAL(papszArgv[iArg],"-f") && iArg < nArgc-1 )
     693                 :         {
     694              50 :             bFormatExplicitelySet = TRUE;
     695              50 :             pszFormat = papszArgv[++iArg];
     696                 :         }
     697             474 :         else if( EQUAL(papszArgv[iArg],"-dsco") && iArg < nArgc-1 )
     698                 :         {
     699               6 :             papszDSCO = CSLAddString(papszDSCO, papszArgv[++iArg] );
     700                 :         }
     701             464 :         else if( EQUAL(papszArgv[iArg],"-lco") && iArg < nArgc-1 )
     702                 :         {
     703               2 :             papszLCO = CSLAddString(papszLCO, papszArgv[++iArg] );
     704                 :         }
     705             460 :         else if( EQUAL(papszArgv[iArg],"-preserve_fid") )
     706                 :         {
     707               0 :             bPreserveFID = TRUE;
     708                 :         }
     709             460 :         else if( EQUALN(papszArgv[iArg],"-skip",5) )
     710                 :         {
     711               0 :             bSkipFailures = TRUE;
     712               0 :             nGroupTransactions = 1; /* #2409 */
     713                 :         }
     714             460 :         else if( EQUAL(papszArgv[iArg],"-append") )
     715                 :         {
     716              12 :             bAppend = TRUE;
     717              12 :             bUpdate = TRUE;
     718                 :         }
     719             448 :         else if( EQUAL(papszArgv[iArg],"-overwrite") )
     720                 :         {
     721              22 :             bOverwrite = TRUE;
     722              22 :             bUpdate = TRUE;
     723                 :         }
     724             426 :         else if( EQUAL(papszArgv[iArg],"-update") )
     725                 :         {
     726               8 :             bUpdate = TRUE;
     727                 :         }
     728             420 :         else if( EQUAL(papszArgv[iArg],"-fid") && papszArgv[iArg+1] != NULL )
     729                 :         {
     730               2 :             nFIDToFetch = atoi(papszArgv[++iArg]);
     731                 :         }
     732             428 :         else if( EQUAL(papszArgv[iArg],"-sql") && papszArgv[iArg+1] != NULL )
     733                 :         {
     734              12 :             pszSQLStatement = papszArgv[++iArg];
     735                 :         }
     736             404 :         else if( EQUAL(papszArgv[iArg],"-dialect") && papszArgv[iArg+1] != NULL )
     737                 :         {
     738               0 :             pszDialect = papszArgv[++iArg];
     739                 :         }
     740             430 :         else if( EQUAL(papszArgv[iArg],"-nln") && iArg < nArgc-1 )
     741                 :         {
     742              26 :             pszNewLayerName = CPLStrdup(papszArgv[++iArg]);
     743                 :         }
     744             392 :         else if( EQUAL(papszArgv[iArg],"-nlt") && iArg < nArgc-1 )
     745                 :         {
     746              14 :             int bIs3D = FALSE;
     747              14 :             CPLString osGeomName = papszArgv[iArg+1];
     748              42 :             if (strlen(papszArgv[iArg+1]) > 3 &&
     749              28 :                 EQUALN(papszArgv[iArg+1] + strlen(papszArgv[iArg+1]) - 3, "25D", 3))
     750                 :             {
     751               2 :                 bIs3D = TRUE;
     752               2 :                 osGeomName.resize(osGeomName.size() - 3);
     753                 :             }
     754              14 :             if( EQUAL(osGeomName,"NONE") )
     755               0 :                 eGType = wkbNone;
     756              14 :             else if( EQUAL(osGeomName,"GEOMETRY") )
     757               0 :                 eGType = wkbUnknown;
     758                 :             else
     759                 :             {
     760              14 :                 eGType = OGRFromOGCGeomType(osGeomName);
     761              14 :                 if (eGType == wkbUnknown)
     762                 :                 {
     763                 :                     fprintf( stderr, "-nlt %s: type not recognised.\n",
     764               0 :                             papszArgv[iArg+1] );
     765               0 :                     exit( 1 );
     766                 :                 }
     767                 :             }
     768              14 :             if (eGType != wkbNone && bIs3D)
     769               2 :                 eGType |= wkb25DBit;
     770                 : 
     771              14 :             iArg++;
     772                 :         }
     773             730 :         else if( (EQUAL(papszArgv[iArg],"-tg") ||
     774             364 :                   EQUAL(papszArgv[iArg],"-gt")) && iArg < nArgc-1 )
     775                 :         {
     776               2 :             nGroupTransactions = atoi(papszArgv[++iArg]);
     777                 :         }
     778             362 :         else if( EQUAL(papszArgv[iArg],"-s_srs") && iArg < nArgc-1 )
     779                 :         {
     780               0 :             pszSourceSRSDef = papszArgv[++iArg];
     781                 :         }
     782             366 :         else if( EQUAL(papszArgv[iArg],"-a_srs") && iArg < nArgc-1 )
     783                 :         {
     784               4 :             pszOutputSRSDef = papszArgv[++iArg];
     785               4 :             if (EQUAL(pszOutputSRSDef, "NULL") ||
     786                 :                 EQUAL(pszOutputSRSDef, "NONE"))
     787                 :             {
     788               2 :                 pszOutputSRSDef = NULL;
     789               2 :                 bNullifyOutputSRS = TRUE;
     790                 :             }
     791                 :         }
     792             362 :         else if( EQUAL(papszArgv[iArg],"-t_srs") && iArg < nArgc-1 )
     793                 :         {
     794               4 :             pszOutputSRSDef = papszArgv[++iArg];
     795               4 :             bTransform = TRUE;
     796                 :         }
     797             374 :         else if( EQUAL(papszArgv[iArg],"-spat") 
     798               4 :                  && papszArgv[iArg+1] != NULL 
     799               4 :                  && papszArgv[iArg+2] != NULL 
     800               4 :                  && papszArgv[iArg+3] != NULL 
     801               4 :                  && papszArgv[iArg+4] != NULL )
     802                 :         {
     803               4 :             OGRLinearRing  oRing;
     804                 : 
     805               4 :             oRing.addPoint( atof(papszArgv[iArg+1]), atof(papszArgv[iArg+2]) );
     806               4 :             oRing.addPoint( atof(papszArgv[iArg+1]), atof(papszArgv[iArg+4]) );
     807               4 :             oRing.addPoint( atof(papszArgv[iArg+3]), atof(papszArgv[iArg+4]) );
     808               4 :             oRing.addPoint( atof(papszArgv[iArg+3]), atof(papszArgv[iArg+2]) );
     809               4 :             oRing.addPoint( atof(papszArgv[iArg+1]), atof(papszArgv[iArg+2]) );
     810                 : 
     811               4 :             poSpatialFilter = OGRGeometryFactory::createGeometry(wkbPolygon);
     812               4 :             ((OGRPolygon *) poSpatialFilter)->addRing( &oRing );
     813               4 :             iArg += 4;
     814                 :         }
     815             356 :         else if( EQUAL(papszArgv[iArg],"-where") && papszArgv[iArg+1] != NULL )
     816                 :         {
     817               6 :             pszWHERE = papszArgv[++iArg];
     818                 :         }
     819             358 :         else if( EQUAL(papszArgv[iArg],"-select") && papszArgv[iArg+1] != NULL)
     820                 :         {
     821              14 :             pszSelect = papszArgv[++iArg];
     822                 :             papszSelFields = CSLTokenizeStringComplex(pszSelect, " ,", 
     823              14 :                                                       FALSE, FALSE );
     824                 :         }
     825             332 :         else if( EQUAL(papszArgv[iArg],"-segmentize") && iArg < nArgc-1 )
     826                 :         {
     827               2 :             eGeomOp = SEGMENTIZE;
     828               2 :             dfGeomOpParam = atof(papszArgv[++iArg]);
     829                 :         }
     830             328 :         else if( EQUAL(papszArgv[iArg],"-simplify") && iArg < nArgc-1 )
     831                 :         {
     832               0 :             eGeomOp = SIMPLIFY_PRESERVE_TOPOLOGY;
     833               0 :             dfGeomOpParam = atof(papszArgv[++iArg]);
     834                 :         }
     835             328 :         else if( EQUAL(papszArgv[iArg],"-fieldTypeToString") && iArg < nArgc-1 )
     836                 :         {
     837                 :             papszFieldTypesToString =
     838               0 :                     CSLTokenizeStringComplex(papszArgv[++iArg], " ,", 
     839               0 :                                              FALSE, FALSE );
     840               0 :             char** iter = papszFieldTypesToString;
     841               0 :             while(*iter)
     842                 :             {
     843               0 :                 if (EQUAL(*iter, "Integer") ||
     844                 :                     EQUAL(*iter, "Real") ||
     845                 :                     EQUAL(*iter, "String") ||
     846                 :                     EQUAL(*iter, "Date") ||
     847                 :                     EQUAL(*iter, "Time") ||
     848                 :                     EQUAL(*iter, "DateTime") ||
     849                 :                     EQUAL(*iter, "Binary") ||
     850                 :                     EQUAL(*iter, "IntegerList") ||
     851                 :                     EQUAL(*iter, "RealList") ||
     852                 :                     EQUAL(*iter, "StringList"))
     853                 :                 {
     854                 :                     /* Do nothing */
     855                 :                 }
     856               0 :                 else if (EQUAL(*iter, "All"))
     857                 :                 {
     858               0 :                     CSLDestroy(papszFieldTypesToString);
     859               0 :                     papszFieldTypesToString = NULL;
     860               0 :                     papszFieldTypesToString = CSLAddString(papszFieldTypesToString, "All");
     861               0 :                     break;
     862                 :                 }
     863                 :                 else
     864                 :                 {
     865                 :                     fprintf(stderr, "Unhandled type for fieldtypeasstring option : %s\n",
     866               0 :                             *iter);
     867               0 :                     Usage();
     868                 :                 }
     869               0 :                 iter ++;
     870                 :             }
     871                 :         }
     872             328 :         else if( EQUAL(papszArgv[iArg],"-progress") )
     873                 :         {
     874               2 :             bDisplayProgress = TRUE;
     875                 :         }
     876             326 :         else if( EQUAL(papszArgv[iArg],"-wrapdateline") )
     877                 :         {
     878               8 :             bWrapDateline = TRUE;
     879                 :         }
     880             324 :         else if( EQUAL(papszArgv[iArg],"-clipsrc") && iArg < nArgc-1 )
     881                 :         {
     882                 :             VSIStatBufL  sStat;
     883               6 :             bClipSrc = TRUE;
     884               6 :             if ( IsNumber(papszArgv[iArg+1])
     885               0 :                  && papszArgv[iArg+2] != NULL 
     886               0 :                  && papszArgv[iArg+3] != NULL 
     887               0 :                  && papszArgv[iArg+4] != NULL)
     888                 :             {
     889               0 :                 OGRLinearRing  oRing;
     890                 : 
     891               0 :                 oRing.addPoint( atof(papszArgv[iArg+1]), atof(papszArgv[iArg+2]) );
     892               0 :                 oRing.addPoint( atof(papszArgv[iArg+1]), atof(papszArgv[iArg+4]) );
     893               0 :                 oRing.addPoint( atof(papszArgv[iArg+3]), atof(papszArgv[iArg+4]) );
     894               0 :                 oRing.addPoint( atof(papszArgv[iArg+3]), atof(papszArgv[iArg+2]) );
     895               0 :                 oRing.addPoint( atof(papszArgv[iArg+1]), atof(papszArgv[iArg+2]) );
     896                 : 
     897               0 :                 poClipSrc = OGRGeometryFactory::createGeometry(wkbPolygon);
     898               0 :                 ((OGRPolygon *) poClipSrc)->addRing( &oRing );
     899               0 :                 iArg += 4;
     900                 :             }
     901              12 :             else if ((EQUALN(papszArgv[iArg+1], "POLYGON", 7) ||
     902               4 :                       EQUALN(papszArgv[iArg+1], "MULTIPOLYGON", 12)) &&
     903               2 :                       VSIStatL(papszArgv[iArg+1], &sStat) != 0)
     904                 :             {
     905               2 :                 char* pszTmp = (char*) papszArgv[iArg+1];
     906               2 :                 OGRGeometryFactory::createFromWkt(&pszTmp, NULL, &poClipSrc);
     907               2 :                 if (poClipSrc == NULL)
     908                 :                 {
     909               0 :                     fprintf( stderr, "FAILURE: Invalid geometry. Must be a valid POLYGON or MULTIPOLYGON WKT\n\n");
     910               0 :                     Usage();
     911                 :                 }
     912               2 :                 iArg ++;
     913                 :             }
     914               4 :             else if (EQUAL(papszArgv[iArg+1], "spat_extent") )
     915                 :             {
     916               2 :                 iArg ++;
     917                 :             }
     918                 :             else
     919                 :             {
     920               2 :                 pszClipSrcDS = papszArgv[iArg+1];
     921               2 :                 iArg ++;
     922                 :             }
     923                 :         }
     924             312 :         else if( EQUAL(papszArgv[iArg],"-clipsrcsql") && iArg < nArgc-1 )
     925                 :         {
     926               0 :             pszClipSrcSQL = papszArgv[iArg+1];
     927               0 :             iArg ++;
     928                 :         }
     929             312 :         else if( EQUAL(papszArgv[iArg],"-clipsrclayer") && iArg < nArgc-1 )
     930                 :         {
     931               0 :             pszClipSrcLayer = papszArgv[iArg+1];
     932               0 :             iArg ++;
     933                 :         }
     934             314 :         else if( EQUAL(papszArgv[iArg],"-clipsrcwhere") && iArg < nArgc-1 )
     935                 :         {
     936               2 :             pszClipSrcWhere = papszArgv[iArg+1];
     937               2 :             iArg ++;
     938                 :         }
     939             314 :         else if( EQUAL(papszArgv[iArg],"-clipdst") && iArg < nArgc-1 )
     940                 :         {
     941                 :             VSIStatBufL  sStat;
     942               4 :             if ( IsNumber(papszArgv[iArg+1])
     943               0 :                  && papszArgv[iArg+2] != NULL 
     944               0 :                  && papszArgv[iArg+3] != NULL 
     945               0 :                  && papszArgv[iArg+4] != NULL)
     946                 :             {
     947               0 :                 OGRLinearRing  oRing;
     948                 : 
     949               0 :                 oRing.addPoint( atof(papszArgv[iArg+1]), atof(papszArgv[iArg+2]) );
     950               0 :                 oRing.addPoint( atof(papszArgv[iArg+1]), atof(papszArgv[iArg+4]) );
     951               0 :                 oRing.addPoint( atof(papszArgv[iArg+3]), atof(papszArgv[iArg+4]) );
     952               0 :                 oRing.addPoint( atof(papszArgv[iArg+3]), atof(papszArgv[iArg+2]) );
     953               0 :                 oRing.addPoint( atof(papszArgv[iArg+1]), atof(papszArgv[iArg+2]) );
     954                 : 
     955               0 :                 poClipDst = OGRGeometryFactory::createGeometry(wkbPolygon);
     956               0 :                 ((OGRPolygon *) poClipDst)->addRing( &oRing );
     957               0 :                 iArg += 4;
     958                 :             }
     959               8 :             else if ((EQUALN(papszArgv[iArg+1], "POLYGON", 7) ||
     960               2 :                       EQUALN(papszArgv[iArg+1], "MULTIPOLYGON", 12)) &&
     961               2 :                       VSIStatL(papszArgv[iArg+1], &sStat) != 0)
     962                 :             {
     963               2 :                 char* pszTmp = (char*) papszArgv[iArg+1];
     964               2 :                 OGRGeometryFactory::createFromWkt(&pszTmp, NULL, &poClipDst);
     965               2 :                 if (poClipDst == NULL)
     966                 :                 {
     967               0 :                     fprintf( stderr, "FAILURE: Invalid geometry. Must be a valid POLYGON or MULTIPOLYGON WKT\n\n");
     968               0 :                     Usage();
     969                 :                 }
     970               2 :                 iArg ++;
     971                 :             }
     972                 :             else
     973                 :             {
     974               2 :                 pszClipDstDS = papszArgv[iArg+1];
     975               2 :                 iArg ++;
     976                 :             }
     977                 :         }
     978             308 :         else if( EQUAL(papszArgv[iArg],"-clipdstsql") && iArg < nArgc-1 )
     979                 :         {
     980               2 :             pszClipDstSQL = papszArgv[iArg+1];
     981               2 :             iArg ++;
     982                 :         }
     983             304 :         else if( EQUAL(papszArgv[iArg],"-clipdstlayer") && iArg < nArgc-1 )
     984                 :         {
     985               0 :             pszClipDstLayer = papszArgv[iArg+1];
     986               0 :             iArg ++;
     987                 :         }
     988             304 :         else if( EQUAL(papszArgv[iArg],"-clipdstwhere") && iArg < nArgc-1 )
     989                 :         {
     990               0 :             pszClipDstWhere = papszArgv[iArg+1];
     991               0 :             iArg ++;
     992                 :         }
     993             304 :         else if( EQUAL(papszArgv[iArg],"-splitlistfields") )
     994                 :         {
     995               2 :             bSplitListFields = TRUE;
     996                 :         }
     997             302 :         else if ( EQUAL(papszArgv[iArg],"-maxsubfields") && iArg < nArgc-1 )
     998                 :         {
     999               0 :             if (IsNumber(papszArgv[iArg+1]))
    1000                 :             {
    1001               0 :                 int nTemp = atoi(papszArgv[iArg+1]);
    1002               0 :                 if (nTemp > 0)
    1003                 :                 {
    1004               0 :                     nMaxSplitListSubFields = nTemp;
    1005               0 :                     iArg ++;
    1006                 :                 }
    1007                 :             }
    1008                 :         }
    1009             302 :         else if( EQUAL(papszArgv[iArg],"-explodecollections") )
    1010                 :         {
    1011               2 :             bExplodeCollections = TRUE;
    1012                 :         }
    1013             306 :         else if( EQUAL(papszArgv[iArg],"-zfield") && iArg < nArgc-1 )
    1014                 :         {
    1015               6 :             pszZField = papszArgv[iArg+1];
    1016               6 :             iArg ++;
    1017                 :         }
    1018             294 :         else if( papszArgv[iArg][0] == '-' )
    1019                 :         {
    1020               0 :             Usage();
    1021                 :         }
    1022             294 :         else if( pszDestDataSource == NULL )
    1023             142 :             pszDestDataSource = papszArgv[iArg];
    1024             152 :         else if( pszDataSource == NULL )
    1025             142 :             pszDataSource = papszArgv[iArg];
    1026                 :         else
    1027              10 :             papszLayers = CSLAddString( papszLayers, papszArgv[iArg] );
    1028                 :     }
    1029                 : 
    1030             142 :     if( pszDataSource == NULL )
    1031               0 :         Usage();
    1032                 : 
    1033             142 :     if( bPreserveFID && bExplodeCollections )
    1034                 :     {
    1035               0 :         fprintf( stderr, "FAILURE: cannot use -preserve_fid and -explodecollections at the same time\n\n" );
    1036               0 :         Usage();
    1037                 :     }
    1038                 : 
    1039             144 :     if( bClipSrc && pszClipSrcDS != NULL)
    1040                 :     {
    1041               2 :         poClipSrc = LoadGeometry(pszClipSrcDS, pszClipSrcSQL, pszClipSrcLayer, pszClipSrcWhere);
    1042               2 :         if (poClipSrc == NULL)
    1043                 :         {
    1044               0 :             fprintf( stderr, "FAILURE: cannot load source clip geometry\n\n" );
    1045               0 :             Usage();
    1046                 :         }
    1047                 :     }
    1048             140 :     else if( bClipSrc && poClipSrc == NULL )
    1049                 :     {
    1050               2 :         if (poSpatialFilter)
    1051               2 :             poClipSrc = poSpatialFilter->clone();
    1052               2 :         if (poClipSrc == NULL)
    1053                 :         {
    1054                 :             fprintf( stderr, "FAILURE: -clipsrc must be used with -spat option or a\n"
    1055               0 :                              "bounding box, WKT string or datasource must be specified\n\n");
    1056               0 :             Usage();
    1057                 :         }
    1058                 :     }
    1059                 :     
    1060             142 :     if( pszClipDstDS != NULL)
    1061                 :     {
    1062               2 :         poClipDst = LoadGeometry(pszClipDstDS, pszClipDstSQL, pszClipDstLayer, pszClipDstWhere);
    1063               2 :         if (poClipDst == NULL)
    1064                 :         {
    1065               0 :             fprintf( stderr, "FAILURE: cannot load dest clip geometry\n\n" );
    1066               0 :             Usage();
    1067                 :         }
    1068                 :     }
    1069                 : 
    1070                 : /* -------------------------------------------------------------------- */
    1071                 : /*      Open data source.                                               */
    1072                 : /* -------------------------------------------------------------------- */
    1073                 :     OGRDataSource       *poDS;
    1074             142 :     OGRDataSource       *poODS = NULL;
    1075             142 :     OGRSFDriver         *poDriver = NULL;
    1076             142 :     int                  bCloseODS = TRUE;
    1077                 : 
    1078                 :     /* Avoid opening twice the same datasource if it is both the input and output */
    1079                 :     /* Known to cause problems with at least FGdb and SQlite drivers. See #4270 */
    1080             148 :     if (bUpdate && strcmp(pszDestDataSource, pszDataSource) == 0)
    1081                 :     {
    1082               6 :         poODS = poDS = OGRSFDriverRegistrar::Open( pszDataSource, TRUE, &poDriver );
    1083                 :         /* Restrict to those 2 drivers. For example it is known to break with */
    1084                 :         /* the PG driver due to the way it manages transactions... */
    1085              12 :         if (poDS && !(EQUAL(poDriver->GetName(), "FileGDB") ||
    1086               6 :                       EQUAL(poDriver->GetName(), "SQLite")))
    1087                 :         {
    1088               4 :             poDS = OGRSFDriverRegistrar::Open( pszDataSource, FALSE );
    1089                 :         }
    1090                 :         else
    1091               2 :             bCloseODS = FALSE;
    1092               6 :         if (poDS)
    1093                 :         {
    1094               6 :             if (bOverwrite || bAppend)
    1095                 :             {
    1096                 :                 /* Various tests to avoid overwriting the source layer(s) */
    1097                 :                 /* or to avoid appending a layer to itself */
    1098               2 :                 int bError = FALSE;
    1099               2 :                 if (pszNewLayerName == NULL)
    1100               0 :                     bError = TRUE;
    1101               2 :                 else if (CSLCount(papszLayers) == 1)
    1102               2 :                     bError = strcmp(pszNewLayerName, papszLayers[0]) == 0;
    1103               0 :                 else if (pszSQLStatement == NULL)
    1104               0 :                     bError = TRUE;
    1105               2 :                 if (bError)
    1106                 :                 {
    1107                 :                     fprintf( stderr,
    1108                 :                              "ERROR: -nln name must be specified combined with "
    1109                 :                              "a single source layer name,\nor a -sql statement, and "
    1110               0 :                              "name must be different from an existing layer.\n");
    1111               0 :                     exit(1);
    1112                 :                 }
    1113                 :             }
    1114                 :         }
    1115                 :     }
    1116                 :     else
    1117             136 :         poDS = OGRSFDriverRegistrar::Open( pszDataSource, FALSE );
    1118                 : 
    1119                 : /* -------------------------------------------------------------------- */
    1120                 : /*      Report failure                                                  */
    1121                 : /* -------------------------------------------------------------------- */
    1122             142 :     if( poDS == NULL )
    1123                 :     {
    1124               0 :         OGRSFDriverRegistrar    *poR = OGRSFDriverRegistrar::GetRegistrar();
    1125                 :         
    1126                 :         fprintf( stderr, "FAILURE:\n"
    1127                 :                 "Unable to open datasource `%s' with the following drivers.\n",
    1128               0 :                 pszDataSource );
    1129                 : 
    1130               0 :         for( int iDriver = 0; iDriver < poR->GetDriverCount(); iDriver++ )
    1131                 :         {
    1132               0 :             fprintf( stderr, "  -> %s\n", poR->GetDriver(iDriver)->GetName() );
    1133                 :         }
    1134                 : 
    1135               0 :         exit( 1 );
    1136                 :     }
    1137                 : 
    1138                 : /* -------------------------------------------------------------------- */
    1139                 : /*      Try opening the output datasource as an existing, writable      */
    1140                 : /* -------------------------------------------------------------------- */
    1141                 : 
    1142             142 :     if( bUpdate && poODS == NULL )
    1143                 :     {
    1144              32 :         poODS = OGRSFDriverRegistrar::Open( pszDestDataSource, TRUE, &poDriver );
    1145                 : 
    1146              32 :         if( poODS == NULL )
    1147                 :         {
    1148               2 :             if (bOverwrite || bAppend)
    1149                 :             {
    1150               2 :                 poODS = OGRSFDriverRegistrar::Open( pszDestDataSource, FALSE, &poDriver );
    1151               2 :                 if (poODS == NULL)
    1152                 :                 {
    1153                 :                     /* ok the datasource doesn't exist at all */
    1154               2 :                     bUpdate = FALSE;
    1155                 :                 }
    1156                 :                 else
    1157                 :                 {
    1158               0 :                     OGRDataSource::DestroyDataSource(poODS);
    1159               0 :                     poODS = NULL;
    1160                 :                 }
    1161                 :             }
    1162                 : 
    1163               2 :             if (bUpdate)
    1164                 :             {
    1165                 :                 fprintf( stderr, "FAILURE:\n"
    1166                 :                         "Unable to open existing output datasource `%s'.\n",
    1167               0 :                         pszDestDataSource );
    1168               0 :                 exit( 1 );
    1169                 :             }
    1170                 :         }
    1171              30 :         else if( CSLCount(papszDSCO) > 0 )
    1172                 :         {
    1173                 :             fprintf( stderr, "WARNING: Datasource creation options ignored since an existing datasource\n"
    1174               0 :                     "         being updated.\n" );
    1175                 :         }
    1176                 :     }
    1177                 : 
    1178                 : /* -------------------------------------------------------------------- */
    1179                 : /*      Find the output driver.                                         */
    1180                 : /* -------------------------------------------------------------------- */
    1181             142 :     if( !bUpdate )
    1182                 :     {
    1183             106 :         if (!bQuiet && !bFormatExplicitelySet)
    1184              72 :             CheckDestDataSourceNameConsistency(pszDestDataSource, pszFormat);
    1185                 : 
    1186             106 :         OGRSFDriverRegistrar *poR = OGRSFDriverRegistrar::GetRegistrar();
    1187                 :         int                  iDriver;
    1188                 : 
    1189             106 :         poDriver = poR->GetDriverByName(pszFormat);
    1190             106 :         if( poDriver == NULL )
    1191                 :         {
    1192               0 :             fprintf( stderr, "Unable to find driver `%s'.\n", pszFormat );
    1193               0 :             fprintf( stderr,  "The following drivers are available:\n" );
    1194                 :         
    1195               0 :             for( iDriver = 0; iDriver < poR->GetDriverCount(); iDriver++ )
    1196                 :             {
    1197               0 :                 fprintf( stderr,  "  -> `%s'\n", poR->GetDriver(iDriver)->GetName() );
    1198                 :             }
    1199               0 :             exit( 1 );
    1200                 :         }
    1201                 : 
    1202             106 :         if( !poDriver->TestCapability( ODrCCreateDataSource ) )
    1203                 :         {
    1204                 :             fprintf( stderr,  "%s driver does not support data source creation.\n",
    1205               0 :                     pszFormat );
    1206               0 :             exit( 1 );
    1207                 :         }
    1208                 : 
    1209                 : /* -------------------------------------------------------------------- */
    1210                 : /*      Special case to improve user experience when translating        */
    1211                 : /*      a datasource with multiple layers into a shapefile. If the      */
    1212                 : /*      user gives a target datasource with .shp and it does not exist, */
    1213                 : /*      the shapefile driver will try to create a file, but this is not */
    1214                 : /*      appropriate because here we have several layers, so create      */
    1215                 : /*      a directory instead.                                            */
    1216                 : /* -------------------------------------------------------------------- */
    1217                 :         VSIStatBufL  sStat;
    1218             170 :         if (EQUAL(poDriver->GetName(), "ESRI Shapefile") &&
    1219                 :             pszSQLStatement == NULL &&
    1220                 :             (CSLCount(papszLayers) > 1 ||
    1221              64 :              (CSLCount(papszLayers) == 0 && poDS->GetLayerCount() > 1)) &&
    1222                 :             pszNewLayerName == NULL &&
    1223                 :             EQUAL(CPLGetExtension(pszDestDataSource), "SHP") &&
    1224                 :             VSIStatL(pszDestDataSource, &sStat) != 0)
    1225                 :         {
    1226               2 :             if (VSIMkdir(pszDestDataSource, 0755) != 0)
    1227                 :             {
    1228                 :                 CPLError( CE_Failure, CPLE_AppDefined,
    1229                 :                       "Failed to create directory %s\n"
    1230                 :                       "for shapefile datastore.\n",
    1231               0 :                       pszDestDataSource );
    1232               0 :                 exit(1);
    1233                 :             }
    1234                 :         }
    1235                 : 
    1236                 : /* -------------------------------------------------------------------- */
    1237                 : /*      Create the output data source.                                  */
    1238                 : /* -------------------------------------------------------------------- */
    1239             106 :         poODS = poDriver->CreateDataSource( pszDestDataSource, papszDSCO );
    1240             106 :         if( poODS == NULL )
    1241                 :         {
    1242                 :             fprintf( stderr,  "%s driver failed to create %s\n", 
    1243               0 :                     pszFormat, pszDestDataSource );
    1244               0 :             exit( 1 );
    1245                 :         }
    1246                 :     }
    1247                 : 
    1248                 : /* -------------------------------------------------------------------- */
    1249                 : /*      Parse the output SRS definition if possible.                    */
    1250                 : /* -------------------------------------------------------------------- */
    1251             142 :     if( pszOutputSRSDef != NULL )
    1252                 :     {
    1253               6 :         poOutputSRS = (OGRSpatialReference*)OSRNewSpatialReference(NULL);
    1254               6 :         if( poOutputSRS->SetFromUserInput( pszOutputSRSDef ) != OGRERR_NONE )
    1255                 :         {
    1256                 :             fprintf( stderr,  "Failed to process SRS definition: %s\n", 
    1257               0 :                     pszOutputSRSDef );
    1258               0 :             exit( 1 );
    1259                 :         }
    1260                 :     }
    1261                 : 
    1262                 : /* -------------------------------------------------------------------- */
    1263                 : /*      Parse the source SRS definition if possible.                    */
    1264                 : /* -------------------------------------------------------------------- */
    1265             142 :     if( pszSourceSRSDef != NULL )
    1266                 :     {
    1267               0 :         poSourceSRS = (OGRSpatialReference*)OSRNewSpatialReference(NULL);
    1268               0 :         if( poSourceSRS->SetFromUserInput( pszSourceSRSDef ) != OGRERR_NONE )
    1269                 :         {
    1270                 :             fprintf( stderr,  "Failed to process SRS definition: %s\n", 
    1271               0 :                     pszSourceSRSDef );
    1272               0 :             exit( 1 );
    1273                 :         }
    1274                 :     }
    1275                 : 
    1276                 : /* -------------------------------------------------------------------- */
    1277                 : /*      Special case for -sql clause.  No source layers required.       */
    1278                 : /* -------------------------------------------------------------------- */
    1279             142 :     if( pszSQLStatement != NULL )
    1280                 :     {
    1281                 :         OGRLayer *poResultSet;
    1282                 : 
    1283              12 :         if( pszWHERE != NULL )
    1284               0 :             fprintf( stderr,  "-where clause ignored in combination with -sql.\n" );
    1285              12 :         if( CSLCount(papszLayers) > 0 )
    1286               0 :             fprintf( stderr,  "layer names ignored in combination with -sql.\n" );
    1287                 :         
    1288                 :         poResultSet = poDS->ExecuteSQL( pszSQLStatement, poSpatialFilter, 
    1289              12 :                                         pszDialect );
    1290                 : 
    1291              12 :         if( poResultSet != NULL )
    1292                 :         {
    1293              12 :             long nCountLayerFeatures = 0;
    1294              12 :             if (bDisplayProgress)
    1295                 :             {
    1296               0 :                 if (!poResultSet->TestCapability(OLCFastFeatureCount))
    1297                 :                 {
    1298               0 :                     fprintf( stderr, "Progress turned off as fast feature count is not available.\n");
    1299               0 :                     bDisplayProgress = FALSE;
    1300                 :                 }
    1301                 :                 else
    1302                 :                 {
    1303               0 :                     nCountLayerFeatures = poResultSet->GetFeatureCount();
    1304               0 :                     pfnProgress = GDALTermProgress;
    1305                 :                 }
    1306                 :             }
    1307                 : 
    1308              12 :             OGRLayer* poPassedLayer = poResultSet;
    1309              12 :             if (bSplitListFields)
    1310                 :             {
    1311               0 :                 poPassedLayer = new OGRSplitListFieldLayer(poPassedLayer, nMaxSplitListSubFields);
    1312               0 :                 int nRet = ((OGRSplitListFieldLayer*)poPassedLayer)->BuildLayerDefn(NULL, NULL);
    1313               0 :                 if (!nRet)
    1314                 :                 {
    1315               0 :                     delete poPassedLayer;
    1316               0 :                     poPassedLayer = poResultSet;
    1317                 :                 }
    1318                 :             }
    1319                 : 
    1320                 : /* -------------------------------------------------------------------- */
    1321                 : /*      Special case to improve user experience when translating into   */
    1322                 : /*      single file shapefile and source has only one layer, and that   */
    1323                 : /*      the layer name isn't specified                                  */
    1324                 : /* -------------------------------------------------------------------- */
    1325                 :             VSIStatBufL  sStat;
    1326              12 :             if (EQUAL(poDriver->GetName(), "ESRI Shapefile") &&
    1327                 :                 pszNewLayerName == NULL &&
    1328                 :                 VSIStatL(pszDestDataSource, &sStat) == 0 && VSI_ISREG(sStat.st_mode))
    1329                 :             {
    1330               0 :                 pszNewLayerName = CPLStrdup(CPLGetBasename(pszDestDataSource));
    1331                 :             }
    1332                 : 
    1333              12 :             if( !TranslateLayer( poDS, poPassedLayer, poODS, papszLCO, 
    1334                 :                                  pszNewLayerName, bTransform, poOutputSRS, bNullifyOutputSRS,
    1335                 :                                  poSourceSRS, papszSelFields, bAppend, eGType,
    1336                 :                                  bOverwrite, eGeomOp, dfGeomOpParam, papszFieldTypesToString,
    1337                 :                                  nCountLayerFeatures, bWrapDateline, poClipSrc, poClipDst,
    1338                 :                                  bExplodeCollections, pszZField, pszWHERE, pfnProgress, pProgressArg))
    1339                 :             {
    1340                 :                 CPLError( CE_Failure, CPLE_AppDefined, 
    1341                 :                           "Terminating translation prematurely after failed\n"
    1342               0 :                           "translation from sql statement." );
    1343                 : 
    1344               0 :                 exit( 1 );
    1345                 :             }
    1346                 : 
    1347              12 :             if (poPassedLayer != poResultSet)
    1348               0 :                 delete poPassedLayer;
    1349                 : 
    1350              12 :             poDS->ReleaseResultSet( poResultSet );
    1351                 :         }
    1352                 :     }
    1353                 : 
    1354                 :     else
    1355                 :     {
    1356             130 :         int nLayerCount = 0;
    1357             130 :         OGRLayer** papoLayers = NULL;
    1358                 : 
    1359                 : /* -------------------------------------------------------------------- */
    1360                 : /*      Process each data source layer.                                 */
    1361                 : /* -------------------------------------------------------------------- */
    1362             130 :         if ( CSLCount(papszLayers) == 0)
    1363                 :         {
    1364             120 :             nLayerCount = poDS->GetLayerCount();
    1365             120 :             papoLayers = (OGRLayer**)CPLMalloc(sizeof(OGRLayer*) * nLayerCount);
    1366                 : 
    1367             304 :             for( int iLayer = 0; 
    1368                 :                  iLayer < nLayerCount; 
    1369                 :                  iLayer++ )
    1370                 :             {
    1371             184 :                 OGRLayer        *poLayer = poDS->GetLayer(iLayer);
    1372                 : 
    1373             184 :                 if( poLayer == NULL )
    1374                 :                 {
    1375                 :                     fprintf( stderr, "FAILURE: Couldn't fetch advertised layer %d!\n",
    1376               0 :                             iLayer );
    1377               0 :                     exit( 1 );
    1378                 :                 }
    1379                 : 
    1380             184 :                 papoLayers[iLayer] = poLayer;
    1381                 :             }
    1382                 :         }
    1383                 : /* -------------------------------------------------------------------- */
    1384                 : /*      Process specified data source layers.                           */
    1385                 : /* -------------------------------------------------------------------- */
    1386                 :         else
    1387                 :         {
    1388              10 :             nLayerCount = CSLCount(papszLayers);
    1389              10 :             papoLayers = (OGRLayer**)CPLMalloc(sizeof(OGRLayer*) * nLayerCount);
    1390                 : 
    1391              40 :             for( int iLayer = 0; 
    1392              20 :                 papszLayers[iLayer] != NULL; 
    1393                 :                 iLayer++ )
    1394                 :             {
    1395              10 :                 OGRLayer        *poLayer = poDS->GetLayerByName(papszLayers[iLayer]);
    1396                 : 
    1397              10 :                 if( poLayer == NULL )
    1398                 :                 {
    1399                 :                     fprintf( stderr, "FAILURE: Couldn't fetch requested layer '%s'!\n",
    1400               0 :                              papszLayers[iLayer] );
    1401               0 :                     if (!bSkipFailures)
    1402               0 :                         exit( 1 );
    1403                 :                 }
    1404                 : 
    1405              10 :                 papoLayers[iLayer] = poLayer;
    1406                 :             }
    1407                 :         }
    1408                 : 
    1409                 : /* -------------------------------------------------------------------- */
    1410                 : /*      Special case to improve user experience when translating into   */
    1411                 : /*      single file shapefile and source has only one layer, and that   */
    1412                 : /*      the layer name isn't specified                                  */
    1413                 : /* -------------------------------------------------------------------- */
    1414                 :         VSIStatBufL  sStat;
    1415             130 :         if (EQUAL(poDriver->GetName(), "ESRI Shapefile") &&
    1416                 :             nLayerCount == 1 && pszNewLayerName == NULL &&
    1417                 :             VSIStatL(pszDestDataSource, &sStat) == 0 && VSI_ISREG(sStat.st_mode))
    1418                 :         {
    1419               6 :             pszNewLayerName = CPLStrdup(CPLGetBasename(pszDestDataSource));
    1420                 :         }
    1421                 : 
    1422             130 :         long* panLayerCountFeatures = (long*) CPLMalloc(sizeof(long) * nLayerCount);
    1423             130 :         long nCountLayersFeatures = 0;
    1424             130 :         long nAccCountFeatures = 0;
    1425                 :         int iLayer;
    1426                 : 
    1427                 :         /* First pass to apply filters and count all features if necessary */
    1428             324 :         for( iLayer = 0; 
    1429                 :             iLayer < nLayerCount; 
    1430                 :             iLayer++ )
    1431                 :         {
    1432             194 :             OGRLayer        *poLayer = papoLayers[iLayer];
    1433             194 :             if (poLayer == NULL)
    1434               0 :                 continue;
    1435                 : 
    1436             194 :             if( pszWHERE != NULL )
    1437                 :             {
    1438               6 :                 if( poLayer->SetAttributeFilter( pszWHERE ) != OGRERR_NONE )
    1439                 :                 {
    1440               0 :                     fprintf( stderr, "FAILURE: SetAttributeFilter(%s) failed.\n", pszWHERE );
    1441               0 :                     if (!bSkipFailures)
    1442               0 :                         exit( 1 );
    1443                 :                 }
    1444                 :             }
    1445                 : 
    1446             194 :             if( poSpatialFilter != NULL )
    1447               4 :                 poLayer->SetSpatialFilter( poSpatialFilter );
    1448                 : 
    1449             194 :             if (bDisplayProgress)
    1450                 :             {
    1451               2 :                 if (!poLayer->TestCapability(OLCFastFeatureCount))
    1452                 :                 {
    1453               0 :                     fprintf( stderr, "Progress turned off as fast feature count is not available.\n");
    1454               0 :                     bDisplayProgress = FALSE;
    1455                 :                 }
    1456                 :                 else
    1457                 :                 {
    1458               2 :                     panLayerCountFeatures[iLayer] = poLayer->GetFeatureCount();
    1459               2 :                     nCountLayersFeatures += panLayerCountFeatures[iLayer];
    1460                 :                 }
    1461                 :             }
    1462                 :         }
    1463                 : 
    1464                 :         /* Second pass to do the real job */
    1465             324 :         for( iLayer = 0; 
    1466                 :             iLayer < nLayerCount; 
    1467                 :             iLayer++ )
    1468                 :         {
    1469             194 :             OGRLayer        *poLayer = papoLayers[iLayer];
    1470             194 :             if (poLayer == NULL)
    1471               0 :                 continue;
    1472                 : 
    1473                 : 
    1474             194 :             OGRLayer* poPassedLayer = poLayer;
    1475             194 :             if (bSplitListFields)
    1476                 :             {
    1477               2 :                 poPassedLayer = new OGRSplitListFieldLayer(poPassedLayer, nMaxSplitListSubFields);
    1478                 : 
    1479               2 :                 if (bDisplayProgress && nMaxSplitListSubFields != 1)
    1480                 :                 {
    1481               0 :                     pfnProgress = GDALScaledProgress;
    1482                 :                     pProgressArg = 
    1483                 :                         GDALCreateScaledProgress(nAccCountFeatures * 1.0 / nCountLayersFeatures,
    1484               0 :                                                 (nAccCountFeatures + panLayerCountFeatures[iLayer] / 2) * 1.0 / nCountLayersFeatures,
    1485                 :                                                 GDALTermProgress,
    1486               0 :                                                 NULL);
    1487                 :                 }
    1488                 :                 else
    1489                 :                 {
    1490               2 :                     pfnProgress = NULL;
    1491               2 :                     pProgressArg = NULL;
    1492                 :                 }
    1493                 : 
    1494               2 :                 int nRet = ((OGRSplitListFieldLayer*)poPassedLayer)->BuildLayerDefn(pfnProgress, pProgressArg);
    1495               2 :                 if (!nRet)
    1496                 :                 {
    1497               0 :                     delete poPassedLayer;
    1498               0 :                     poPassedLayer = poLayer;
    1499                 :                 }
    1500                 : 
    1501               2 :                 if (bDisplayProgress)
    1502               0 :                     GDALDestroyScaledProgress(pProgressArg);
    1503                 :             }
    1504                 : 
    1505                 : 
    1506             194 :             if (bDisplayProgress)
    1507                 :             {
    1508               2 :                 pfnProgress = GDALScaledProgress;
    1509               2 :                 int nStart = 0;
    1510               2 :                 if (poPassedLayer != poLayer && nMaxSplitListSubFields != 1)
    1511               0 :                     nStart = panLayerCountFeatures[iLayer] / 2;
    1512                 :                 pProgressArg = 
    1513                 :                     GDALCreateScaledProgress((nAccCountFeatures + nStart) * 1.0 / nCountLayersFeatures,
    1514               2 :                                             (nAccCountFeatures + panLayerCountFeatures[iLayer]) * 1.0 / nCountLayersFeatures,
    1515                 :                                             GDALTermProgress,
    1516               2 :                                             NULL);
    1517                 :             }
    1518                 : 
    1519             194 :             nAccCountFeatures += panLayerCountFeatures[iLayer];
    1520                 : 
    1521             194 :             if( !TranslateLayer( poDS, poPassedLayer, poODS, papszLCO, 
    1522                 :                                 pszNewLayerName, bTransform, poOutputSRS, bNullifyOutputSRS,
    1523                 :                                 poSourceSRS, papszSelFields, bAppend, eGType,
    1524                 :                                 bOverwrite, eGeomOp, dfGeomOpParam, papszFieldTypesToString,
    1525                 :                                 panLayerCountFeatures[iLayer], bWrapDateline, poClipSrc, poClipDst,
    1526                 :                                 bExplodeCollections, pszZField, pszWHERE, pfnProgress, pProgressArg)
    1527                 :                 && !bSkipFailures )
    1528                 :             {
    1529                 :                 CPLError( CE_Failure, CPLE_AppDefined, 
    1530                 :                         "Terminating translation prematurely after failed\n"
    1531                 :                         "translation of layer %s (use -skipfailures to skip errors)\n", 
    1532               0 :                         poLayer->GetName() );
    1533                 : 
    1534               0 :                 exit( 1 );
    1535                 :             }
    1536                 : 
    1537             194 :             if (poPassedLayer != poLayer)
    1538               2 :                 delete poPassedLayer;
    1539                 : 
    1540             194 :             if (bDisplayProgress)
    1541               2 :                 GDALDestroyScaledProgress(pProgressArg);
    1542                 :         }
    1543                 : 
    1544             130 :         CPLFree(panLayerCountFeatures);
    1545             130 :         CPLFree(papoLayers);
    1546                 :     }
    1547                 : /* -------------------------------------------------------------------- */
    1548                 : /*      Process DS style table                                          */
    1549                 : /* -------------------------------------------------------------------- */
    1550                 : 
    1551             142 :     poODS->SetStyleTable( poDS->GetStyleTable () );
    1552                 :     
    1553                 : /* -------------------------------------------------------------------- */
    1554                 : /*      Close down.                                                     */
    1555                 : /* -------------------------------------------------------------------- */
    1556             142 :     OGRSpatialReference::DestroySpatialReference(poOutputSRS);
    1557             142 :     OGRSpatialReference::DestroySpatialReference(poSourceSRS);
    1558             142 :     if (bCloseODS)
    1559             140 :         OGRDataSource::DestroyDataSource(poODS);
    1560             142 :     OGRDataSource::DestroyDataSource(poDS);
    1561             142 :     OGRGeometryFactory::destroyGeometry(poSpatialFilter);
    1562             142 :     OGRGeometryFactory::destroyGeometry(poClipSrc);
    1563             142 :     OGRGeometryFactory::destroyGeometry(poClipDst);
    1564                 : 
    1565             142 :     CSLDestroy(papszSelFields);
    1566             142 :     CSLDestroy( papszArgv );
    1567             142 :     CSLDestroy( papszLayers );
    1568             142 :     CSLDestroy( papszDSCO );
    1569             142 :     CSLDestroy( papszLCO );
    1570             142 :     CSLDestroy( papszFieldTypesToString );
    1571             142 :     CPLFree( pszNewLayerName );
    1572                 : 
    1573             142 :     OGRCleanupAll();
    1574                 : 
    1575                 : #ifdef DBMALLOC
    1576                 :     malloc_dump(1);
    1577                 : #endif
    1578                 :     
    1579             142 :     return 0;
    1580                 : }
    1581                 : 
    1582                 : /************************************************************************/
    1583                 : /*                               Usage()                                */
    1584                 : /************************************************************************/
    1585                 : 
    1586               0 : static void Usage(int bShort)
    1587                 : 
    1588                 : {
    1589               0 :     OGRSFDriverRegistrar        *poR = OGRSFDriverRegistrar::GetRegistrar();
    1590                 : 
    1591                 : 
    1592                 :     printf( "Usage: ogr2ogr [--help-general] [-skipfailures] [-append] [-update]\n"
    1593                 :             "               [-select field_list] [-where restricted_where]\n"
    1594                 :             "               [-progress] [-sql <sql statement>] [-dialect dialect]\n"
    1595                 :             "               [-preserve_fid] [-fid FID]\n"
    1596                 :             "               [-spat xmin ymin xmax ymax]\n"
    1597                 :             "               [-a_srs srs_def] [-t_srs srs_def] [-s_srs srs_def]\n"
    1598                 :             "               [-f format_name] [-overwrite] [[-dsco NAME=VALUE] ...]\n"
    1599                 :             "               dst_datasource_name src_datasource_name\n"
    1600                 :             "               [-lco NAME=VALUE] [-nln name] [-nlt type] [layer [layer ...]]\n"
    1601                 :             "\n"
    1602                 :             "Advanced options :\n"
    1603                 :             "               [-gt n]\n"
    1604                 :             "               [-clipsrc [xmin ymin xmax ymax]|WKT|datasource|spat_extent]\n"
    1605                 :             "               [-clipsrcsql sql_statement] [-clipsrclayer layer]\n"
    1606                 :             "               [-clipsrcwhere expression]\n"
    1607                 :             "               [-clipdst [xmin ymin xmax ymax]|WKT|datasource]\n"
    1608                 :             "               [-clipdstsql sql_statement] [-clipdstlayer layer]\n"
    1609                 :             "               [-clipdstwhere expression]\n"
    1610                 :             "               [-wrapdateline]\n"
    1611                 :             "               [[-simplify tolerance] | [-segmentize max_dist]]\n"
    1612                 :             "               [-fieldTypeToString All|(type1[,type2]*)]\n"
    1613                 :             "               [-splitlistfields] [-maxsubfields val]\n"
    1614               0 :             "               [-explodecollections] [-zfield field_name]\n");
    1615                 : 
    1616               0 :     if (bShort)
    1617                 :     {
    1618               0 :         printf( "\nNote: ogr2ogr --long-usage for full help.\n");
    1619               0 :         exit( 1 );
    1620                 :     }
    1621                 : 
    1622               0 :     printf("\n -f format_name: output file format name, possible values are:\n");
    1623                 : 
    1624               0 :     for( int iDriver = 0; iDriver < poR->GetDriverCount(); iDriver++ )
    1625                 :     {
    1626               0 :         OGRSFDriver *poDriver = poR->GetDriver(iDriver);
    1627                 : 
    1628               0 :         if( poDriver->TestCapability( ODrCCreateDataSource ) )
    1629               0 :             printf( "     -f \"%s\"\n", poDriver->GetName() );
    1630                 :     }
    1631                 : 
    1632                 :     printf( " -append: Append to existing layer instead of creating new if it exists\n"
    1633                 :             " -overwrite: delete the output layer and recreate it empty\n"
    1634                 :             " -update: Open existing output datasource in update mode\n"
    1635                 :             " -progress: Display progress on terminal. Only works if input layers have the \n"
    1636                 :             "                                          \"fast feature count\" capability\n"
    1637                 :             " -select field_list: Comma-delimited list of fields from input layer to\n"
    1638                 :             "                     copy to the new layer (defaults to all)\n" 
    1639                 :             " -where restricted_where: Attribute query (like SQL WHERE)\n" 
    1640                 :             " -wrapdateline: split geometries crossing the dateline meridian\n"
    1641                 :             "                (long. = +/- 180deg)\n" 
    1642                 :             " -sql statement: Execute given SQL statement and save result.\n"
    1643                 :             " -dialect value: select a dialect, usually OGRSQL to avoid native sql.\n"
    1644                 :             " -skipfailures: skip features or layers that fail to convert\n"
    1645                 :             " -gt n: group n features per transaction (default 200)\n"
    1646                 :             " -spat xmin ymin xmax ymax: spatial query extents\n"
    1647                 :             " -simplify tolerance: distance tolerance for simplification.\n"
    1648                 :             " -segmentize max_dist: maximum distance between 2 nodes.\n"
    1649                 :             "                       Used to create intermediate points\n"
    1650                 :             " -dsco NAME=VALUE: Dataset creation option (format specific)\n"
    1651                 :             " -lco  NAME=VALUE: Layer creation option (format specific)\n"
    1652                 :             " -nln name: Assign an alternate name to the new layer\n"
    1653                 :             " -nlt type: Force a geometry type for new layer.  One of NONE, GEOMETRY,\n"
    1654                 :             "      POINT, LINESTRING, POLYGON, GEOMETRYCOLLECTION, MULTIPOINT,\n"
    1655                 :             "      MULTIPOLYGON, or MULTILINESTRING.  Add \"25D\" for 3D layers.\n"
    1656                 :             "      Default is type of source layer.\n"
    1657                 :             " -fieldTypeToString type1,...: Converts fields of specified types to\n"
    1658                 :             "      fields of type string in the new layer. Valid types are : Integer,\n"
    1659                 :             "      Real, String, Date, Time, DateTime, Binary, IntegerList, RealList,\n"
    1660               0 :             "      StringList. Special value All will convert all fields to strings.\n");
    1661                 : 
    1662                 :     printf(" -a_srs srs_def: Assign an output SRS\n"
    1663                 :            " -t_srs srs_def: Reproject/transform to this SRS on output\n"
    1664                 :            " -s_srs srs_def: Override source SRS\n"
    1665                 :            "\n" 
    1666                 :            " Srs_def can be a full WKT definition (hard to escape properly),\n"
    1667                 :            " or a well known definition (ie. EPSG:4326) or a file with a WKT\n"
    1668               0 :            " definition.\n" );
    1669                 : 
    1670               0 :     exit( 1 );
    1671                 : }
    1672                 : 
    1673                 : /************************************************************************/
    1674                 : /*                               SetZ()                                 */
    1675                 : /************************************************************************/
    1676             120 : static void SetZ (OGRGeometry* poGeom, double dfZ )
    1677                 : {
    1678             120 :     if (poGeom == NULL)
    1679               0 :         return;
    1680             120 :     switch (wkbFlatten(poGeom->getGeometryType()))
    1681                 :     {
    1682                 :         case wkbPoint:
    1683               0 :             ((OGRPoint*)poGeom)->setZ(dfZ);
    1684               0 :             break;
    1685                 : 
    1686                 :         case wkbLineString:
    1687                 :         case wkbLinearRing:
    1688                 :         {
    1689                 :             int i;
    1690              60 :             OGRLineString* poLS = (OGRLineString*) poGeom;
    1691            1530 :             for(i=0;i<poLS->getNumPoints();i++)
    1692            1470 :                 poLS->setPoint(i, poLS->getX(i), poLS->getY(i), dfZ);
    1693              60 :             break;
    1694                 :         }
    1695                 : 
    1696                 :         case wkbPolygon:
    1697                 :         {
    1698                 :             int i;
    1699              60 :             OGRPolygon* poPoly = (OGRPolygon*) poGeom;
    1700              60 :             SetZ(poPoly->getExteriorRing(), dfZ);
    1701              60 :             for(i=0;i<poPoly->getNumInteriorRings();i++)
    1702               0 :                 SetZ(poPoly->getInteriorRing(i), dfZ);
    1703              60 :             break;
    1704                 :         }
    1705                 : 
    1706                 :         case wkbMultiPoint:
    1707                 :         case wkbMultiLineString:
    1708                 :         case wkbMultiPolygon:
    1709                 :         case wkbGeometryCollection:
    1710                 :         {
    1711                 :             int i;
    1712               0 :             OGRGeometryCollection* poGeomColl = (OGRGeometryCollection*) poGeom;
    1713               0 :             for(i=0;i<poGeomColl->getNumGeometries();i++)
    1714               0 :                 SetZ(poGeomColl->getGeometryRef(i), dfZ);
    1715                 :             break;
    1716                 :         }
    1717                 : 
    1718                 :         default:
    1719                 :             break;
    1720                 :     }
    1721                 : }
    1722                 : 
    1723                 : 
    1724                 : /************************************************************************/
    1725                 : /*                           TranslateLayer()                           */
    1726                 : /************************************************************************/
    1727                 : 
    1728             206 : static int TranslateLayer( OGRDataSource *poSrcDS, 
    1729                 :                            OGRLayer * poSrcLayer,
    1730                 :                            OGRDataSource *poDstDS,
    1731                 :                            char **papszLCO,
    1732                 :                            const char *pszNewLayerName,
    1733                 :                            int bTransform, 
    1734                 :                            OGRSpatialReference *poOutputSRS,
    1735                 :                            int bNullifyOutputSRS,
    1736                 :                            OGRSpatialReference *poSourceSRS,
    1737                 :                            char **papszSelFields,
    1738                 :                            int bAppend, int eGType, int bOverwrite,
    1739                 :                            GeomOperation eGeomOp,
    1740                 :                            double dfGeomOpParam,
    1741                 :                            char** papszFieldTypesToString,
    1742                 :                            long nCountLayerFeatures,
    1743                 :                            int bWrapDateline,
    1744                 :                            OGRGeometry* poClipSrc,
    1745                 :                            OGRGeometry *poClipDst,
    1746                 :                            int bExplodeCollections,
    1747                 :                            const char* pszZField,
    1748                 :                            const char* pszWHERE,
    1749                 :                            GDALProgressFunc pfnProgress,
    1750                 :                            void *pProgressArg)
    1751                 : 
    1752                 : {
    1753                 :     OGRLayer    *poDstLayer;
    1754                 :     OGRFeatureDefn *poSrcFDefn;
    1755             206 :     OGRFeatureDefn *poDstFDefn = NULL;
    1756             206 :     int         bForceToPolygon = FALSE;
    1757             206 :     int         bForceToMultiPolygon = FALSE;
    1758             206 :     int         bForceToMultiLineString = FALSE;
    1759                 :     
    1760             206 :     char**      papszTransformOptions = NULL;
    1761                 : 
    1762             206 :     if( pszNewLayerName == NULL )
    1763             174 :         pszNewLayerName = poSrcLayer->GetName();
    1764                 : 
    1765             206 :     if( wkbFlatten(eGType) == wkbPolygon )
    1766               2 :         bForceToPolygon = TRUE;
    1767             204 :     else if( wkbFlatten(eGType) == wkbMultiPolygon )
    1768               4 :         bForceToMultiPolygon = TRUE;
    1769             200 :     else if( wkbFlatten(eGType) == wkbMultiLineString )
    1770               0 :         bForceToMultiLineString = TRUE;
    1771                 : 
    1772                 : /* -------------------------------------------------------------------- */
    1773                 : /*      Setup coordinate transformation if we need it.                  */
    1774                 : /* -------------------------------------------------------------------- */
    1775             206 :     OGRCoordinateTransformation *poCT = NULL;
    1776                 : 
    1777             206 :     if( bTransform )
    1778                 :     {
    1779               4 :         if( poSourceSRS == NULL )
    1780               4 :             poSourceSRS = poSrcLayer->GetSpatialRef();
    1781                 : 
    1782               4 :         if( poSourceSRS == NULL )
    1783                 :         {
    1784                 :             fprintf( stderr, "Can't transform coordinates, source layer has no\n"
    1785               0 :                     "coordinate system.  Use -s_srs to set one.\n" );
    1786               0 :             exit( 1 );
    1787                 :         }
    1788                 : 
    1789               4 :         CPLAssert( NULL != poSourceSRS );
    1790               4 :         CPLAssert( NULL != poOutputSRS );
    1791                 : 
    1792               4 :         poCT = OGRCreateCoordinateTransformation( poSourceSRS, poOutputSRS );
    1793               4 :         if( poCT == NULL )
    1794                 :         {
    1795               0 :             char        *pszWKT = NULL;
    1796                 : 
    1797                 :             fprintf( stderr, "Failed to create coordinate transformation between the\n"
    1798                 :                    "following coordinate systems.  This may be because they\n"
    1799                 :                    "are not transformable, or because projection services\n"
    1800               0 :                    "(PROJ.4 DLL/.so) could not be loaded.\n" );
    1801                 :             
    1802               0 :             poSourceSRS->exportToPrettyWkt( &pszWKT, FALSE );
    1803               0 :             fprintf( stderr,  "Source:\n%s\n", pszWKT );
    1804                 :             
    1805               0 :             poOutputSRS->exportToPrettyWkt( &pszWKT, FALSE );
    1806               0 :             fprintf( stderr,  "Target:\n%s\n", pszWKT );
    1807               0 :             exit( 1 );
    1808                 :         }
    1809                 :     }
    1810                 :     
    1811             206 :     if (bWrapDateline)
    1812                 :     {
    1813               8 :         if( poSourceSRS == NULL )
    1814               6 :             poSourceSRS = poSrcLayer->GetSpatialRef();
    1815                 : 
    1816               8 :         if (poCT != NULL && poOutputSRS->IsGeographic())
    1817                 :         {
    1818                 :             papszTransformOptions =
    1819               2 :                 CSLAddString(papszTransformOptions, "WRAPDATELINE=YES");
    1820                 :         }
    1821               6 :         else if (poSourceSRS != NULL && poOutputSRS == NULL && poSourceSRS->IsGeographic())
    1822                 :         {
    1823                 :             papszTransformOptions =
    1824               6 :                 CSLAddString(papszTransformOptions, "WRAPDATELINE=YES");
    1825                 :         }
    1826                 :         else
    1827                 :         {
    1828               0 :             fprintf(stderr, "-wrapdateline option only works when reprojecting to a geographic SRS\n");
    1829                 :         }
    1830                 :     }
    1831                 :     
    1832                 : /* -------------------------------------------------------------------- */
    1833                 : /*      Get other info.                                                 */
    1834                 : /* -------------------------------------------------------------------- */
    1835             206 :     poSrcFDefn = poSrcLayer->GetLayerDefn();
    1836                 :     
    1837             206 :     if( poOutputSRS == NULL && !bNullifyOutputSRS )
    1838             198 :         poOutputSRS = poSrcLayer->GetSpatialRef();
    1839                 : 
    1840                 : /* -------------------------------------------------------------------- */
    1841                 : /*      Find the layer.                                                 */
    1842                 : /* -------------------------------------------------------------------- */
    1843                 : 
    1844                 :     /* GetLayerByName() can instanciate layers that would have been */
    1845                 :     /* 'hidden' otherwise, for example, non-spatial tables in a */
    1846                 :     /* Postgis-enabled database, so this apparently useless command is */
    1847                 :     /* not useless... (#4012) */
    1848             206 :     CPLPushErrorHandler(CPLQuietErrorHandler);
    1849             206 :     poDstLayer = poDstDS->GetLayerByName(pszNewLayerName);
    1850             206 :     CPLPopErrorHandler();
    1851             206 :     CPLErrorReset();
    1852                 : 
    1853             206 :     int iLayer = -1;
    1854             206 :     if (poDstLayer != NULL)
    1855                 :     {
    1856              26 :         int nLayerCount = poDstDS->GetLayerCount();
    1857             700 :         for( iLayer = 0; iLayer < nLayerCount; iLayer++ )
    1858                 :         {
    1859             700 :             OGRLayer        *poLayer = poDstDS->GetLayer(iLayer);
    1860             700 :             if (poLayer == poDstLayer)
    1861              26 :                 break;
    1862                 :         }
    1863                 : 
    1864              26 :         if (iLayer == nLayerCount)
    1865                 :             /* shouldn't happen with an ideal driver */
    1866               0 :             poDstLayer = NULL;
    1867                 :     }
    1868                 : 
    1869                 : /* -------------------------------------------------------------------- */
    1870                 : /*      If the user requested overwrite, and we have the layer in       */
    1871                 : /*      question we need to delete it now so it will get recreated      */
    1872                 : /*      (overwritten).                                                  */
    1873                 : /* -------------------------------------------------------------------- */
    1874             206 :     if( poDstLayer != NULL && bOverwrite )
    1875                 :     {
    1876              14 :         if( poDstDS->DeleteLayer( iLayer ) != OGRERR_NONE )
    1877                 :         {
    1878                 :             fprintf( stderr, 
    1879               0 :                      "DeleteLayer() failed when overwrite requested.\n" );
    1880               0 :             CSLDestroy(papszTransformOptions);
    1881               0 :             return FALSE;
    1882                 :         }
    1883              14 :         poDstLayer = NULL;
    1884                 :     }
    1885                 : 
    1886                 : /* -------------------------------------------------------------------- */
    1887                 : /*      If the layer does not exist, then create it.                    */
    1888                 : /* -------------------------------------------------------------------- */
    1889             206 :     if( poDstLayer == NULL )
    1890                 :     {
    1891             194 :         if( eGType == -2 )
    1892                 :         {
    1893             180 :             eGType = poSrcFDefn->GetGeomType();
    1894                 : 
    1895             180 :             if ( bExplodeCollections )
    1896                 :             {
    1897               2 :                 int n25DBit = eGType & wkb25DBit;
    1898               2 :                 if (wkbFlatten(eGType) == wkbMultiPoint)
    1899                 :                 {
    1900               0 :                     eGType = wkbPoint | n25DBit;
    1901                 :                 }
    1902               2 :                 else if (wkbFlatten(eGType) == wkbMultiLineString)
    1903                 :                 {
    1904               0 :                     eGType = wkbLineString | n25DBit;
    1905                 :                 }
    1906               2 :                 else if (wkbFlatten(eGType) == wkbMultiPolygon)
    1907                 :                 {
    1908               0 :                     eGType = wkbPolygon | n25DBit;
    1909                 :                 }
    1910               2 :                 else if (wkbFlatten(eGType) == wkbGeometryCollection)
    1911                 :                 {
    1912               0 :                     eGType = wkbUnknown | n25DBit;
    1913                 :                 }
    1914                 :             }
    1915                 : 
    1916             180 :             if ( pszZField )
    1917               6 :                 eGType |= wkb25DBit;
    1918                 :         }
    1919                 : 
    1920             194 :         if( !poDstDS->TestCapability( ODsCCreateLayer ) )
    1921                 :         {
    1922                 :             fprintf( stderr, 
    1923                 :               "Layer %s not found, and CreateLayer not supported by driver.", 
    1924               0 :                      pszNewLayerName );
    1925               0 :             return FALSE;
    1926                 :         }
    1927                 : 
    1928             194 :         CPLErrorReset();
    1929                 : 
    1930                 :         poDstLayer = poDstDS->CreateLayer( pszNewLayerName, poOutputSRS,
    1931                 :                                            (OGRwkbGeometryType) eGType, 
    1932             194 :                                            papszLCO );
    1933                 : 
    1934             194 :         if( poDstLayer == NULL )
    1935                 :         {
    1936               0 :             CSLDestroy(papszTransformOptions);
    1937               0 :             return FALSE;
    1938                 :         }
    1939                 : 
    1940             194 :         bAppend = FALSE;
    1941                 :     }
    1942                 : 
    1943                 : /* -------------------------------------------------------------------- */
    1944                 : /*      Otherwise we will append to it, if append was requested.        */
    1945                 : /* -------------------------------------------------------------------- */
    1946              12 :     else if( !bAppend )
    1947                 :     {
    1948                 :         fprintf( stderr, "FAILED: Layer %s already exists, and -append not specified.\n"
    1949                 :                 "        Consider using -append, or -overwrite.\n",
    1950               0 :                 pszNewLayerName );
    1951               0 :         return FALSE;
    1952                 :     }
    1953                 :     else
    1954                 :     {
    1955              12 :         if( CSLCount(papszLCO) > 0 )
    1956                 :         {
    1957                 :             fprintf( stderr, "WARNING: Layer creation options ignored since an existing layer is\n"
    1958               0 :                     "         being appended to.\n" );
    1959                 :         }
    1960                 :     }
    1961                 : 
    1962                 : /* -------------------------------------------------------------------- */
    1963                 : /*      Process Layer style table                                       */
    1964                 : /* -------------------------------------------------------------------- */
    1965                 : 
    1966             206 :     poDstLayer->SetStyleTable( poSrcLayer->GetStyleTable () );
    1967                 : /* -------------------------------------------------------------------- */
    1968                 : /*      Add fields.  Default to copy all field.                         */
    1969                 : /*      If only a subset of all fields requested, then output only      */
    1970                 : /*      the selected fields, and in the order that they were            */
    1971                 : /*      selected.                                                       */
    1972                 : /* -------------------------------------------------------------------- */
    1973             206 :     int         nSrcFieldCount = poSrcFDefn->GetFieldCount();
    1974                 :     int         iField, *panMap;
    1975                 : 
    1976                 :     // Initialize the index-to-index map to -1's
    1977             206 :     panMap = (int *) VSIMalloc( sizeof(int) * nSrcFieldCount );
    1978            1302 :     for( iField=0; iField < nSrcFieldCount; iField++)
    1979            1096 :         panMap[iField] = -1;
    1980                 :         
    1981                 :     /* Caution : at the time of writing, the MapInfo driver */
    1982                 :     /* returns NULL until a field has been added */
    1983             206 :     poDstFDefn = poDstLayer->GetLayerDefn();
    1984                 : 
    1985             220 :     if (papszSelFields && !bAppend )
    1986                 :     {
    1987              14 :         int  nDstFieldCount = 0;
    1988              14 :         if (poDstFDefn)
    1989              12 :             nDstFieldCount = poDstFDefn->GetFieldCount();
    1990              36 :         for( iField=0; papszSelFields[iField] != NULL; iField++)
    1991                 :         {
    1992              22 :             int iSrcField = poSrcFDefn->GetFieldIndex(papszSelFields[iField]);
    1993              22 :             if (iSrcField >= 0)
    1994                 :             {
    1995              22 :                 OGRFieldDefn* poSrcFieldDefn = poSrcFDefn->GetFieldDefn(iSrcField);
    1996              22 :                 OGRFieldDefn oFieldDefn( poSrcFieldDefn );
    1997                 : 
    1998              22 :                 if (papszFieldTypesToString != NULL &&
    1999                 :                     (CSLFindString(papszFieldTypesToString, "All") != -1 ||
    2000                 :                      CSLFindString(papszFieldTypesToString,
    2001                 :                                    OGRFieldDefn::GetFieldTypeName(poSrcFieldDefn->GetType())) != -1))
    2002                 :                 {
    2003               0 :                     oFieldDefn.SetType(OFTString);
    2004                 :                 }
    2005                 :                 
    2006                 :                 /* The field may have been already created at layer creation */
    2007              22 :                 int iDstField = -1;
    2008              22 :                 if (poDstFDefn)
    2009              20 :                     iDstField = poDstFDefn->GetFieldIndex(oFieldDefn.GetNameRef());
    2010              22 :                 if (iDstField >= 0)
    2011                 :                 {
    2012               0 :                     panMap[iSrcField] = iDstField;
    2013                 :                 }
    2014              22 :                 else if (poDstLayer->CreateField( &oFieldDefn ) == OGRERR_NONE)
    2015                 :                 {
    2016                 :                     /* now that we've created a field, GetLayerDefn() won't return NULL */
    2017              22 :                     if (poDstFDefn == NULL)
    2018               2 :                         poDstFDefn = poDstLayer->GetLayerDefn();
    2019                 : 
    2020                 :                     /* Sanity check : if it fails, the driver is buggy */
    2021              22 :                     if (poDstFDefn != NULL &&
    2022                 :                         poDstFDefn->GetFieldCount() != nDstFieldCount + 1)
    2023                 :                     {
    2024                 :                         CPLError(CE_Warning, CPLE_AppDefined,
    2025                 :                                  "The output driver has claimed to have added the %s field, but it did not!",
    2026               0 :                                  oFieldDefn.GetNameRef() );
    2027                 :                     }
    2028                 :                     else
    2029                 :                     {
    2030              22 :                         panMap[iSrcField] = nDstFieldCount;
    2031              22 :                         nDstFieldCount ++;
    2032                 :                     }
    2033              22 :                 }
    2034                 :             }
    2035                 :             else
    2036                 :             {
    2037                 :                 fprintf( stderr, "Field '%s' not found in source layer.\n", 
    2038               0 :                         papszSelFields[iField] );
    2039               0 :                 if( !bSkipFailures )
    2040                 :                 {
    2041               0 :                     VSIFree(panMap);
    2042               0 :                     CSLDestroy(papszTransformOptions);
    2043               0 :                     return FALSE;
    2044                 :                 }
    2045                 :             }
    2046                 :         }
    2047                 :         
    2048                 :         /* -------------------------------------------------------------------- */
    2049                 :         /* Use SetIgnoredFields() on source layer if available                  */
    2050                 :         /* -------------------------------------------------------------------- */
    2051              14 :         if (poSrcLayer->TestCapability(OLCIgnoreFields))
    2052                 :         {
    2053                 :             int iSrcField;
    2054               6 :             char** papszIgnoredFields = NULL;
    2055               6 :             int bUseIgnoredFields = TRUE;
    2056               6 :             char** papszWHEREUsedFields = NULL;
    2057                 : 
    2058               6 :             if (pszWHERE)
    2059                 :             {
    2060                 :                 /* We must not ignore fields used in the -where expression (#4015) */
    2061               4 :                 OGRFeatureQuery oFeatureQuery;
    2062               4 :                 if ( oFeatureQuery.Compile( poSrcLayer->GetLayerDefn(), pszWHERE ) == OGRERR_NONE )
    2063                 :                 {
    2064               4 :                     papszWHEREUsedFields = oFeatureQuery.GetUsedFields();
    2065                 :                 }
    2066                 :                 else
    2067                 :                 {
    2068               0 :                     bUseIgnoredFields = FALSE;
    2069               4 :                 }
    2070                 :             }
    2071                 : 
    2072              24 :             for(iSrcField=0;iSrcField<poSrcFDefn->GetFieldCount();iSrcField++)
    2073                 :             {
    2074                 :                 const char* pszFieldName =
    2075              18 :                     poSrcFDefn->GetFieldDefn(iSrcField)->GetNameRef();
    2076              18 :                 int bFieldRequested = FALSE;
    2077              32 :                 for( iField=0; papszSelFields[iField] != NULL; iField++)
    2078                 :                 {
    2079              22 :                     if (EQUAL(pszFieldName, papszSelFields[iField]))
    2080                 :                     {
    2081               8 :                         bFieldRequested = TRUE;
    2082               8 :                         break;
    2083                 :                     }
    2084                 :                 }
    2085              18 :                 bFieldRequested |= CSLFindString(papszWHEREUsedFields, pszFieldName) >= 0;
    2086              18 :                 bFieldRequested |= (pszZField != NULL && EQUAL(pszFieldName, pszZField));
    2087                 : 
    2088                 :                 /* If source field not requested, add it to ignored files list */
    2089              18 :                 if (!bFieldRequested)
    2090               8 :                     papszIgnoredFields = CSLAddString(papszIgnoredFields, pszFieldName);
    2091                 :             }
    2092               6 :             if (bUseIgnoredFields)
    2093               6 :                 poSrcLayer->SetIgnoredFields((const char**)papszIgnoredFields);
    2094               6 :             CSLDestroy(papszIgnoredFields);
    2095               6 :             CSLDestroy(papszWHEREUsedFields);
    2096                 :         }
    2097                 :     }
    2098             192 :     else if( !bAppend )
    2099                 :     {
    2100             180 :         int nDstFieldCount = 0;
    2101             180 :         if (poDstFDefn)
    2102             176 :             nDstFieldCount = poDstFDefn->GetFieldCount();
    2103            1204 :         for( iField = 0; iField < nSrcFieldCount; iField++ )
    2104                 :         {
    2105            1024 :             OGRFieldDefn* poSrcFieldDefn = poSrcFDefn->GetFieldDefn(iField);
    2106            1024 :             OGRFieldDefn oFieldDefn( poSrcFieldDefn );
    2107                 : 
    2108            1024 :             if (papszFieldTypesToString != NULL &&
    2109                 :                 (CSLFindString(papszFieldTypesToString, "All") != -1 ||
    2110                 :                  CSLFindString(papszFieldTypesToString,
    2111                 :                                OGRFieldDefn::GetFieldTypeName(poSrcFieldDefn->GetType())) != -1))
    2112                 :             {
    2113               0 :                 oFieldDefn.SetType(OFTString);
    2114                 :             }
    2115                 : 
    2116                 :             /* The field may have been already created at layer creation */
    2117            1024 :             int iDstField = -1;
    2118            1024 :             if (poDstFDefn)
    2119            1020 :                  iDstField = poDstFDefn->GetFieldIndex(oFieldDefn.GetNameRef());
    2120            1024 :             if (iDstField >= 0)
    2121                 :             {
    2122             570 :                 panMap[iField] = iDstField;
    2123                 :             }
    2124             454 :             else if (poDstLayer->CreateField( &oFieldDefn ) == OGRERR_NONE)
    2125                 :             {
    2126                 :                 /* now that we've created a field, GetLayerDefn() won't return NULL */
    2127             454 :                 if (poDstFDefn == NULL)
    2128               4 :                     poDstFDefn = poDstLayer->GetLayerDefn();
    2129                 : 
    2130                 :                 /* Sanity check : if it fails, the driver is buggy */
    2131             454 :                 if (poDstFDefn != NULL &&
    2132                 :                     poDstFDefn->GetFieldCount() != nDstFieldCount + 1)
    2133                 :                 {
    2134                 :                     CPLError(CE_Warning, CPLE_AppDefined,
    2135                 :                              "The output driver has claimed to have added the %s field, but it did not!",
    2136               0 :                              oFieldDefn.GetNameRef() );
    2137                 :                 }
    2138                 :                 else
    2139                 :                 {
    2140             454 :                     panMap[iField] = nDstFieldCount;
    2141             454 :                     nDstFieldCount ++;
    2142                 :                 }
    2143                 :             }
    2144                 :         }
    2145                 :     }
    2146                 :     else
    2147                 :     {
    2148                 :         /* For an existing layer, build the map by fetching the index in the destination */
    2149                 :         /* layer for each source field */
    2150              12 :         if (poDstFDefn == NULL)
    2151                 :         {
    2152               0 :             fprintf( stderr, "poDstFDefn == NULL.\n" );
    2153               0 :             VSIFree(panMap);
    2154               0 :             CSLDestroy(papszTransformOptions);
    2155               0 :             return FALSE;
    2156                 :         }
    2157                 :         
    2158              48 :         for( iField = 0; iField < nSrcFieldCount; iField++ )
    2159                 :         {
    2160              36 :             OGRFieldDefn* poSrcFieldDefn = poSrcFDefn->GetFieldDefn(iField);
    2161              36 :             int iDstField = poDstFDefn->GetFieldIndex(poSrcFieldDefn->GetNameRef());
    2162              36 :             if (iDstField >= 0)
    2163              36 :                 panMap[iField] = iDstField;
    2164                 :         }
    2165                 :     }
    2166                 :     
    2167                 : /* -------------------------------------------------------------------- */
    2168                 : /*      Transfer features.                                              */
    2169                 : /* -------------------------------------------------------------------- */
    2170                 :     OGRFeature  *poFeature;
    2171             206 :     int         nFeaturesInTransaction = 0;
    2172             206 :     GIntBig      nCount = 0; /* written + failed */
    2173             206 :     GIntBig      nFeaturesWritten = 0;
    2174                 : 
    2175             206 :     int iSrcZField = -1;
    2176             206 :     if (pszZField != NULL)
    2177                 :     {
    2178               6 :         iSrcZField = poSrcFDefn->GetFieldIndex(pszZField);
    2179                 :     }
    2180                 :     
    2181             206 :     poSrcLayer->ResetReading();
    2182                 : 
    2183             206 :     if( nGroupTransactions )
    2184             206 :         poDstLayer->StartTransaction();
    2185                 : 
    2186          251704 :     while( TRUE )
    2187                 :     {
    2188          251910 :         OGRFeature      *poDstFeature = NULL;
    2189                 : 
    2190          251910 :         if( nFIDToFetch != OGRNullFID )
    2191                 :         {
    2192                 :             // Only fetch feature on first pass.
    2193               4 :             if( nFeaturesInTransaction == 0 )
    2194               2 :                 poFeature = poSrcLayer->GetFeature(nFIDToFetch);
    2195                 :             else
    2196               2 :                 poFeature = NULL;
    2197                 :         }
    2198                 :         else
    2199          251906 :             poFeature = poSrcLayer->GetNextFeature();
    2200                 :         
    2201          251910 :         if( poFeature == NULL )
    2202                 :             break;
    2203                 : 
    2204          251704 :         int nParts = 0;
    2205          251704 :         int nIters = 1;
    2206          251704 :         if (bExplodeCollections)
    2207                 :         {
    2208               4 :             OGRGeometry* poSrcGeometry = poFeature->GetGeometryRef();
    2209               4 :             if (poSrcGeometry)
    2210                 :             {
    2211               4 :                 switch (wkbFlatten(poSrcGeometry->getGeometryType()))
    2212                 :                 {
    2213                 :                     case wkbMultiPoint:
    2214                 :                     case wkbMultiLineString:
    2215                 :                     case wkbMultiPolygon:
    2216                 :                     case wkbGeometryCollection:
    2217               2 :                         nParts = ((OGRGeometryCollection*)poSrcGeometry)->getNumGeometries();
    2218               2 :                         nIters = nParts;
    2219               2 :                         if (nIters == 0)
    2220               0 :                             nIters = 1;
    2221                 :                     default:
    2222                 :                         break;
    2223                 :                 }
    2224                 :             }
    2225                 :         }
    2226                 : 
    2227          503410 :         for(int iPart = 0; iPart < nIters; iPart++)
    2228                 :         {
    2229          251706 :             if( ++nFeaturesInTransaction == nGroupTransactions )
    2230                 :             {
    2231            1260 :                 poDstLayer->CommitTransaction();
    2232            1260 :                 poDstLayer->StartTransaction();
    2233            1260 :                 nFeaturesInTransaction = 0;
    2234                 :             }
    2235                 : 
    2236          251706 :             CPLErrorReset();
    2237          251706 :             poDstFeature = OGRFeature::CreateFeature( poDstLayer->GetLayerDefn() );
    2238                 : 
    2239          251706 :             if( poDstFeature->SetFrom( poFeature, panMap, TRUE ) != OGRERR_NONE )
    2240                 :             {
    2241               0 :                 if( nGroupTransactions )
    2242               0 :                     poDstLayer->CommitTransaction();
    2243                 : 
    2244                 :                 CPLError( CE_Failure, CPLE_AppDefined,
    2245                 :                         "Unable to translate feature %ld from layer %s.\n",
    2246               0 :                         poFeature->GetFID(), poSrcFDefn->GetName() );
    2247                 : 
    2248               0 :                 OGRFeature::DestroyFeature( poFeature );
    2249               0 :                 OGRFeature::DestroyFeature( poDstFeature );
    2250               0 :                 VSIFree(panMap);
    2251               0 :                 CSLDestroy(papszTransformOptions);
    2252               0 :                 return FALSE;
    2253                 :             }
    2254                 : 
    2255          251706 :             if( bPreserveFID )
    2256               0 :                 poDstFeature->SetFID( poFeature->GetFID() );
    2257                 : 
    2258          251706 :             OGRGeometry* poDstGeometry = poDstFeature->GetGeometryRef();
    2259          251706 :             if (poDstGeometry != NULL)
    2260                 :             {
    2261           48678 :                 if (nParts > 0)
    2262                 :                 {
    2263                 :                     /* For -explodecollections, extract the iPart(th) of the geometry */
    2264               4 :                     OGRGeometry* poPart = ((OGRGeometryCollection*)poDstGeometry)->getGeometryRef(iPart);
    2265               4 :                     ((OGRGeometryCollection*)poDstGeometry)->removeGeometry(iPart, FALSE);
    2266               4 :                     poDstFeature->SetGeometryDirectly(poPart);
    2267               4 :                     poDstGeometry = poPart;
    2268                 :                 }
    2269                 : 
    2270           48678 :                 if (iSrcZField != -1)
    2271                 :                 {
    2272              60 :                     SetZ(poDstGeometry, poFeature->GetFieldAsDouble(iSrcZField));
    2273                 :                     /* This will correct the coordinate dimension to 3 */
    2274              60 :                     OGRGeometry* poDupGeometry = poDstGeometry->clone();
    2275              60 :                     poDstFeature->SetGeometryDirectly(poDupGeometry);
    2276              60 :                     poDstGeometry = poDupGeometry;
    2277                 :                 }
    2278                 : 
    2279           48678 :                 if (eGeomOp == SEGMENTIZE)
    2280                 :                 {
    2281              20 :                     if (dfGeomOpParam > 0)
    2282              20 :                         poDstGeometry->segmentize(dfGeomOpParam);
    2283                 :                 }
    2284           48658 :                 else if (eGeomOp == SIMPLIFY_PRESERVE_TOPOLOGY)
    2285                 :                 {
    2286               0 :                     if (dfGeomOpParam > 0)
    2287                 :                     {
    2288               0 :                         OGRGeometry* poNewGeom = poDstGeometry->SimplifyPreserveTopology(dfGeomOpParam);
    2289               0 :                         if (poNewGeom)
    2290                 :                         {
    2291               0 :                             poDstFeature->SetGeometryDirectly(poNewGeom);
    2292               0 :                             poDstGeometry = poNewGeom;
    2293                 :                         }
    2294                 :                     }
    2295                 :                 }
    2296                 : 
    2297           48678 :                 if (poClipSrc)
    2298                 :                 {
    2299              48 :                     OGRGeometry* poClipped = poDstGeometry->Intersection(poClipSrc);
    2300              48 :                     if (poClipped == NULL || poClipped->IsEmpty())
    2301                 :                     {
    2302              24 :                         OGRGeometryFactory::destroyGeometry(poClipped);
    2303              24 :                         goto end_loop;
    2304                 :                     }
    2305              24 :                     poDstFeature->SetGeometryDirectly(poClipped);
    2306              24 :                     poDstGeometry = poClipped;
    2307                 :                 }
    2308                 : 
    2309           48682 :                 if( poCT != NULL || papszTransformOptions != NULL)
    2310                 :                 {
    2311                 :                     OGRGeometry* poReprojectedGeom =
    2312              28 :                         OGRGeometryFactory::transformWithOptions(poDstGeometry, poCT, papszTransformOptions);
    2313              28 :                     if( poReprojectedGeom == NULL )
    2314                 :                     {
    2315               0 :                         if( nGroupTransactions )
    2316               0 :                             poDstLayer->CommitTransaction();
    2317                 : 
    2318                 :                         fprintf( stderr, "Failed to reproject feature %d (geometry probably out of source or destination SRS).\n",
    2319               0 :                                 (int) poFeature->GetFID() );
    2320               0 :                         if( !bSkipFailures )
    2321                 :                         {
    2322               0 :                             OGRFeature::DestroyFeature( poFeature );
    2323               0 :                             OGRFeature::DestroyFeature( poDstFeature );
    2324               0 :                             VSIFree(panMap);
    2325               0 :                             CSLDestroy(papszTransformOptions);
    2326               0 :                             return FALSE;
    2327                 :                         }
    2328                 :                     }
    2329                 : 
    2330              28 :                     poDstFeature->SetGeometryDirectly(poReprojectedGeom);
    2331              28 :                     poDstGeometry = poReprojectedGeom;
    2332                 :                 }
    2333           48626 :                 else if (poOutputSRS != NULL)
    2334                 :                 {
    2335           48518 :                     poDstGeometry->assignSpatialReference(poOutputSRS);
    2336                 :                 }
    2337                 : 
    2338           48654 :                 if (poClipDst)
    2339                 :                 {
    2340              40 :                     OGRGeometry* poClipped = poDstGeometry->Intersection(poClipDst);
    2341              40 :                     if (poClipped == NULL || poClipped->IsEmpty())
    2342                 :                     {
    2343              24 :                         OGRGeometryFactory::destroyGeometry(poClipped);
    2344              24 :                         goto end_loop;
    2345                 :                     }
    2346                 : 
    2347              16 :                     poDstFeature->SetGeometryDirectly(poClipped);
    2348              16 :                     poDstGeometry = poClipped;
    2349                 :                 }
    2350                 : 
    2351           48630 :                 if( bForceToPolygon )
    2352                 :                 {
    2353                 :                     poDstFeature->SetGeometryDirectly(
    2354                 :                         OGRGeometryFactory::forceToPolygon(
    2355              20 :                             poDstFeature->StealGeometry() ) );
    2356                 :                 }
    2357           48610 :                 else if( bForceToMultiPolygon )
    2358                 :                 {
    2359                 :                     poDstFeature->SetGeometryDirectly(
    2360                 :                         OGRGeometryFactory::forceToMultiPolygon(
    2361              28 :                             poDstFeature->StealGeometry() ) );
    2362                 :                 }
    2363           48582 :                 else if ( bForceToMultiLineString )
    2364                 :                 {
    2365                 :                     poDstFeature->SetGeometryDirectly(
    2366                 :                         OGRGeometryFactory::forceToMultiLineString(
    2367               0 :                             poDstFeature->StealGeometry() ) );
    2368                 :                 }
    2369                 :             }
    2370                 : 
    2371          251658 :             CPLErrorReset();
    2372          251658 :             if( poDstLayer->CreateFeature( poDstFeature ) == OGRERR_NONE )
    2373                 :             {
    2374          251658 :                 nFeaturesWritten ++;
    2375                 :             }
    2376               0 :             else if( !bSkipFailures )
    2377                 :             {
    2378               0 :                 if( nGroupTransactions )
    2379               0 :                     poDstLayer->RollbackTransaction();
    2380                 : 
    2381               0 :                 OGRFeature::DestroyFeature( poFeature );
    2382               0 :                 OGRFeature::DestroyFeature( poDstFeature );
    2383               0 :                 VSIFree(panMap);
    2384               0 :                 CSLDestroy(papszTransformOptions);
    2385               0 :                 return FALSE;
    2386                 :             }
    2387                 : 
    2388                 : end_loop:
    2389          251706 :             OGRFeature::DestroyFeature( poDstFeature );
    2390                 :         }
    2391                 : 
    2392          251704 :         OGRFeature::DestroyFeature( poFeature );
    2393                 : 
    2394                 :         /* Report progress */
    2395          251704 :         nCount ++;
    2396          251704 :         if (pfnProgress)
    2397              20 :             pfnProgress(nCount * 1.0 / nCountLayerFeatures, "", pProgressArg);
    2398                 :     }
    2399                 : 
    2400             206 :     if( nGroupTransactions )
    2401             206 :         poDstLayer->CommitTransaction();
    2402                 : 
    2403                 :     CPLDebug("OGR2OGR", CPL_FRMT_GIB " features written in layer '%s'",
    2404             206 :              nFeaturesWritten, pszNewLayerName);
    2405                 : 
    2406                 : /* -------------------------------------------------------------------- */
    2407                 : /*      Cleaning                                                        */
    2408                 : /* -------------------------------------------------------------------- */
    2409             206 :     OGRCoordinateTransformation::DestroyCT(poCT);
    2410                 :     
    2411             206 :     VSIFree(panMap);
    2412             206 :     CSLDestroy(papszTransformOptions);
    2413                 : 
    2414             206 :     return TRUE;
    2415                 : }
    2416                 : 

Generated by: LCOV version 1.7