LCOV - code coverage report
Current view: directory - apps - ogr2ogr.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 1022 721 70.5 %
Date: 2011-12-18 Functions: 26 15 57.7 %

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

Generated by: LCOV version 1.7