LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/sqlite - ogrsqlitelayer.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 1322 801 60.6 %
Date: 2013-03-30 Functions: 29 26 89.7 %

       1                 : /******************************************************************************
       2                 :  * $Id: ogrsqlitelayer.cpp 25454 2013-01-05 14:18:12Z rouault $
       3                 :  *
       4                 :  * Project:  OpenGIS Simple Features Reference Implementation
       5                 :  * Purpose:  Implements OGRSQLiteLayer class, code shared between 
       6                 :  *           the direct table access, and the generic SQL results.
       7                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       8                 :  *
       9                 :  ******************************************************************************
      10                 :  *
      11                 :  * Contributor: Alessandro Furieri, a.furieri@lqt.it
      12                 :  * Portions of this module supporting SpatiaLite's own 3D geometries
      13                 :  * [XY, XYM, XYZ and XYZM] available since v.2.4.0
      14                 :  * Developed for Faunalia ( http://www.faunalia.it) with funding from 
      15                 :  * Regione Toscana - Settore SISTEMA INFORMATIVO TERRITORIALE ED AMBIENTALE
      16                 :  *
      17                 :  ******************************************************************************
      18                 :  * Copyright (c) 2004, Frank Warmerdam <warmerdam@pobox.com>
      19                 :  *
      20                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      21                 :  * copy of this software and associated documentation files (the "Software"),
      22                 :  * to deal in the Software without restriction, including without limitation
      23                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      24                 :  * and/or sell copies of the Software, and to permit persons to whom the
      25                 :  * Software is furnished to do so, subject to the following conditions:
      26                 :  *
      27                 :  * The above copyright notice and this permission notice shall be included
      28                 :  * in all copies or substantial portions of the Software.
      29                 :  *
      30                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      31                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      32                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      33                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      34                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      35                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      36                 :  * DEALINGS IN THE SOFTWARE.
      37                 :  ****************************************************************************/
      38                 : 
      39                 : #include "cpl_conv.h"
      40                 : #include "cpl_string.h"
      41                 : #include "ogr_sqlite.h"
      42                 : #include <cassert>
      43                 : 
      44                 : CPL_CVSID("$Id: ogrsqlitelayer.cpp 25454 2013-01-05 14:18:12Z rouault $");
      45                 : 
      46                 : /************************************************************************/
      47                 : /*                           OGRSQLiteLayer()                           */
      48                 : /************************************************************************/
      49                 : 
      50            1549 : OGRSQLiteLayer::OGRSQLiteLayer()
      51                 : 
      52                 : {
      53            1549 :     poDS = NULL;
      54                 : 
      55            1549 :     pszFIDColumn = NULL;
      56                 : 
      57            1549 :     eGeomFormat = OSGF_None;
      58                 : 
      59            1549 :     hStmt = NULL;
      60            1549 :     bDoStep = TRUE;
      61                 : 
      62            1549 :     iNextShapeId = 0;
      63                 : 
      64            1549 :     poSRS = NULL;
      65            1549 :     nSRSId = UNINITIALIZED_SRID; // we haven't even queried the database for it yet. 
      66                 : 
      67            1549 :     panFieldOrdinals = NULL;
      68            1549 :     iFIDCol = -1;
      69            1549 :     iGeomCol = -1;
      70                 : 
      71            1549 :     bTriedAsSpatiaLite = FALSE;
      72            1549 :     bHasSpatialIndex = FALSE;
      73            1549 :     bHasM = FALSE;
      74                 : 
      75            1549 :     bIsVirtualShape = FALSE;
      76                 : 
      77            1549 :     bUseComprGeom = CSLTestBoolean(CPLGetConfigOption("COMPRESS_GEOM", "FALSE"));
      78                 : 
      79            1549 :     papszCompressedColumns = NULL;
      80            1549 : }
      81                 : 
      82                 : /************************************************************************/
      83                 : /*                          ~OGRSQLiteLayer()                           */
      84                 : /************************************************************************/
      85                 : 
      86            1549 : OGRSQLiteLayer::~OGRSQLiteLayer()
      87                 : 
      88                 : {
      89            1549 :     Finalize();
      90            1549 : }
      91                 : 
      92                 : /************************************************************************/
      93                 : /*                               Finalize()                             */
      94                 : /************************************************************************/
      95                 : 
      96            2002 : void OGRSQLiteLayer::Finalize()
      97                 : {
      98                 :     /* Caution: this function can be called several times (see */
      99                 :     /* OGRSQLiteExecuteSQLLayer::~OGRSQLiteExecuteSQLLayer()), so it must */
     100                 :     /* be a no-op on second call */
     101                 : 
     102            2002 :     if( m_nFeaturesRead > 0 && poFeatureDefn != NULL )
     103                 :     {
     104                 :         CPLDebug( "SQLite", "%d features read on layer '%s'.",
     105                 :                   (int) m_nFeaturesRead, 
     106             733 :                   poFeatureDefn->GetName() );
     107                 :     }
     108                 : 
     109            2002 :     if( hStmt != NULL )
     110                 :     {
     111             617 :         sqlite3_finalize( hStmt );
     112             617 :         hStmt = NULL;
     113                 :     }
     114                 : 
     115            2002 :     if( poFeatureDefn != NULL )
     116                 :     {
     117            1327 :         poFeatureDefn->Release();
     118            1327 :         poFeatureDefn = NULL;
     119                 :     }
     120                 : 
     121            2002 :     if( poSRS != NULL )
     122                 :     {
     123             407 :         poSRS->Release();
     124             407 :         poSRS = NULL;
     125                 :     }
     126                 : 
     127            2002 :     CPLFree( pszFIDColumn );
     128            2002 :     pszFIDColumn = NULL;
     129            2002 :     CPLFree( panFieldOrdinals );
     130            2002 :     panFieldOrdinals = NULL;
     131                 : 
     132            2002 :     CSLDestroy(papszCompressedColumns);
     133            2002 :     papszCompressedColumns = NULL;
     134            2002 : }
     135                 : 
     136                 : /************************************************************************/
     137                 : /*                          OGRIsBinaryGeomCol()                        */
     138                 : /************************************************************************/
     139                 : 
     140                 : static
     141             299 : int OGRIsBinaryGeomCol( sqlite3_stmt *hStmt, int iCol,
     142                 :                         OGRFieldDefn& oField,
     143                 :                         OGRSQLiteGeomFormat& eGeomFormat,
     144                 :                         CPLString& osGeomColumn )
     145                 : {
     146             299 :     OGRGeometry* poGeometry = NULL;
     147             299 :     const int nBytes = sqlite3_column_bytes( hStmt, iCol );
     148             299 :     CPLPushErrorHandler(CPLQuietErrorHandler);
     149                 :     /* Try as spatialite first since createFromWkb() can sometimes */
     150                 :     /* interpret spatialite blobs as WKB for certain SRID values */
     151             299 :     if( OGRSQLiteLayer::ImportSpatiaLiteGeometry(
     152                 :             (GByte*)sqlite3_column_blob( hStmt, iCol ), nBytes,
     153                 :             &poGeometry ) == OGRERR_NONE )
     154                 :     {
     155             157 :         eGeomFormat = OSGF_SpatiaLite;
     156                 :     }
     157             142 :     else if( OGRGeometryFactory::createFromWkb(
     158                 :             (GByte*)sqlite3_column_blob( hStmt, iCol ),
     159                 :             NULL, &poGeometry, nBytes ) == OGRERR_NONE )
     160                 :     {
     161              10 :         eGeomFormat = OSGF_WKB;
     162                 :     }
     163             132 :     else if( OGRGeometryFactory::createFromFgf( 
     164                 :             (GByte*)sqlite3_column_blob( hStmt, iCol ),
     165                 :             NULL, &poGeometry, nBytes, NULL ) == OGRERR_NONE )
     166                 :     {
     167               0 :         eGeomFormat = OSGF_FGF;
     168                 :     }
     169             299 :     CPLPopErrorHandler();
     170             299 :     CPLErrorReset();
     171             299 :     delete poGeometry;
     172             299 :     if( eGeomFormat != OSGF_None )
     173                 :     {
     174             167 :         osGeomColumn = oField.GetNameRef();
     175             167 :         return TRUE;
     176                 :     }
     177             132 :     return FALSE;
     178                 : }
     179                 : 
     180                 : /************************************************************************/
     181                 : /*                          BuildFeatureDefn()                          */
     182                 : /*                                                                      */
     183                 : /*      Build feature definition from a set of column definitions       */
     184                 : /*      set on a statement.  Sift out geometry and FID fields.          */
     185                 : /************************************************************************/
     186                 : 
     187            1242 : void OGRSQLiteLayer::BuildFeatureDefn( const char *pszLayerName,
     188                 :                                        sqlite3_stmt *hStmt,
     189                 :                                        const std::set<CPLString>& aosGeomCols )
     190                 : 
     191                 : {
     192            1242 :     poFeatureDefn = new OGRFeatureDefn( pszLayerName );
     193            1242 :     int    nRawColumns = sqlite3_column_count( hStmt );
     194                 : 
     195            1242 :     poFeatureDefn->Reference();
     196                 : 
     197            1242 :     panFieldOrdinals = (int *) CPLMalloc( sizeof(int) * nRawColumns );
     198                 : 
     199                 :     int iCol;
     200            1242 :     for( iCol = 0; iCol < nRawColumns; iCol++ )
     201                 :     {
     202                 :         OGRFieldDefn    oField( OGRSQLiteParamsUnquote(sqlite3_column_name( hStmt, iCol )),
     203            4539 :                                 OFTString );
     204                 : 
     205                 :         // In some cases, particularly when there is a real name for
     206                 :         // the primary key/_rowid_ column we will end up getting the
     207                 :         // primary key column appearing twice.  Ignore any repeated names.
     208            4539 :         if( poFeatureDefn->GetFieldIndex( oField.GetNameRef() ) != -1 )
     209               7 :             continue;
     210                 : 
     211                 :         /* In the case of Spatialite VirtualShape, the PKUID */
     212                 :         /* should be considered as a primary key */
     213            4532 :         if( bIsVirtualShape && EQUAL(oField.GetNameRef(), "PKUID") )
     214                 :         {
     215               4 :             CPLFree(pszFIDColumn);
     216               4 :             pszFIDColumn = CPLStrdup(oField.GetNameRef());
     217                 :         }
     218                 : 
     219            4532 :         if( pszFIDColumn != NULL && EQUAL(pszFIDColumn, oField.GetNameRef()))
     220             854 :             continue;
     221                 : 
     222                 :         //oField.SetWidth( MAX(0,poStmt->GetColSize( iCol )) );
     223                 : 
     224            3678 :         if( osGeomColumn.size()
     225                 :             && EQUAL(oField.GetNameRef(),osGeomColumn) )
     226             311 :             continue;
     227            3367 :         if( aosGeomCols.find( oField.GetNameRef() ) != aosGeomCols.end() )
     228               6 :             continue;
     229                 : 
     230            3361 :         int nColType = sqlite3_column_type( hStmt, iCol );
     231            3361 :         const char * pszDeclType = sqlite3_column_decltype(hStmt, iCol);
     232                 :         //CPLDebug("SQLITE", "decltype(%s) = %s",
     233                 :         //         oField.GetNameRef(), pszDeclType ? pszDeclType : "null");
     234            3361 :         OGRFieldType eFieldType = OFTString;
     235            3361 :         if (pszDeclType != NULL)
     236                 :         {
     237            2941 :             if (EQUAL(pszDeclType, "INTEGER"))
     238             764 :                 nColType = SQLITE_INTEGER;
     239            2480 :             else if (EQUAL(pszDeclType, "FLOAT") ||
     240                 :                      EQUAL(pszDeclType, "DECIMAL"))
     241             303 :                 nColType = SQLITE_FLOAT;
     242            1874 :             else if (EQUAL(pszDeclType, "BLOB"))
     243             439 :                 nColType = SQLITE_BLOB;
     244            2101 :             else if (EQUAL(pszDeclType, "TEXT") ||
     245                 :                      EQUALN(pszDeclType, "VARCHAR", 7))
     246                 :             {
     247             666 :                 nColType = SQLITE_TEXT;
     248             666 :                 if( strstr(pszDeclType, "_deflate") != NULL )
     249                 :                 {
     250              48 :                     if( CSLFindString(papszCompressedColumns,
     251                 :                                       oField.GetNameRef()) < 0 )
     252                 :                     {
     253                 :                         papszCompressedColumns = CSLAddString(
     254              48 :                             papszCompressedColumns, oField.GetNameRef());
     255              48 :                         CPLDebug("SQLITE", "%s is compressed", oField.GetNameRef());
     256                 :                     }
     257                 :                 }
     258                 :             }
     259             863 :             else if ((EQUAL(pszDeclType, "TIMESTAMP") ||
     260                 :                       EQUAL(pszDeclType, "DATETIME")) && nColType == SQLITE_TEXT)
     261              94 :                 eFieldType = OFTDateTime;
     262             769 :             else if (EQUAL(pszDeclType, "DATE") && nColType == SQLITE_TEXT)
     263              94 :                 eFieldType = OFTDate;
     264             581 :             else if (EQUAL(pszDeclType, "TIME") && nColType == SQLITE_TEXT)
     265              94 :                 eFieldType = OFTTime;
     266                 :         }
     267                 : 
     268                 :         // Recognise some common geometry column names.
     269            3361 :         if( (EQUAL(oField.GetNameRef(),"wkt_geometry") 
     270                 :              || EQUAL(oField.GetNameRef(),"geometry")
     271                 :              || EQUALN(oField.GetNameRef(), "asbinary(", 9)
     272                 :              || EQUALN(oField.GetNameRef(), "astext(", 7)
     273                 :              || (EQUALN(oField.GetNameRef(), "st_", 3) && nColType == SQLITE_BLOB ) )
     274                 :             && osGeomColumn.size() == 0 )
     275                 :         {
     276             226 :             if( nColType == SQLITE_BLOB )
     277                 :             {
     278             218 :                 const int nBytes = sqlite3_column_bytes( hStmt, iCol );
     279             218 :                 if( nBytes > 0 )
     280                 :                 {
     281             130 :                     if( OGRIsBinaryGeomCol( hStmt, iCol, oField,
     282                 :                                     eGeomFormat, osGeomColumn ) )
     283             130 :                         continue;
     284                 :                 }
     285                 :                 else
     286                 :                 {
     287                 :                     /* This could also be a SpatialLite geometry, so */
     288                 :                     /* we'll also try to decode as SpatialLite if */
     289                 :                     /* bTriedAsSpatiaLite is not FALSE */
     290              88 :                     osGeomColumn = oField.GetNameRef();
     291              88 :                     eGeomFormat = OSGF_WKB;
     292              88 :                     continue;
     293                 :                 }
     294                 :             }
     295               8 :             else if( nColType == SQLITE_TEXT )
     296                 :             {
     297               4 :                 char* pszText = (char*) sqlite3_column_text( hStmt, iCol );
     298               4 :                 if( pszText != NULL )
     299                 :                 {
     300               4 :                     CPLPushErrorHandler(CPLQuietErrorHandler);
     301               4 :                     OGRGeometry* poGeometry = NULL;
     302               4 :                     if( OGRGeometryFactory::createFromWkt( 
     303                 :                         &pszText, NULL, &poGeometry ) == OGRERR_NONE )
     304                 :                     {
     305               3 :                         osGeomColumn = oField.GetNameRef();
     306               3 :                         eGeomFormat = OSGF_WKT;
     307                 :                     }
     308               4 :                     CPLPopErrorHandler();
     309               4 :                     CPLErrorReset();
     310               4 :                     delete poGeometry;
     311               4 :                     if( eGeomFormat != OSGF_None )
     312               3 :                         continue;
     313                 :                 }
     314                 :                 else
     315                 :                 {
     316               0 :                     osGeomColumn = oField.GetNameRef();
     317               0 :                     eGeomFormat = OSGF_WKT;
     318               0 :                     continue;
     319                 :                 }
     320                 :             }
     321                 :         }
     322                 : 
     323                 :         // SpatialLite / Gaia
     324            3140 :         if( EQUAL(oField.GetNameRef(),"GaiaGeometry") 
     325                 :             && osGeomColumn.size() == 0 )
     326                 :         {
     327               0 :             osGeomColumn = oField.GetNameRef();
     328               0 :             eGeomFormat = OSGF_SpatiaLite;
     329               0 :             continue;
     330                 :         }
     331                 : 
     332                 :         // Recognize a geometry column from trying to build the geometry
     333                 :         // Usefull for OGRSQLiteSelectLayer
     334            3140 :         if( nColType == SQLITE_BLOB && osGeomColumn.size() == 0 )
     335                 :         {
     336             261 :             const int nBytes = sqlite3_column_bytes( hStmt, iCol );
     337             261 :             if( nBytes > 0 && OGRIsBinaryGeomCol( hStmt, iCol, oField,
     338                 :                                                   eGeomFormat, osGeomColumn ) )
     339              37 :                 continue;
     340                 :         }
     341                 : 
     342                 :         // The rowid is for internal use, not a real column.
     343            3103 :         if( EQUAL(oField.GetNameRef(),"_rowid_") )
     344               0 :             continue;
     345                 : 
     346                 :         // The OGC_FID is for internal use, not a real user visible column.
     347            3103 :         if( EQUAL(oField.GetNameRef(),"OGC_FID") )
     348              37 :             continue;
     349                 : 
     350            3066 :         switch( nColType )
     351                 :         {
     352                 :           case SQLITE_INTEGER:
     353             907 :             oField.SetType( OFTInteger );
     354             907 :             break;
     355                 : 
     356                 :           case SQLITE_FLOAT:
     357             456 :             oField.SetType( OFTReal );
     358             456 :             break;
     359                 : 
     360                 :           case SQLITE_BLOB:
     361             312 :             oField.SetType( OFTBinary );
     362                 :             break;
     363                 : 
     364                 :           default:
     365                 :             /* leave it as OFTString */;
     366                 :         }
     367                 :         
     368                 :         /* config option just in case we wouldn't want that in some cases */
     369            3066 :         if( (eFieldType == OFTTime || eFieldType == OFTDate ||
     370                 :              eFieldType == OFTDateTime) &&
     371                 :             CSLTestBoolean(
     372                 :                 CPLGetConfigOption("OGR_SQLITE_ENABLE_DATETIME", "YES")) )
     373                 :         {
     374             282 :             oField.SetType( eFieldType );
     375                 :         }
     376                 : 
     377            3066 :         poFeatureDefn->AddFieldDefn( &oField );
     378            3066 :         panFieldOrdinals[poFeatureDefn->GetFieldCount() - 1] = iCol+1;
     379                 :     }
     380                 : 
     381            1242 :     if( pszFIDColumn != NULL )
     382                 :     {
     383             439 :         for( iCol = 0; iCol < nRawColumns; iCol++ )
     384                 :         {
     385             439 :             if( EQUAL(OGRSQLiteParamsUnquote(sqlite3_column_name(hStmt,iCol)).c_str(),
     386                 :                       pszFIDColumn) )
     387                 :             {
     388             435 :                 iFIDCol = iCol;
     389             435 :                 break;
     390                 :             }
     391                 :         }
     392                 :     }
     393                 : 
     394                 : /* -------------------------------------------------------------------- */
     395                 : /*      If we have no geometry source, we know our geometry type is     */
     396                 : /*      none.                                                           */
     397                 : /* -------------------------------------------------------------------- */
     398            1242 :     if( osGeomColumn.size() == 0 )
     399             673 :         poFeatureDefn->SetGeomType( wkbNone );
     400                 :     else
     401                 :     {
     402            2372 :         for( iCol = 0; iCol < nRawColumns; iCol++ )
     403                 :         {
     404            2372 :             if( EQUAL(OGRSQLiteParamsUnquote(sqlite3_column_name(hStmt,iCol)).c_str(),
     405                 :                       osGeomColumn) )
     406                 :             {
     407             569 :                 iGeomCol = iCol;
     408             569 :                 break;
     409                 :             }
     410                 :         }
     411                 :     }
     412            1242 : }
     413                 : 
     414                 : /************************************************************************/
     415                 : /*                            GetFIDColumn()                            */
     416                 : /************************************************************************/
     417                 : 
     418               1 : const char *OGRSQLiteLayer::GetFIDColumn() 
     419                 : 
     420                 : {
     421               1 :     if( pszFIDColumn != NULL )
     422               1 :         return pszFIDColumn;
     423                 :     else
     424               0 :         return "";
     425                 : }
     426                 : 
     427                 : /************************************************************************/
     428                 : /*                         GetGeometryColumn()                          */
     429                 : /************************************************************************/
     430                 : 
     431              37 : const char *OGRSQLiteLayer::GetGeometryColumn() 
     432                 : 
     433                 : {
     434              37 :     if( osGeomColumn.size() != 0 )
     435              37 :         return osGeomColumn.c_str();
     436                 :     else
     437               0 :         return "";
     438                 : }
     439                 : 
     440                 : /************************************************************************/
     441                 : /*                            ResetReading()                            */
     442                 : /************************************************************************/
     443                 : 
     444            1097 : void OGRSQLiteLayer::ResetReading()
     445                 : 
     446                 : {
     447            1097 :     ClearStatement();
     448            1097 :     iNextShapeId = 0;
     449            1097 : }
     450                 : 
     451                 : /************************************************************************/
     452                 : /*                           GetNextFeature()                           */
     453                 : /************************************************************************/
     454                 : 
     455            2910 : OGRFeature *OGRSQLiteLayer::GetNextFeature()
     456                 : 
     457                 : {
     458             216 :     for( ; TRUE; )
     459                 :     {
     460                 :         OGRFeature      *poFeature;
     461                 : 
     462            2910 :         poFeature = GetNextRawFeature();
     463            2910 :         if( poFeature == NULL )
     464             229 :             return NULL;
     465                 : 
     466            2681 :         if( (m_poFilterGeom == NULL
     467                 :             || FilterGeometry( poFeature->GetGeometryRef() ) )
     468                 :             && (m_poAttrQuery == NULL
     469                 :                 || m_poAttrQuery->Evaluate( poFeature )) )
     470            2465 :             return poFeature;
     471                 : 
     472             216 :         delete poFeature;
     473                 :     }
     474                 : }
     475                 : 
     476                 : /************************************************************************/
     477                 : /*                         GetNextRawFeature()                          */
     478                 : /************************************************************************/
     479                 : 
     480            2951 : OGRFeature *OGRSQLiteLayer::GetNextRawFeature()
     481                 : 
     482                 : {
     483            2951 :     if( hStmt == NULL )
     484                 :     {
     485             469 :         ResetStatement();
     486             469 :         if (hStmt == NULL)
     487               2 :             return NULL;
     488                 :     }
     489                 : 
     490                 : /* -------------------------------------------------------------------- */
     491                 : /*      Fetch a record (unless otherwise instructed)                    */
     492                 : /* -------------------------------------------------------------------- */
     493            2949 :     if( bDoStep )
     494                 :     {
     495                 :         int rc;
     496                 : 
     497            2439 :         rc = sqlite3_step( hStmt );
     498            2439 :         if( rc != SQLITE_ROW )
     499                 :         {
     500             243 :             if ( rc != SQLITE_DONE )
     501                 :             {
     502               0 :                 sqlite3_reset(hStmt);
     503                 :                 CPLError( CE_Failure, CPLE_AppDefined,
     504                 :                         "In GetNextRawFeature(): sqlite3_step() : %s",
     505               0 :                         sqlite3_errmsg(poDS->GetDB()) );
     506                 :             }
     507                 : 
     508             243 :             ClearStatement();
     509                 : 
     510             243 :             return NULL;
     511                 :         }
     512                 :     }
     513                 :     else
     514             510 :         bDoStep = TRUE;
     515                 : 
     516                 : /* -------------------------------------------------------------------- */
     517                 : /*      Create a feature from the current result.                       */
     518                 : /* -------------------------------------------------------------------- */
     519                 :     int         iField;
     520            2706 :     OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
     521                 : 
     522                 : /* -------------------------------------------------------------------- */
     523                 : /*      Set FID if we have a column to set it from.                     */
     524                 : /* -------------------------------------------------------------------- */
     525            2706 :     if( iFIDCol >= 0 )
     526            1217 :         poFeature->SetFID( sqlite3_column_int64( hStmt, iFIDCol ) );
     527                 :     else
     528            1489 :         poFeature->SetFID( iNextShapeId );
     529                 : 
     530            2706 :     iNextShapeId++;
     531                 : 
     532            2706 :     m_nFeaturesRead++;
     533                 : 
     534                 : /* -------------------------------------------------------------------- */
     535                 : /*      Process Geometry if we have a column.                           */
     536                 : /* -------------------------------------------------------------------- */
     537            2706 :     if( iGeomCol >= 0 && !poFeatureDefn->IsGeometryIgnored() )
     538                 :     {
     539            2074 :         OGRGeometry *poGeometry = NULL;
     540            2074 :         if ( eGeomFormat == OSGF_WKT )
     541                 :         {
     542              10 :             char *pszWKTCopy, *pszWKT = NULL;
     543                 : 
     544              10 :             pszWKT = (char *) sqlite3_column_text( hStmt, iGeomCol );
     545              10 :             pszWKTCopy = pszWKT;
     546              10 :             if( OGRGeometryFactory::createFromWkt( 
     547                 :                     &pszWKTCopy, NULL, &poGeometry ) == OGRERR_NONE )
     548              10 :                 poFeature->SetGeometryDirectly( poGeometry );
     549                 :         }
     550            2064 :         else if ( eGeomFormat == OSGF_WKB )
     551                 :         {
     552             919 :             const int nBytes = sqlite3_column_bytes( hStmt, iGeomCol );
     553                 : 
     554                 :             /* Try as spatialite first since createFromWkb() can sometimes */
     555                 :             /* interpret spatialite blobs as WKB for certain SRID values */
     556             919 :             if (!bTriedAsSpatiaLite)
     557                 :             {
     558                 :                 /* If the layer is the result of a sql select, we cannot be sure if it is */
     559                 :                 /* WKB or SpatialLite format */
     560              72 :                 if( ImportSpatiaLiteGeometry( 
     561                 :                     (GByte*)sqlite3_column_blob( hStmt, iGeomCol ), nBytes,
     562                 :                     &poGeometry ) == OGRERR_NONE )
     563                 :                 {
     564               0 :                     poFeature->SetGeometryDirectly( poGeometry );
     565               0 :                     eGeomFormat = OSGF_SpatiaLite;
     566                 :                 }
     567              72 :                 bTriedAsSpatiaLite = TRUE;
     568                 :             }
     569                 : 
     570             919 :             if( eGeomFormat == OSGF_WKB && OGRGeometryFactory::createFromWkb( 
     571                 :                     (GByte*)sqlite3_column_blob( hStmt, iGeomCol ),
     572                 :                     NULL, &poGeometry, nBytes ) == OGRERR_NONE )
     573                 :             {
     574             778 :                 poFeature->SetGeometryDirectly( poGeometry );
     575                 :             }
     576                 :         }
     577            1145 :         else if ( eGeomFormat == OSGF_FGF )
     578                 :         {
     579              22 :             const int nBytes = sqlite3_column_bytes( hStmt, iGeomCol );
     580                 : 
     581              22 :             if( OGRGeometryFactory::createFromFgf( 
     582                 :                     (GByte*)sqlite3_column_blob( hStmt, iGeomCol ),
     583                 :                     NULL, &poGeometry, nBytes, NULL ) == OGRERR_NONE )
     584              16 :                 poFeature->SetGeometryDirectly( poGeometry );
     585                 :         }
     586            1123 :         else if ( eGeomFormat == OSGF_SpatiaLite )
     587                 :         {
     588            1123 :             const int nBytes = sqlite3_column_bytes( hStmt, iGeomCol );
     589                 : 
     590            1123 :             if( ImportSpatiaLiteGeometry( 
     591                 :                     (GByte*)sqlite3_column_blob( hStmt, iGeomCol ), nBytes,
     592                 :                     &poGeometry ) == OGRERR_NONE )
     593            1120 :                 poFeature->SetGeometryDirectly( poGeometry );
     594                 :         }
     595                 : 
     596            2074 :         if (poGeometry != NULL && poSRS != NULL)
     597            1191 :             poGeometry->assignSpatialReference(poSRS);
     598                 :     }
     599                 : 
     600                 : /* -------------------------------------------------------------------- */
     601                 : /*      set the fields.                                                 */
     602                 : /* -------------------------------------------------------------------- */
     603            9610 :     for( iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
     604                 :     {
     605            6904 :         OGRFieldDefn *poFieldDefn = poFeatureDefn->GetFieldDefn( iField );
     606            6904 :         if ( poFieldDefn->IsIgnored() )
     607             104 :             continue;
     608                 : 
     609            6800 :         int iRawField = panFieldOrdinals[iField] - 1;
     610                 : 
     611            6800 :         if( sqlite3_column_type( hStmt, iRawField ) == SQLITE_NULL )
     612            1013 :             continue;
     613                 : 
     614            5787 :         switch( poFieldDefn->GetType() )
     615                 :         {
     616                 :         case OFTInteger:
     617                 :             //FIXME use int64 when OGR has 64bit integer support
     618                 :             poFeature->SetField( iField, 
     619             571 :                 sqlite3_column_int( hStmt, iRawField ) );
     620             571 :             break;
     621                 : 
     622                 :         case OFTReal:
     623                 :             poFeature->SetField( iField, 
     624            2721 :                 sqlite3_column_double( hStmt, iRawField ) );
     625            2721 :             break;
     626                 : 
     627                 :         case OFTBinary:
     628                 :             {
     629             170 :                 const int nBytes = sqlite3_column_bytes( hStmt, iRawField );
     630                 : 
     631                 :                 poFeature->SetField( iField, nBytes,
     632             170 :                     (GByte*)sqlite3_column_blob( hStmt, iRawField ) );
     633                 :             }
     634             170 :             break;
     635                 : 
     636                 :         case OFTString:
     637                 :         {
     638            2043 :             if( CSLFindString(papszCompressedColumns,
     639                 :                               poFeatureDefn->GetFieldDefn(iField)->GetNameRef()) >= 0 )
     640                 :             {
     641              39 :                 const int nBytes = sqlite3_column_bytes( hStmt, iRawField );
     642              39 :                 GByte* pabyBlob = (GByte*)sqlite3_column_blob( hStmt, iRawField );
     643                 : 
     644              39 :                 void* pOut = CPLZLibInflate( pabyBlob, nBytes, NULL, 0, NULL );
     645              39 :                 if( pOut != NULL )
     646                 :                 {
     647              39 :                     poFeature->SetField( iField, (const char*) pOut );
     648              39 :                     CPLFree(pOut);
     649                 :                 }
     650                 :                 else
     651                 :                 {
     652                 :                     poFeature->SetField( iField, 
     653                 :                         (const char *) 
     654               0 :                         sqlite3_column_text( hStmt, iRawField ) );
     655                 :                 }
     656                 :             }
     657                 :             else
     658                 :             {
     659                 :                 poFeature->SetField( iField, 
     660                 :                     (const char *) 
     661            2004 :                     sqlite3_column_text( hStmt, iRawField ) );
     662                 :             }
     663            2043 :             break;
     664                 :         }
     665                 : 
     666                 :         case OFTDate:
     667                 :         case OFTTime:
     668                 :         case OFTDateTime:
     669                 :         {
     670             282 :             if( sqlite3_column_type( hStmt, iRawField ) == SQLITE_TEXT )
     671                 :             {
     672                 :                 const char* pszValue = (const char *) 
     673             282 :                     sqlite3_column_text( hStmt, iRawField );
     674             282 :                 OGRSQLITEStringToDateTimeField( poFeature, iField, pszValue );
     675                 :             }
     676                 :             break;
     677                 :         }
     678                 : 
     679                 :         default:
     680                 :             break;
     681                 :         }
     682                 :     }
     683                 : 
     684            2706 :     return poFeature;
     685                 : }
     686                 : 
     687                 : /************************************************************************/
     688                 : /*                             GetFeature()                             */
     689                 : /************************************************************************/
     690                 : 
     691              12 : OGRFeature *OGRSQLiteLayer::GetFeature( long nFeatureId )
     692                 : 
     693                 : {
     694              12 :     return OGRLayer::GetFeature( nFeatureId );
     695                 : }
     696                 : 
     697                 : 
     698                 : /************************************************************************/
     699                 : /*                     createFromSpatialiteInternal()                   */
     700                 : /************************************************************************/
     701                 : 
     702                 : /* See http://www.gaia-gis.it/spatialite/spatialite-manual-2.3.0.html#t3.3 */
     703                 : /* for the specification of the spatialite BLOB geometry format */
     704                 : /* Derived from WKB, but unfortunately it is not practical to reuse existing */
     705                 : /* WKB encoding/decoding code */
     706                 : 
     707                 : #ifdef CPL_LSB
     708                 : #define NEED_SWAP_SPATIALITE()  (eByteOrder != wkbNDR)
     709                 : #else
     710                 : #define NEED_SWAP_SPATIALITE()  (eByteOrder == wkbNDR)
     711                 : #endif
     712                 : 
     713                 : 
     714            1380 : OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
     715                 :                                                     OGRGeometry **ppoReturn,
     716                 :                                                     int nBytes,
     717                 :                                                     OGRwkbByteOrder eByteOrder,
     718                 :                                                     int* pnBytesConsumed,
     719                 :                                                     int nRecLevel)
     720                 : {
     721            1380 :     OGRErr      eErr = OGRERR_NONE;
     722            1380 :     OGRGeometry *poGeom = NULL;
     723                 :     GInt32       nGType;
     724                 :     GInt32       compressedSize;
     725                 : 
     726            1380 :     *ppoReturn = NULL;
     727                 : 
     728                 :     /* Arbitrary value, but certainly large enough for reasonable usages ! */
     729            1380 :     if( nRecLevel == 32 )
     730                 :     {
     731                 :         CPLError( CE_Failure, CPLE_AppDefined,
     732                 :                     "Too many recursiong level (%d) while parsing Spatialite geometry.",
     733               0 :                     nRecLevel );
     734               0 :         return OGRERR_CORRUPT_DATA;
     735                 :     }
     736                 : 
     737            1380 :     if (nBytes < 4)
     738               0 :         return OGRERR_NOT_ENOUGH_DATA;
     739                 : 
     740                 : /* -------------------------------------------------------------------- */
     741                 : /*      Decode the geometry type.                                       */
     742                 : /* -------------------------------------------------------------------- */
     743            1380 :     memcpy( &nGType, pabyData, 4 );
     744            1380 :     if (NEED_SWAP_SPATIALITE())
     745               0 :         CPL_SWAP32PTR( &nGType );
     746                 : 
     747            1380 :     if( ( nGType >= OGRSplitePointXY && 
     748                 :           nGType <= OGRSpliteGeometryCollectionXY ) ||       // XY types
     749                 :         ( nGType >= OGRSplitePointXYZ && 
     750                 :           nGType <= OGRSpliteGeometryCollectionXYZ ) ||      // XYZ types
     751                 :         ( nGType >= OGRSplitePointXYM && 
     752                 :           nGType <= OGRSpliteGeometryCollectionXYM ) ||      // XYM types
     753                 :         ( nGType >= OGRSplitePointXYZM && 
     754                 :           nGType <= OGRSpliteGeometryCollectionXYZM ) ||     // XYZM types
     755                 :         ( nGType >= OGRSpliteComprLineStringXY && 
     756                 :           nGType <= OGRSpliteComprGeometryCollectionXY ) ||  // XY compressed
     757                 :         ( nGType >= OGRSpliteComprLineStringXYZ && 
     758                 :           nGType <= OGRSpliteComprGeometryCollectionXYZ ) || // XYZ compressed
     759                 :         ( nGType >= OGRSpliteComprLineStringXYM && 
     760                 :           nGType <= OGRSpliteComprGeometryCollectionXYM ) || // XYM compressed
     761                 :         ( nGType >= OGRSpliteComprLineStringXYZM && 
     762                 :           nGType <= OGRSpliteComprGeometryCollectionXYZM ) ) // XYZM compressed
     763                 :         ;
     764                 :     else
     765               0 :         return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
     766                 : 
     767                 : /* -------------------------------------------------------------------- */
     768                 : /*      Point [XY]                                                      */
     769                 : /* -------------------------------------------------------------------- */
     770            1380 :     if( nGType == OGRSplitePointXY )
     771                 :     {
     772                 :         double  adfTuple[2];
     773                 : 
     774             476 :         if( nBytes < 4 + 2 * 8 )
     775               0 :             return OGRERR_NOT_ENOUGH_DATA;
     776                 : 
     777             476 :         memcpy( adfTuple, pabyData + 4, 2*8 );
     778             476 :         if (NEED_SWAP_SPATIALITE())
     779                 :         {
     780               0 :             CPL_SWAP64PTR( adfTuple );
     781               0 :             CPL_SWAP64PTR( adfTuple + 1 );
     782                 :         }
     783                 : 
     784             476 :         poGeom = new OGRPoint( adfTuple[0], adfTuple[1] );
     785                 : 
     786             476 :         if( pnBytesConsumed )
     787              14 :             *pnBytesConsumed = 4 + 2 * 8;
     788                 :     }
     789                 : /* -------------------------------------------------------------------- */
     790                 : /*      Point [XYZ]                                                     */
     791                 : /* -------------------------------------------------------------------- */
     792             904 :     else if( nGType == OGRSplitePointXYZ )
     793                 :     {
     794                 :         double  adfTuple[3];
     795                 : 
     796              10 :         if( nBytes < 4 + 3 * 8 )
     797               0 :             return OGRERR_NOT_ENOUGH_DATA;
     798                 : 
     799              10 :         memcpy( adfTuple, pabyData + 4, 3*8 );
     800              10 :         if (NEED_SWAP_SPATIALITE())
     801                 :         {
     802               0 :             CPL_SWAP64PTR( adfTuple );
     803               0 :             CPL_SWAP64PTR( adfTuple + 1 );
     804               0 :             CPL_SWAP64PTR( adfTuple + 2 );
     805                 :         }
     806                 : 
     807              10 :         poGeom = new OGRPoint( adfTuple[0], adfTuple[1], adfTuple[2] );
     808                 : 
     809              10 :         if( pnBytesConsumed )
     810               8 :             *pnBytesConsumed = 4 + 3 * 8;
     811                 :     }
     812                 : 
     813                 : /* -------------------------------------------------------------------- */
     814                 : /*      Point [XYM]                                                     */
     815                 : /* -------------------------------------------------------------------- */
     816             894 :     else if( nGType == OGRSplitePointXYM )
     817                 :     {
     818                 :         double  adfTuple[3];
     819                 : 
     820               0 :         if( nBytes < 4 + 3 * 8 )
     821               0 :             return OGRERR_NOT_ENOUGH_DATA;
     822                 : 
     823               0 :         memcpy( adfTuple, pabyData + 4, 3*8 );
     824               0 :         if (NEED_SWAP_SPATIALITE())
     825                 :         {
     826               0 :             CPL_SWAP64PTR( adfTuple );
     827               0 :             CPL_SWAP64PTR( adfTuple + 1 );
     828               0 :             CPL_SWAP64PTR( adfTuple + 2 );
     829                 :         }
     830                 : 
     831               0 :         poGeom = new OGRPoint( adfTuple[0], adfTuple[1] );
     832                 : 
     833               0 :         if( pnBytesConsumed )
     834               0 :             *pnBytesConsumed = 4 + 3 * 8;
     835                 :     }
     836                 : 
     837                 : /* -------------------------------------------------------------------- */
     838                 : /*      Point [XYZM]                                                    */
     839                 : /* -------------------------------------------------------------------- */
     840             894 :     else if( nGType == OGRSplitePointXYZM )
     841                 :     {
     842                 :         double  adfTuple[4];
     843                 : 
     844               0 :         if( nBytes < 4 + 4 * 8 )
     845               0 :             return OGRERR_NOT_ENOUGH_DATA;
     846                 : 
     847               0 :         memcpy( adfTuple, pabyData + 4, 4*8 );
     848               0 :         if (NEED_SWAP_SPATIALITE())
     849                 :         {
     850               0 :             CPL_SWAP64PTR( adfTuple );
     851               0 :             CPL_SWAP64PTR( adfTuple + 1 );
     852               0 :             CPL_SWAP64PTR( adfTuple + 2 );
     853               0 :             CPL_SWAP64PTR( adfTuple + 3 );
     854                 :         }
     855                 : 
     856               0 :         poGeom = new OGRPoint( adfTuple[0], adfTuple[1], adfTuple[2] );
     857                 : 
     858               0 :         if( pnBytesConsumed )
     859               0 :             *pnBytesConsumed = 4 + 4 * 8;
     860                 :     }
     861                 : 
     862                 : /* -------------------------------------------------------------------- */
     863                 : /*      LineString [XY]                                                 */
     864                 : /* -------------------------------------------------------------------- */
     865             894 :     else if( nGType == OGRSpliteLineStringXY )
     866                 :     {
     867                 :         double adfTuple[2];
     868                 :         GInt32 nPointCount;
     869                 :         int    iPoint;
     870                 :         OGRLineString *poLS;
     871                 : 
     872              25 :         if( nBytes < 8 )
     873               0 :             return OGRERR_NOT_ENOUGH_DATA;
     874                 : 
     875              25 :         memcpy( &nPointCount, pabyData + 4, 4 );
     876              25 :         if (NEED_SWAP_SPATIALITE())
     877               0 :             CPL_SWAP32PTR( &nPointCount );
     878                 : 
     879              25 :         if( nPointCount < 0 || nPointCount > INT_MAX / (2 * 8))
     880               0 :             return OGRERR_CORRUPT_DATA;
     881                 : 
     882              25 :         if (nBytes - 8 < 2 * 8 * nPointCount )
     883               0 :             return OGRERR_NOT_ENOUGH_DATA;
     884                 : 
     885              25 :         poGeom = poLS = new OGRLineString();
     886              25 :         poLS->setNumPoints( nPointCount );
     887                 : 
     888              66 :         for( iPoint = 0; iPoint < nPointCount; iPoint++ )
     889                 :         {
     890              41 :             memcpy( adfTuple, pabyData + 8 + 2*8*iPoint, 2*8 );
     891              41 :             if (NEED_SWAP_SPATIALITE())
     892                 :             {
     893               0 :                 CPL_SWAP64PTR( adfTuple );
     894               0 :                 CPL_SWAP64PTR( adfTuple + 1 );
     895                 :             }
     896                 : 
     897              41 :             poLS->setPoint( iPoint, adfTuple[0], adfTuple[1] );
     898                 :         }
     899                 : 
     900              25 :         if( pnBytesConsumed )
     901               9 :             *pnBytesConsumed = 8 + 2 * 8 * nPointCount;
     902                 :     }
     903                 : 
     904                 : /* -------------------------------------------------------------------- */
     905                 : /*      LineString [XYZ]                                                */
     906                 : /* -------------------------------------------------------------------- */
     907             869 :     else if( nGType == OGRSpliteLineStringXYZ )
     908                 :     {
     909                 :         double adfTuple[3];
     910                 :         GInt32 nPointCount;
     911                 :         int    iPoint;
     912                 :         OGRLineString *poLS;
     913                 : 
     914               7 :         if( nBytes < 8 )
     915               0 :             return OGRERR_NOT_ENOUGH_DATA;
     916                 : 
     917               7 :         memcpy( &nPointCount, pabyData + 4, 4 );
     918               7 :         if (NEED_SWAP_SPATIALITE())
     919               0 :             CPL_SWAP32PTR( &nPointCount );
     920                 : 
     921               7 :         if( nPointCount < 0 || nPointCount > INT_MAX / (3 * 8))
     922               0 :             return OGRERR_CORRUPT_DATA;
     923                 : 
     924               7 :         if (nBytes - 8 < 3 * 8 * nPointCount )
     925               0 :             return OGRERR_NOT_ENOUGH_DATA;
     926                 : 
     927               7 :         poGeom = poLS = new OGRLineString();
     928               7 :         poLS->setNumPoints( nPointCount );
     929                 : 
     930              22 :         for( iPoint = 0; iPoint < nPointCount; iPoint++ )
     931                 :         {
     932              15 :             memcpy( adfTuple, pabyData + 8 + 3*8*iPoint, 3*8 );
     933              15 :             if (NEED_SWAP_SPATIALITE())
     934                 :             {
     935               0 :                 CPL_SWAP64PTR( adfTuple );
     936               0 :                 CPL_SWAP64PTR( adfTuple + 1 );
     937               0 :                 CPL_SWAP64PTR( adfTuple + 2 );
     938                 :             }
     939                 : 
     940              15 :             poLS->setPoint( iPoint, adfTuple[0], adfTuple[1], adfTuple[2] );
     941                 :         }
     942                 : 
     943               7 :         if( pnBytesConsumed )
     944               5 :             *pnBytesConsumed = 8 + 3 * 8 * nPointCount;
     945                 :     }
     946                 : 
     947                 : /* -------------------------------------------------------------------- */
     948                 : /*      LineString [XYM]                                                */
     949                 : /* -------------------------------------------------------------------- */
     950             862 :     else if( nGType == OGRSpliteLineStringXYM )
     951                 :     {
     952                 :         double adfTuple[3];
     953                 :         GInt32 nPointCount;
     954                 :         int    iPoint;
     955                 :         OGRLineString *poLS;
     956                 : 
     957               0 :         if( nBytes < 8 )
     958               0 :             return OGRERR_NOT_ENOUGH_DATA;
     959                 : 
     960               0 :         memcpy( &nPointCount, pabyData + 4, 4 );
     961               0 :         if (NEED_SWAP_SPATIALITE())
     962               0 :             CPL_SWAP32PTR( &nPointCount );
     963                 : 
     964               0 :         if( nPointCount < 0 || nPointCount > INT_MAX / (3 * 8))
     965               0 :             return OGRERR_CORRUPT_DATA;
     966                 : 
     967               0 :         if (nBytes - 8 < 3 * 8 * nPointCount )
     968               0 :             return OGRERR_NOT_ENOUGH_DATA;
     969                 : 
     970               0 :         poGeom = poLS = new OGRLineString();
     971               0 :         poLS->setNumPoints( nPointCount );
     972                 : 
     973               0 :         for( iPoint = 0; iPoint < nPointCount; iPoint++ )
     974                 :         {
     975               0 :             memcpy( adfTuple, pabyData + 8 + 3*8*iPoint, 3*8 );
     976               0 :             if (NEED_SWAP_SPATIALITE())
     977                 :             {
     978               0 :                 CPL_SWAP64PTR( adfTuple );
     979               0 :                 CPL_SWAP64PTR( adfTuple + 1 );
     980               0 :                 CPL_SWAP64PTR( adfTuple + 2 );
     981                 :             }
     982                 : 
     983               0 :             poLS->setPoint( iPoint, adfTuple[0], adfTuple[1] );
     984                 :         }
     985                 : 
     986               0 :         if( pnBytesConsumed )
     987               0 :             *pnBytesConsumed = 8 + 3 * 8 * nPointCount;
     988                 :     }
     989                 : 
     990                 : /* -------------------------------------------------------------------- */
     991                 : /*      LineString [XYZM]                                               */
     992                 : /* -------------------------------------------------------------------- */
     993             862 :     else if( nGType == OGRSpliteLineStringXYZM )
     994                 :     {
     995                 :         double adfTuple[4];
     996                 :         GInt32 nPointCount;
     997                 :         int    iPoint;
     998                 :         OGRLineString *poLS;
     999                 : 
    1000               0 :         if( nBytes < 8 )
    1001               0 :             return OGRERR_NOT_ENOUGH_DATA;
    1002                 : 
    1003               0 :         memcpy( &nPointCount, pabyData + 4, 4 );
    1004               0 :         if (NEED_SWAP_SPATIALITE())
    1005               0 :             CPL_SWAP32PTR( &nPointCount );
    1006                 : 
    1007               0 :         if( nPointCount < 0 || nPointCount > INT_MAX / (4 * 8))
    1008               0 :             return OGRERR_CORRUPT_DATA;
    1009                 : 
    1010               0 :         if (nBytes - 8 < 4 * 8 * nPointCount )
    1011               0 :             return OGRERR_NOT_ENOUGH_DATA;
    1012                 : 
    1013               0 :         poGeom = poLS = new OGRLineString();
    1014               0 :         poLS->setNumPoints( nPointCount );
    1015                 : 
    1016               0 :         for( iPoint = 0; iPoint < nPointCount; iPoint++ )
    1017                 :         {
    1018               0 :             memcpy( adfTuple, pabyData + 8 + 4*8*iPoint, 4*8 );
    1019               0 :             if (NEED_SWAP_SPATIALITE())
    1020                 :             {
    1021               0 :                 CPL_SWAP64PTR( adfTuple );
    1022               0 :                 CPL_SWAP64PTR( adfTuple + 1 );
    1023               0 :                 CPL_SWAP64PTR( adfTuple + 2 );
    1024               0 :                 CPL_SWAP64PTR( adfTuple + 3 );
    1025                 :             }
    1026                 : 
    1027               0 :             poLS->setPoint( iPoint, adfTuple[0], adfTuple[1], adfTuple[2] );
    1028                 :         }
    1029                 : 
    1030               0 :         if( pnBytesConsumed )
    1031               0 :             *pnBytesConsumed = 8 + 4 * 8 * nPointCount;
    1032                 :     }
    1033                 : 
    1034                 : /* -------------------------------------------------------------------- */
    1035                 : /*      LineString [XY] Compressed                                      */
    1036                 : /* -------------------------------------------------------------------- */
    1037             862 :     else if( nGType == OGRSpliteComprLineStringXY )
    1038                 :     {
    1039                 :         double adfTuple[2];
    1040                 :         double adfTupleBase[2];
    1041                 :         float asfTuple[2];
    1042                 :         GInt32 nPointCount;
    1043                 :         int    iPoint;
    1044                 :         OGRLineString *poLS;
    1045                 :         int    nNextByte;
    1046                 : 
    1047               5 :         if( nBytes < 8 )
    1048               0 :             return OGRERR_NOT_ENOUGH_DATA;
    1049                 : 
    1050               5 :         memcpy( &nPointCount, pabyData + 4, 4 );
    1051               5 :         if (NEED_SWAP_SPATIALITE())
    1052               0 :             CPL_SWAP32PTR( &nPointCount );
    1053                 : 
    1054               5 :         if( nPointCount < 0 || nPointCount - 2 > (INT_MAX - 16 * 2) / 8)
    1055               0 :             return OGRERR_CORRUPT_DATA;
    1056                 : 
    1057               5 :         compressedSize = 16 * 2;                  // first and last Points 
    1058               5 :         compressedSize += 8 * (nPointCount - 2);  // intermediate Points
    1059                 : 
    1060               5 :         if (nBytes - 8 < compressedSize )
    1061               0 :             return OGRERR_NOT_ENOUGH_DATA;
    1062                 : 
    1063               5 :         poGeom = poLS = new OGRLineString();
    1064               5 :         poLS->setNumPoints( nPointCount );
    1065                 : 
    1066               5 :         nNextByte = 8;
    1067               5 :         adfTupleBase[0] = 0.0;
    1068               5 :         adfTupleBase[1] = 0.0;
    1069                 :     
    1070              16 :         for( iPoint = 0; iPoint < nPointCount; iPoint++ )
    1071                 :         {
    1072              21 :             if ( iPoint == 0 || iPoint == (nPointCount - 1 ) )
    1073                 :             {
    1074                 :                 // first and last Points are uncompressed 
    1075              10 :                 memcpy( adfTuple, pabyData + nNextByte, 2*8 );
    1076              10 :                 nNextByte += 2 * 8;
    1077                 :       
    1078              10 :                 if (NEED_SWAP_SPATIALITE())
    1079                 :                 {
    1080               0 :                     CPL_SWAP64PTR( adfTuple );
    1081               0 :                     CPL_SWAP64PTR( adfTuple + 1 );
    1082                 :                 }
    1083                 :             }
    1084                 :             else
    1085                 :             {
    1086                 :                 // any other intermediate Point is compressed
    1087               1 :                 memcpy( asfTuple, pabyData + nNextByte, 2*4 );
    1088               1 :                 nNextByte += 2 * 4;
    1089                 : 
    1090               1 :                 if (NEED_SWAP_SPATIALITE())
    1091                 :                 {
    1092               0 :                     CPL_SWAP32PTR( asfTuple );
    1093               0 :                     CPL_SWAP32PTR( asfTuple + 1 );
    1094                 :                 }
    1095               1 :                 adfTuple[0] = asfTuple[0] + adfTupleBase[0];
    1096               1 :                 adfTuple[1] = asfTuple[1] + adfTupleBase[1];
    1097                 :             }
    1098                 : 
    1099              11 :             poLS->setPoint( iPoint, adfTuple[0], adfTuple[1] );
    1100              11 :             adfTupleBase[0] = adfTuple[0];
    1101              11 :             adfTupleBase[1] = adfTuple[1];
    1102                 :         }
    1103                 : 
    1104               5 :         if( pnBytesConsumed )
    1105               3 :             *pnBytesConsumed = nNextByte;
    1106                 :     }
    1107                 : 
    1108                 : /* -------------------------------------------------------------------- */
    1109                 : /*      LineString [XYZ] Compressed                                     */
    1110                 : /* -------------------------------------------------------------------- */
    1111             857 :     else if( nGType == OGRSpliteComprLineStringXYZ )
    1112                 :     {
    1113                 :         double adfTuple[3];
    1114                 :         double adfTupleBase[3];
    1115                 :         float asfTuple[3];
    1116                 :         GInt32 nPointCount;
    1117                 :         int    iPoint;
    1118                 :         OGRLineString *poLS;
    1119                 :         int    nNextByte;
    1120                 : 
    1121               5 :         if( nBytes < 8 )
    1122               0 :             return OGRERR_NOT_ENOUGH_DATA;
    1123                 : 
    1124               5 :         memcpy( &nPointCount, pabyData + 4, 4 );
    1125               5 :         if (NEED_SWAP_SPATIALITE())
    1126               0 :             CPL_SWAP32PTR( &nPointCount );
    1127                 : 
    1128               5 :         if( nPointCount < 0 || nPointCount - 2 > (INT_MAX - 24 * 2) / 12)
    1129               0 :             return OGRERR_CORRUPT_DATA;
    1130                 : 
    1131               5 :         compressedSize = 24 * 2;                  // first and last Points
    1132               5 :         compressedSize += 12 * (nPointCount - 2);  // intermediate Points
    1133                 : 
    1134               5 :         if (nBytes - 8 < compressedSize )
    1135               0 :             return OGRERR_NOT_ENOUGH_DATA;
    1136                 : 
    1137               5 :         poGeom = poLS = new OGRLineString();
    1138               5 :         poLS->setNumPoints( nPointCount );
    1139                 : 
    1140               5 :         nNextByte = 8;
    1141               5 :         adfTupleBase[0] = 0.0;
    1142               5 :         adfTupleBase[1] = 0.0;
    1143               5 :         adfTupleBase[2] = 0.0;
    1144                 :     
    1145              16 :         for( iPoint = 0; iPoint < nPointCount; iPoint++ )
    1146                 :         {
    1147              21 :             if ( iPoint == 0 || iPoint == (nPointCount - 1 ) )
    1148                 :             {
    1149                 :                 // first and last Points are uncompressed 
    1150              10 :                 memcpy( adfTuple, pabyData + nNextByte, 3*8 );
    1151              10 :                 nNextByte += 3 * 8;
    1152                 : 
    1153              10 :                 if (NEED_SWAP_SPATIALITE())
    1154                 :                 {
    1155               0 :                     CPL_SWAP64PTR( adfTuple );
    1156               0 :                     CPL_SWAP64PTR( adfTuple + 1 );
    1157               0 :                     CPL_SWAP64PTR( adfTuple + 2 );
    1158                 :                 }
    1159                 :             }
    1160                 :             else
    1161                 :             {
    1162                 :                 // any other intermediate Point is compressed 
    1163               1 :                 memcpy( asfTuple, pabyData + nNextByte, 3*4 );
    1164               1 :                 nNextByte += 3 * 4;
    1165                 : 
    1166               1 :                 if (NEED_SWAP_SPATIALITE())
    1167                 :                 {
    1168               0 :                     CPL_SWAP32PTR( asfTuple );
    1169               0 :                     CPL_SWAP32PTR( asfTuple + 1 );
    1170               0 :                     CPL_SWAP32PTR( asfTuple + 2 );
    1171                 :                 }
    1172               1 :                 adfTuple[0] = asfTuple[0] + adfTupleBase[0];
    1173               1 :                 adfTuple[1] = asfTuple[1] + adfTupleBase[1];
    1174               1 :                 adfTuple[2] = asfTuple[2] + adfTupleBase[2];
    1175                 :             }
    1176                 : 
    1177              11 :             poLS->setPoint( iPoint, adfTuple[0], adfTuple[1], adfTuple[2] );
    1178              11 :             adfTupleBase[0] = adfTuple[0];
    1179              11 :             adfTupleBase[1] = adfTuple[1];
    1180              11 :             adfTupleBase[2] = adfTuple[2];
    1181                 :         }
    1182                 : 
    1183               5 :         if( pnBytesConsumed )
    1184               3 :             *pnBytesConsumed = nNextByte;
    1185                 :     }
    1186                 : 
    1187                 : /* -------------------------------------------------------------------- */
    1188                 : /*      LineString [XYM] Compressed                                     */
    1189                 : /* -------------------------------------------------------------------- */
    1190             852 :     else if( nGType == OGRSpliteComprLineStringXYM )
    1191                 :     {
    1192                 :         double adfTuple[2];
    1193                 :         double adfTupleBase[2];
    1194                 :         float asfTuple[2];
    1195                 :         GInt32 nPointCount;
    1196                 :         int    iPoint;
    1197                 :         OGRLineString *poLS;
    1198                 :         int    nNextByte;
    1199                 : 
    1200               0 :         if( nBytes < 8 )
    1201               0 :             return OGRERR_NOT_ENOUGH_DATA;
    1202                 : 
    1203               0 :         memcpy( &nPointCount, pabyData + 4, 4 );
    1204               0 :         if (NEED_SWAP_SPATIALITE())
    1205               0 :             CPL_SWAP32PTR( &nPointCount );
    1206                 : 
    1207               0 :         if( nPointCount < 0 || nPointCount - 2 > (INT_MAX - 24 * 2) / 16)
    1208               0 :             return OGRERR_CORRUPT_DATA;
    1209                 : 
    1210               0 :         compressedSize = 24 * 2;                  // first and last Points
    1211               0 :         compressedSize += 16 * (nPointCount - 2);  // intermediate Points
    1212                 : 
    1213               0 :         if (nBytes - 8 < compressedSize )
    1214               0 :             return OGRERR_NOT_ENOUGH_DATA;
    1215                 : 
    1216               0 :         poGeom = poLS = new OGRLineString();
    1217               0 :         poLS->setNumPoints( nPointCount );
    1218                 : 
    1219               0 :         nNextByte = 8;
    1220               0 :         adfTupleBase[0] = 0.0;
    1221               0 :         adfTupleBase[1] = 0.0;
    1222                 :     
    1223               0 :         for( iPoint = 0; iPoint < nPointCount; iPoint++ )
    1224                 :         {
    1225               0 :             if ( iPoint == 0 || iPoint == (nPointCount - 1 ) )
    1226                 :             {
    1227                 :                 // first and last Points are uncompressed 
    1228               0 :                 memcpy( adfTuple, pabyData + nNextByte, 2*8 );
    1229               0 :                 nNextByte += 3 * 8;
    1230                 : 
    1231               0 :                 if (NEED_SWAP_SPATIALITE())
    1232                 :                 {
    1233               0 :                     CPL_SWAP64PTR( adfTuple );
    1234               0 :                     CPL_SWAP64PTR( adfTuple + 1 );
    1235                 :                 }
    1236                 :             }
    1237                 :             else
    1238                 :             {
    1239                 :                 // any other intermediate Point is compressed
    1240               0 :                 memcpy( asfTuple, pabyData + nNextByte, 2*4 );
    1241               0 :                 nNextByte += 2 * 4 + 8;
    1242                 : 
    1243               0 :                 if (NEED_SWAP_SPATIALITE())
    1244                 :                 {
    1245               0 :                     CPL_SWAP32PTR( asfTuple );
    1246               0 :                     CPL_SWAP32PTR( asfTuple + 1 );
    1247                 :                 }
    1248               0 :                 adfTuple[0] = asfTuple[0] + adfTupleBase[0];
    1249               0 :                 adfTuple[1] = asfTuple[1] + adfTupleBase[1];
    1250                 :             }
    1251                 : 
    1252               0 :             poLS->setPoint( iPoint, adfTuple[0], adfTuple[1] );
    1253               0 :             adfTupleBase[0] = adfTuple[0];
    1254               0 :             adfTupleBase[1] = adfTuple[1];
    1255                 :         }
    1256                 : 
    1257               0 :         if( pnBytesConsumed )
    1258               0 :             *pnBytesConsumed = nNextByte;
    1259                 :     }
    1260                 : 
    1261                 : /* -------------------------------------------------------------------- */
    1262                 : /*      LineString [XYZM] Compressed                                    */
    1263                 : /* -------------------------------------------------------------------- */
    1264             852 :     else if( nGType == OGRSpliteComprLineStringXYZM )
    1265                 :     {
    1266                 :         double adfTuple[3];
    1267                 :         double adfTupleBase[3];
    1268                 :         float asfTuple[3];
    1269                 :         GInt32 nPointCount;
    1270                 :         int    iPoint;
    1271                 :         OGRLineString *poLS;
    1272                 :         int    nNextByte;
    1273                 : 
    1274               0 :         if( nBytes < 8 )
    1275               0 :             return OGRERR_NOT_ENOUGH_DATA;
    1276                 : 
    1277               0 :         memcpy( &nPointCount, pabyData + 4, 4 );
    1278               0 :         if (NEED_SWAP_SPATIALITE())
    1279               0 :             CPL_SWAP32PTR( &nPointCount );
    1280                 : 
    1281               0 :         if( nPointCount < 0 || nPointCount - 2 > (INT_MAX - 32 * 2) / 20)
    1282               0 :             return OGRERR_CORRUPT_DATA;
    1283                 : 
    1284               0 :         compressedSize = 32 * 2;                   // first and last Points
    1285                 :         /* Note 20 is not an error : x,y,z are float and the m is a double */
    1286               0 :         compressedSize += 20 * (nPointCount - 2);  // intermediate Points
    1287                 : 
    1288               0 :         if (nBytes - 8 < compressedSize )
    1289               0 :             return OGRERR_NOT_ENOUGH_DATA;
    1290                 : 
    1291               0 :         poGeom = poLS = new OGRLineString();
    1292               0 :         poLS->setNumPoints( nPointCount );
    1293                 : 
    1294               0 :         nNextByte = 8;
    1295               0 :         adfTupleBase[0] = 0.0;
    1296               0 :         adfTupleBase[1] = 0.0;
    1297               0 :         adfTupleBase[2] = 0.0;
    1298                 :     
    1299               0 :         for( iPoint = 0; iPoint < nPointCount; iPoint++ )
    1300                 :         {
    1301               0 :             if ( iPoint == 0 || iPoint == (nPointCount - 1 ) )
    1302                 :             {
    1303                 :                 // first and last Points are uncompressed
    1304               0 :                 memcpy( adfTuple, pabyData + nNextByte, 3*8 );
    1305               0 :                 nNextByte += 4 * 8;
    1306                 : 
    1307               0 :                 if (NEED_SWAP_SPATIALITE())
    1308                 :                 {
    1309               0 :                     CPL_SWAP64PTR( adfTuple );
    1310               0 :                     CPL_SWAP64PTR( adfTuple + 1 );
    1311               0 :                     CPL_SWAP64PTR( adfTuple + 2 );
    1312                 :                 }
    1313                 :             }
    1314                 :             else
    1315                 :             {
    1316                 :                 // any other intermediate Point is compressed
    1317               0 :                 memcpy( asfTuple, pabyData + nNextByte, 3*4 );
    1318               0 :                 nNextByte += 3 * 4 + 8;
    1319                 : 
    1320               0 :                 if (NEED_SWAP_SPATIALITE())
    1321                 :                 {
    1322               0 :                     CPL_SWAP32PTR( asfTuple );
    1323               0 :                     CPL_SWAP32PTR( asfTuple + 1 );
    1324               0 :                     CPL_SWAP32PTR( asfTuple + 2 );
    1325                 :                 }
    1326               0 :                 adfTuple[0] = asfTuple[0] + adfTupleBase[0];
    1327               0 :                 adfTuple[1] = asfTuple[1] + adfTupleBase[1];
    1328               0 :                 adfTuple[2] = asfTuple[2] + adfTupleBase[2];
    1329                 :             }
    1330                 : 
    1331               0 :             poLS->setPoint( iPoint, adfTuple[0], adfTuple[1], adfTuple[2] );
    1332               0 :             adfTupleBase[0] = adfTuple[0];
    1333               0 :             adfTupleBase[1] = adfTuple[1];
    1334               0 :             adfTupleBase[2] = adfTuple[2];
    1335                 :         }
    1336                 : 
    1337               0 :         if( pnBytesConsumed )
    1338               0 :             *pnBytesConsumed = nNextByte;
    1339                 :     }
    1340                 : 
    1341                 : /* -------------------------------------------------------------------- */
    1342                 : /*      Polygon [XY]                                                    */
    1343                 : /* -------------------------------------------------------------------- */
    1344             852 :     else if( nGType == OGRSplitePolygonXY )
    1345                 :     {
    1346                 :         double adfTuple[2];
    1347                 :         GInt32 nPointCount;
    1348                 :         GInt32 nRingCount;
    1349                 :         int    iPoint, iRing;
    1350                 :         OGRLinearRing *poLR;
    1351                 :         OGRPolygon *poPoly;
    1352                 :         int    nNextByte;
    1353                 : 
    1354             467 :         if( nBytes < 8 )
    1355               0 :             return OGRERR_NOT_ENOUGH_DATA;
    1356                 : 
    1357             467 :         memcpy( &nRingCount, pabyData + 4, 4 );
    1358             467 :         if (NEED_SWAP_SPATIALITE())
    1359               0 :             CPL_SWAP32PTR( &nRingCount );
    1360                 : 
    1361             467 :         if (nRingCount < 0 || nRingCount > INT_MAX / 4)
    1362               0 :             return OGRERR_CORRUPT_DATA;
    1363                 : 
    1364                 :         // Each ring has a minimum of 4 bytes 
    1365             467 :         if (nBytes - 8 < nRingCount * 4)
    1366               0 :             return OGRERR_NOT_ENOUGH_DATA;
    1367                 : 
    1368             467 :         nNextByte = 8;
    1369                 :         
    1370             467 :         poGeom = poPoly = new OGRPolygon();
    1371                 : 
    1372             939 :         for( iRing = 0; iRing < nRingCount; iRing++ )
    1373                 :         {
    1374             472 :             if( nBytes - nNextByte < 4 )
    1375               0 :                 return OGRERR_NOT_ENOUGH_DATA;
    1376                 : 
    1377             472 :             memcpy( &nPointCount, pabyData + nNextByte, 4 );
    1378             472 :             if (NEED_SWAP_SPATIALITE())
    1379               0 :                 CPL_SWAP32PTR( &nPointCount );
    1380                 : 
    1381             472 :             if( nPointCount < 0 || nPointCount > INT_MAX / (2 * 8))
    1382               0 :                 return OGRERR_CORRUPT_DATA;
    1383                 : 
    1384             472 :             nNextByte += 4;
    1385                 : 
    1386             472 :             if( nBytes - nNextByte < 2 * 8 * nPointCount )
    1387               0 :                 return OGRERR_NOT_ENOUGH_DATA;
    1388                 : 
    1389             472 :             poLR = new OGRLinearRing();
    1390             472 :             poLR->setNumPoints( nPointCount );
    1391                 :             
    1392            7190 :             for( iPoint = 0; iPoint < nPointCount; iPoint++ )
    1393                 :             {
    1394            6718 :                 memcpy( adfTuple, pabyData + nNextByte, 2*8 );
    1395            6718 :                 nNextByte += 2 * 8;
    1396                 : 
    1397            6718 :                 if (NEED_SWAP_SPATIALITE())
    1398                 :                 {
    1399               0 :                     CPL_SWAP64PTR( adfTuple );
    1400               0 :                     CPL_SWAP64PTR( adfTuple + 1 );
    1401                 :                 }
    1402                 : 
    1403            6718 :                 poLR->setPoint( iPoint, adfTuple[0], adfTuple[1] );
    1404                 :             }
    1405                 : 
    1406             472 :             poPoly->addRingDirectly( poLR );
    1407                 :         }
    1408                 : 
    1409             467 :         if( pnBytesConsumed )
    1410              30 :             *pnBytesConsumed = nNextByte;
    1411                 :     }
    1412                 : 
    1413                 : /* -------------------------------------------------------------------- */
    1414                 : /*      Polygon [XYZ]                                                   */
    1415                 : /* -------------------------------------------------------------------- */
    1416             385 :     else if( nGType == OGRSplitePolygonXYZ )
    1417                 :     {
    1418                 :         double adfTuple[3];
    1419                 :         GInt32 nPointCount;
    1420                 :         GInt32 nRingCount;
    1421                 :         int    iPoint, iRing;
    1422                 :         OGRLinearRing *poLR;
    1423                 :         OGRPolygon *poPoly;
    1424                 :         int    nNextByte;
    1425                 : 
    1426               7 :         if( nBytes < 8 )
    1427               0 :             return OGRERR_NOT_ENOUGH_DATA;
    1428                 : 
    1429               7 :         memcpy( &nRingCount, pabyData + 4, 4 );
    1430               7 :         if (NEED_SWAP_SPATIALITE())
    1431               0 :             CPL_SWAP32PTR( &nRingCount );
    1432                 : 
    1433               7 :         if (nRingCount < 0 || nRingCount > INT_MAX / 4)
    1434               0 :             return OGRERR_CORRUPT_DATA;
    1435                 : 
    1436                 :         // Each ring has a minimum of 4 bytes
    1437               7 :         if (nBytes - 8 < nRingCount * 4)
    1438               0 :             return OGRERR_NOT_ENOUGH_DATA;
    1439                 : 
    1440               7 :         nNextByte = 8;
    1441                 :         
    1442               7 :         poGeom = poPoly = new OGRPolygon();
    1443                 : 
    1444              14 :         for( iRing = 0; iRing < nRingCount; iRing++ )
    1445                 :         {
    1446               7 :             if( nBytes - nNextByte < 4 )
    1447               0 :                 return OGRERR_NOT_ENOUGH_DATA;
    1448                 : 
    1449               7 :             memcpy( &nPointCount, pabyData + nNextByte, 4 );
    1450               7 :             if (NEED_SWAP_SPATIALITE())
    1451               0 :                 CPL_SWAP32PTR( &nPointCount );
    1452                 : 
    1453               7 :             if( nPointCount < 0 || nPointCount > INT_MAX / (3 * 8))
    1454               0 :                 return OGRERR_CORRUPT_DATA;
    1455                 : 
    1456               7 :             nNextByte += 4;
    1457                 : 
    1458               7 :             if( nBytes - nNextByte < 3 * 8 * nPointCount )
    1459               0 :                 return OGRERR_NOT_ENOUGH_DATA;
    1460                 : 
    1461               7 :             poLR = new OGRLinearRing();
    1462               7 :             poLR->setNumPoints( nPointCount );
    1463                 :             
    1464              42 :             for( iPoint = 0; iPoint < nPointCount; iPoint++ )
    1465                 :             {
    1466              35 :                 memcpy( adfTuple, pabyData + nNextByte, 3*8 );
    1467              35 :                 nNextByte += 3 * 8;
    1468                 : 
    1469              35 :                 if (NEED_SWAP_SPATIALITE())
    1470                 :                 {
    1471               0 :                     CPL_SWAP64PTR( adfTuple );
    1472               0 :                     CPL_SWAP64PTR( adfTuple + 1 );
    1473               0 :                     CPL_SWAP64PTR( adfTuple + 2 );
    1474                 :                 }
    1475                 : 
    1476              35 :                 poLR->setPoint( iPoint, adfTuple[0], adfTuple[1], adfTuple[2] );
    1477                 :             }
    1478                 : 
    1479               7 :             poPoly->addRingDirectly( poLR );
    1480                 :         }
    1481                 : 
    1482               7 :         if( pnBytesConsumed )
    1483               5 :             *pnBytesConsumed = nNextByte;
    1484                 :     }
    1485                 : 
    1486                 : /* -------------------------------------------------------------------- */
    1487                 : /*      Polygon [XYM]                                                   */
    1488                 : /* -------------------------------------------------------------------- */
    1489             378 :     else if( nGType == OGRSplitePolygonXYM )
    1490                 :     {
    1491                 :         double adfTuple[3];
    1492                 :         GInt32 nPointCount;
    1493                 :         GInt32 nRingCount;
    1494                 :         int    iPoint, iRing;
    1495                 :         OGRLinearRing *poLR;
    1496                 :         OGRPolygon *poPoly;
    1497                 :         int    nNextByte;
    1498                 : 
    1499               0 :         if( nBytes < 8 )
    1500               0 :             return OGRERR_NOT_ENOUGH_DATA;
    1501                 : 
    1502               0 :         memcpy( &nRingCount, pabyData + 4, 4 );
    1503               0 :         if (NEED_SWAP_SPATIALITE())
    1504               0 :             CPL_SWAP32PTR( &nRingCount );
    1505                 : 
    1506               0 :         if (nRingCount < 0 || nRingCount > INT_MAX / 4)
    1507               0 :             return OGRERR_CORRUPT_DATA;
    1508                 : 
    1509                 :         // Each ring has a minimum of 4 bytes 
    1510               0 :         if (nBytes - 8 < nRingCount * 4)
    1511               0 :             return OGRERR_NOT_ENOUGH_DATA;
    1512                 : 
    1513               0 :         nNextByte = 8;
    1514                 :         
    1515               0 :         poGeom = poPoly = new OGRPolygon();
    1516                 : 
    1517               0 :         for( iRing = 0; iRing < nRingCount; iRing++ )
    1518                 :         {
    1519               0 :             if( nBytes - nNextByte < 4 )
    1520               0 :                 return OGRERR_NOT_ENOUGH_DATA;
    1521                 : 
    1522               0 :             memcpy( &nPointCount, pabyData + nNextByte, 4 );
    1523               0 :             if (NEED_SWAP_SPATIALITE())
    1524               0 :                 CPL_SWAP32PTR( &nPointCount );
    1525                 : 
    1526               0 :             if( nPointCount < 0 || nPointCount > INT_MAX / (3 * 8))
    1527               0 :                 return OGRERR_CORRUPT_DATA;
    1528                 : 
    1529               0 :             nNextByte += 4;
    1530                 : 
    1531               0 :             if( nBytes - nNextByte < 3 * 8 * nPointCount )
    1532               0 :                 return OGRERR_NOT_ENOUGH_DATA;
    1533                 : 
    1534               0 :             poLR = new OGRLinearRing();
    1535               0 :             poLR->setNumPoints( nPointCount );
    1536                 :             
    1537               0 :             for( iPoint = 0; iPoint < nPointCount; iPoint++ )
    1538                 :             {
    1539               0 :                 memcpy( adfTuple, pabyData + nNextByte, 3*8 );
    1540               0 :                 nNextByte += 3 * 8;
    1541                 : 
    1542               0 :                 if (NEED_SWAP_SPATIALITE())
    1543                 :                 {
    1544               0 :                     CPL_SWAP64PTR( adfTuple );
    1545               0 :                     CPL_SWAP64PTR( adfTuple + 1 );
    1546               0 :                     CPL_SWAP64PTR( adfTuple + 2 );
    1547                 :                 }
    1548                 : 
    1549               0 :                 poLR->setPoint( iPoint, adfTuple[0], adfTuple[1] );
    1550                 :             }
    1551                 : 
    1552               0 :             poPoly->addRingDirectly( poLR );
    1553                 :         }
    1554                 : 
    1555               0 :         if( pnBytesConsumed )
    1556               0 :             *pnBytesConsumed = nNextByte;
    1557                 :     }
    1558                 : 
    1559                 : /* -------------------------------------------------------------------- */
    1560                 : /*      Polygon [XYZM]                                                  */
    1561                 : /* -------------------------------------------------------------------- */
    1562             378 :     else if( nGType == OGRSplitePolygonXYZM )
    1563                 :     {
    1564                 :         double adfTuple[4];
    1565                 :         GInt32 nPointCount;
    1566                 :         GInt32 nRingCount;
    1567                 :         int    iPoint, iRing;
    1568                 :         OGRLinearRing *poLR;
    1569                 :         OGRPolygon *poPoly;
    1570                 :         int    nNextByte;
    1571                 : 
    1572               0 :         if( nBytes < 8 )
    1573               0 :             return OGRERR_NOT_ENOUGH_DATA;
    1574                 : 
    1575               0 :         memcpy( &nRingCount, pabyData + 4, 4 );
    1576               0 :         if (NEED_SWAP_SPATIALITE())
    1577               0 :             CPL_SWAP32PTR( &nRingCount );
    1578                 : 
    1579               0 :         if (nRingCount < 0 || nRingCount > INT_MAX / 4)
    1580               0 :             return OGRERR_CORRUPT_DATA;
    1581                 : 
    1582                 :         // Each ring has a minimum of 4 bytes 
    1583               0 :         if (nBytes - 8 < nRingCount * 4)
    1584               0 :             return OGRERR_NOT_ENOUGH_DATA;
    1585                 : 
    1586               0 :         nNextByte = 8;
    1587                 :         
    1588               0 :         poGeom = poPoly = new OGRPolygon();
    1589                 : 
    1590               0 :         for( iRing = 0; iRing < nRingCount; iRing++ )
    1591                 :         {
    1592               0 :             if( nBytes - nNextByte < 4 )
    1593               0 :                 return OGRERR_NOT_ENOUGH_DATA;
    1594                 : 
    1595               0 :             memcpy( &nPointCount, pabyData + nNextByte, 4 );
    1596               0 :             if (NEED_SWAP_SPATIALITE())
    1597               0 :                 CPL_SWAP32PTR( &nPointCount );
    1598                 : 
    1599               0 :             if( nPointCount < 0 || nPointCount > INT_MAX / (4 * 8))
    1600               0 :                 return OGRERR_CORRUPT_DATA;
    1601                 : 
    1602               0 :             nNextByte += 4;
    1603                 : 
    1604               0 :             if( nBytes - nNextByte < 4 * 8 * nPointCount )
    1605               0 :                 return OGRERR_NOT_ENOUGH_DATA;
    1606                 : 
    1607               0 :             poLR = new OGRLinearRing();
    1608               0 :             poLR->setNumPoints( nPointCount );
    1609                 :             
    1610               0 :             for( iPoint = 0; iPoint < nPointCount; iPoint++ )
    1611                 :             {
    1612               0 :                 memcpy( adfTuple, pabyData + nNextByte, 4*8 );
    1613               0 :                 nNextByte += 4 * 8;
    1614                 : 
    1615               0 :                 if (NEED_SWAP_SPATIALITE())
    1616                 :                 {
    1617               0 :                     CPL_SWAP64PTR( adfTuple );
    1618               0 :                     CPL_SWAP64PTR( adfTuple + 1 );
    1619               0 :                     CPL_SWAP64PTR( adfTuple + 2 );
    1620               0 :                     CPL_SWAP64PTR( adfTuple + 3 );
    1621                 :                 }
    1622                 : 
    1623               0 :                 poLR->setPoint( iPoint, adfTuple[0], adfTuple[1], adfTuple[2] );
    1624                 :             }
    1625                 : 
    1626               0 :             poPoly->addRingDirectly( poLR );
    1627                 :         }
    1628                 : 
    1629               0 :         if( pnBytesConsumed )
    1630               0 :             *pnBytesConsumed = nNextByte;
    1631                 :     }
    1632                 : 
    1633                 : /* -------------------------------------------------------------------- */
    1634                 : /*      Polygon [XY] Compressed                                         */
    1635                 : /* -------------------------------------------------------------------- */
    1636             378 :     else if( nGType == OGRSpliteComprPolygonXY  )
    1637                 :     {
    1638                 :         double adfTuple[2];
    1639                 :         double adfTupleBase[2];
    1640                 :         float asfTuple[2];
    1641                 :         GInt32 nPointCount;
    1642                 :         GInt32 nRingCount;
    1643                 :         int    iPoint, iRing;
    1644                 :         OGRLinearRing *poLR;
    1645                 :         OGRPolygon *poPoly;
    1646                 :         int    nNextByte;
    1647                 : 
    1648             306 :         if( nBytes < 8 )
    1649               0 :             return OGRERR_NOT_ENOUGH_DATA;
    1650                 : 
    1651             306 :         memcpy( &nRingCount, pabyData + 4, 4 );
    1652             306 :         if (NEED_SWAP_SPATIALITE())
    1653               0 :             CPL_SWAP32PTR( &nRingCount );
    1654                 : 
    1655             306 :         if (nRingCount < 0 || nRingCount > INT_MAX / 4)
    1656               0 :             return OGRERR_CORRUPT_DATA;
    1657                 : 
    1658                 :         // Each ring has a minimum of 4 bytes
    1659             306 :         if (nBytes - 8 < nRingCount * 4)
    1660               0 :             return OGRERR_NOT_ENOUGH_DATA;
    1661                 : 
    1662             306 :         nNextByte = 8;
    1663                 :         
    1664             306 :         poGeom = poPoly = new OGRPolygon();
    1665                 : 
    1666             613 :         for( iRing = 0; iRing < nRingCount; iRing++ )
    1667                 :         {
    1668             307 :             if( nBytes - nNextByte < 4 )
    1669               0 :                 return OGRERR_NOT_ENOUGH_DATA;
    1670                 : 
    1671             307 :             memcpy( &nPointCount, pabyData + nNextByte, 4 );
    1672             307 :             if (NEED_SWAP_SPATIALITE())
    1673               0 :                 CPL_SWAP32PTR( &nPointCount );
    1674                 : 
    1675             307 :             if( nPointCount < 0 || nPointCount - 2 > (INT_MAX - 16 * 2) / 8)
    1676               0 :                 return OGRERR_CORRUPT_DATA;
    1677                 : 
    1678             307 :             compressedSize = 16 * 2;                  // first and last Points
    1679             307 :             compressedSize += 8 * (nPointCount - 2);  // intermediate Points
    1680                 : 
    1681             307 :             nNextByte += 4;
    1682             307 :             adfTupleBase[0] = 0.0;
    1683             307 :             adfTupleBase[1] = 0.0;
    1684                 : 
    1685             307 :             if (nBytes - nNextByte < compressedSize )
    1686               0 :                 return OGRERR_NOT_ENOUGH_DATA;
    1687                 : 
    1688             307 :             poLR = new OGRLinearRing();
    1689             307 :             poLR->setNumPoints( nPointCount );
    1690                 :             
    1691            9236 :             for( iPoint = 0; iPoint < nPointCount; iPoint++ )
    1692                 :             {
    1693            9543 :                 if ( iPoint == 0 || iPoint == (nPointCount - 1 ) )
    1694                 :                 {
    1695                 :                     // first and last Points are uncompressed 
    1696             614 :                     memcpy( adfTuple, pabyData + nNextByte, 2*8 );
    1697             614 :                     nNextByte += 2 * 8;
    1698                 : 
    1699             614 :                     if (NEED_SWAP_SPATIALITE())
    1700                 :                     {
    1701               0 :                         CPL_SWAP64PTR( adfTuple );
    1702               0 :                         CPL_SWAP64PTR( adfTuple + 1 );
    1703                 :                     }
    1704                 :                 }
    1705                 :                 else
    1706                 :                 {
    1707                 :                     // any other intermediate Point is compressed
    1708            8315 :                     memcpy( asfTuple, pabyData + nNextByte, 2*4 );
    1709            8315 :                     nNextByte += 2 * 4;
    1710                 : 
    1711            8315 :                     if (NEED_SWAP_SPATIALITE())
    1712                 :                     {
    1713               0 :                         CPL_SWAP32PTR( asfTuple );
    1714               0 :                         CPL_SWAP32PTR( asfTuple + 1 );
    1715                 :                     }
    1716            8315 :                     adfTuple[0] = asfTuple[0] + adfTupleBase[0];
    1717            8315 :                     adfTuple[1] = asfTuple[1] + adfTupleBase[1];
    1718                 :                 }
    1719                 : 
    1720            8929 :                 poLR->setPoint( iPoint, adfTuple[0], adfTuple[1] );
    1721            8929 :                 adfTupleBase[0] = adfTuple[0];
    1722            8929 :                 adfTupleBase[1] = adfTuple[1];
    1723                 :             }
    1724                 : 
    1725             307 :             poPoly->addRingDirectly( poLR );
    1726                 :         }
    1727                 : 
    1728             306 :         if( pnBytesConsumed )
    1729               5 :             *pnBytesConsumed = nNextByte;
    1730                 :     }
    1731                 : 
    1732                 : /* -------------------------------------------------------------------- */
    1733                 : /*      Polygon [XYZ] Compressed                                        */
    1734                 : /* -------------------------------------------------------------------- */
    1735              72 :     else if( nGType == OGRSpliteComprPolygonXYZ )
    1736                 :     {
    1737                 :         double adfTuple[3];
    1738                 :         double adfTupleBase[3];
    1739                 :         float asfTuple[3];
    1740                 :         GInt32 nPointCount;
    1741                 :         GInt32 nRingCount;
    1742                 :         int    iPoint, iRing;
    1743                 :         OGRLinearRing *poLR;
    1744                 :         OGRPolygon *poPoly;
    1745                 :         int    nNextByte;
    1746                 : 
    1747               5 :         if( nBytes < 8 )
    1748               0 :             return OGRERR_NOT_ENOUGH_DATA;
    1749                 : 
    1750               5 :         memcpy( &nRingCount, pabyData + 4, 4 );
    1751               5 :         if (NEED_SWAP_SPATIALITE())
    1752               0 :             CPL_SWAP32PTR( &nRingCount );
    1753                 : 
    1754               5 :         if (nRingCount < 0 || nRingCount > INT_MAX / 4)
    1755               0 :             return OGRERR_CORRUPT_DATA;
    1756                 : 
    1757                 :         // Each ring has a minimum of 4 bytes
    1758               5 :         if (nBytes - 8 < nRingCount * 4)
    1759               0 :             return OGRERR_NOT_ENOUGH_DATA;
    1760                 : 
    1761               5 :         nNextByte = 8;
    1762                 :         
    1763               5 :         poGeom = poPoly = new OGRPolygon();
    1764                 : 
    1765              10 :         for( iRing = 0; iRing < nRingCount; iRing++ )
    1766                 :         {
    1767               5 :             if( nBytes - nNextByte < 4 )
    1768               0 :                 return OGRERR_NOT_ENOUGH_DATA;
    1769                 : 
    1770               5 :             memcpy( &nPointCount, pabyData + nNextByte, 4 );
    1771               5 :             if (NEED_SWAP_SPATIALITE())
    1772               0 :                 CPL_SWAP32PTR( &nPointCount );
    1773                 : 
    1774               5 :             if( nPointCount < 0 || nPointCount - 2 > (INT_MAX - 24 * 2) / 12)
    1775               0 :                 return OGRERR_CORRUPT_DATA;
    1776                 : 
    1777               5 :             compressedSize = 24 * 2;                    // first and last Points
    1778               5 :             compressedSize += 12 * (nPointCount - 2);  // intermediate Points
    1779                 : 
    1780               5 :             nNextByte += 4;
    1781               5 :             adfTupleBase[0] = 0.0;
    1782               5 :             adfTupleBase[1] = 0.0;
    1783               5 :             adfTupleBase[2] = 0.0;
    1784                 : 
    1785               5 :             if (nBytes - nNextByte < compressedSize )
    1786               0 :                 return OGRERR_NOT_ENOUGH_DATA;
    1787                 : 
    1788               5 :             poLR = new OGRLinearRing();
    1789               5 :             poLR->setNumPoints( nPointCount );
    1790                 :             
    1791              30 :             for( iPoint = 0; iPoint < nPointCount; iPoint++ )
    1792                 :             {
    1793              35 :                 if ( iPoint == 0 || iPoint == (nPointCount - 1 ) )
    1794                 :                 {
    1795                 :                     // first and last Points are uncompressed 
    1796              10 :                     memcpy( adfTuple, pabyData + nNextByte, 3*8 );
    1797              10 :                     nNextByte += 3 * 8;
    1798                 : 
    1799              10 :                     if (NEED_SWAP_SPATIALITE())
    1800                 :                     {
    1801               0 :                         CPL_SWAP64PTR( adfTuple );
    1802               0 :                         CPL_SWAP64PTR( adfTuple + 1 );
    1803               0 :                         CPL_SWAP64PTR( adfTuple + 2 );
    1804                 :                     }
    1805                 :                 }
    1806                 :                 else
    1807                 :                 {
    1808                 :                     // any other intermediate Point is compressed
    1809              15 :                     memcpy( asfTuple, pabyData + nNextByte, 3*4 );
    1810              15 :                     nNextByte += 3 * 4;
    1811                 : 
    1812              15 :                     if (NEED_SWAP_SPATIALITE())
    1813                 :                     {
    1814               0 :                         CPL_SWAP32PTR( asfTuple );
    1815               0 :                         CPL_SWAP32PTR( asfTuple + 1 );
    1816               0 :                         CPL_SWAP32PTR( asfTuple + 2 );
    1817                 :                     }
    1818              15 :                     adfTuple[0] = asfTuple[0] + adfTupleBase[0];
    1819              15 :                     adfTuple[1] = asfTuple[1] + adfTupleBase[1];
    1820              15 :                     adfTuple[2] = asfTuple[2] + adfTupleBase[2];
    1821                 :                 }
    1822                 : 
    1823              25 :                 poLR->setPoint( iPoint, adfTuple[0], adfTuple[1], adfTuple[2] );
    1824              25 :                 adfTupleBase[0] = adfTuple[0];
    1825              25 :                 adfTupleBase[1] = adfTuple[1];
    1826              25 :                 adfTupleBase[2] = adfTuple[2];
    1827                 :             }
    1828                 : 
    1829               5 :             poPoly->addRingDirectly( poLR );
    1830                 :         }
    1831                 : 
    1832               5 :         if( pnBytesConsumed )
    1833               3 :             *pnBytesConsumed = nNextByte;
    1834                 :     }
    1835                 : 
    1836                 : /* -------------------------------------------------------------------- */
    1837                 : /*      Polygon [XYM] Compressed                                        */
    1838                 : /* -------------------------------------------------------------------- */
    1839              67 :     else if( nGType == OGRSpliteComprPolygonXYM )
    1840                 :     {
    1841                 :         double adfTuple[2];
    1842                 :         double adfTupleBase[3];
    1843                 :         float asfTuple[2];
    1844                 :         GInt32 nPointCount;
    1845                 :         GInt32 nRingCount;
    1846                 :         int    iPoint, iRing;
    1847                 :         OGRLinearRing *poLR;
    1848                 :         OGRPolygon *poPoly;
    1849                 :         int    nNextByte;
    1850                 : 
    1851               0 :         if( nBytes < 8 )
    1852               0 :             return OGRERR_NOT_ENOUGH_DATA;
    1853                 : 
    1854               0 :         memcpy( &nRingCount, pabyData + 4, 4 );
    1855               0 :         if (NEED_SWAP_SPATIALITE())
    1856               0 :             CPL_SWAP32PTR( &nRingCount );
    1857                 : 
    1858               0 :         if (nRingCount < 0 || nRingCount > INT_MAX / 4)
    1859               0 :             return OGRERR_CORRUPT_DATA;
    1860                 : 
    1861                 :         // Each ring has a minimum of 4 bytes
    1862               0 :         if (nBytes - 8 < nRingCount * 4)
    1863               0 :             return OGRERR_NOT_ENOUGH_DATA;
    1864                 : 
    1865               0 :         nNextByte = 8;
    1866                 :         
    1867               0 :         poGeom = poPoly = new OGRPolygon();
    1868                 : 
    1869               0 :         for( iRing = 0; iRing < nRingCount; iRing++ )
    1870                 :         {
    1871               0 :             if( nBytes - nNextByte < 4 )
    1872               0 :                 return OGRERR_NOT_ENOUGH_DATA;
    1873                 : 
    1874               0 :             memcpy( &nPointCount, pabyData + nNextByte, 4 );
    1875               0 :             if (NEED_SWAP_SPATIALITE())
    1876               0 :                 CPL_SWAP32PTR( &nPointCount );
    1877                 : 
    1878                 : 
    1879               0 :             if( nPointCount < 0 || nPointCount - 2 > (INT_MAX - 24 * 2) / 16)
    1880               0 :                 return OGRERR_CORRUPT_DATA;
    1881                 : 
    1882               0 :             compressedSize = 24 * 2;                   // first and last Points
    1883               0 :             compressedSize += 16 * (nPointCount - 2);  // intermediate Points
    1884                 : 
    1885               0 :             nNextByte += 4;
    1886               0 :       adfTupleBase[0] = 0.0;
    1887               0 :       adfTupleBase[1] = 0.0;
    1888                 : 
    1889               0 :             if (nBytes - nNextByte < compressedSize )
    1890               0 :                 return OGRERR_NOT_ENOUGH_DATA;
    1891                 : 
    1892               0 :             poLR = new OGRLinearRing();
    1893               0 :             poLR->setNumPoints( nPointCount );
    1894                 :             
    1895               0 :             for( iPoint = 0; iPoint < nPointCount; iPoint++ )
    1896                 :             {
    1897               0 :                 if ( iPoint == 0 || iPoint == (nPointCount - 1 ) )
    1898                 :                 {
    1899                 :                     // first and last Points are uncompressed 
    1900               0 :                     memcpy( adfTuple, pabyData + nNextByte, 2*8 );
    1901               0 :                     nNextByte += 2 * 8;
    1902                 : 
    1903               0 :                     if (NEED_SWAP_SPATIALITE())
    1904                 :                     {
    1905               0 :                         CPL_SWAP64PTR( adfTuple );
    1906               0 :                         CPL_SWAP64PTR( adfTuple + 1 );
    1907                 :                     }
    1908                 :                 }
    1909                 :                 else
    1910                 :                 {
    1911                 :                     // any other intermediate Point is compressed
    1912               0 :                     memcpy( asfTuple, pabyData + nNextByte, 2*4 );
    1913               0 :                     nNextByte += 2 * 4 + 8;
    1914                 : 
    1915               0 :                     if (NEED_SWAP_SPATIALITE())
    1916                 :                     {
    1917               0 :                         CPL_SWAP32PTR( asfTuple );
    1918               0 :                         CPL_SWAP32PTR( asfTuple + 1 );
    1919                 :                     }
    1920               0 :                     adfTuple[0] = asfTuple[0] + adfTupleBase[0];
    1921               0 :                     adfTuple[1] = asfTuple[1] + adfTupleBase[1];
    1922                 :                 }
    1923                 : 
    1924               0 :                 poLR->setPoint( iPoint, adfTuple[0], adfTuple[1] );
    1925               0 :                 adfTupleBase[0] = adfTuple[0];
    1926               0 :                 adfTupleBase[1] = adfTuple[1];
    1927                 :             }
    1928                 : 
    1929               0 :             poPoly->addRingDirectly( poLR );
    1930                 :         }
    1931                 : 
    1932               0 :         if( pnBytesConsumed )
    1933               0 :             *pnBytesConsumed = nNextByte;
    1934                 :     }
    1935                 : 
    1936                 : /* -------------------------------------------------------------------- */
    1937                 : /*      Polygon [XYZM] Compressed                                       */
    1938                 : /* -------------------------------------------------------------------- */
    1939              67 :     else if( nGType == OGRSpliteComprPolygonXYZM )
    1940                 :     {
    1941                 :         double adfTuple[3];
    1942                 :         double adfTupleBase[3];
    1943                 :         float asfTuple[3];
    1944                 :         GInt32 nPointCount;
    1945                 :         GInt32 nRingCount;
    1946                 :         int    iPoint, iRing;
    1947                 :         OGRLinearRing *poLR;
    1948                 :         OGRPolygon *poPoly;
    1949                 :         int    nNextByte;
    1950                 : 
    1951               0 :         if( nBytes < 8 )
    1952               0 :             return OGRERR_NOT_ENOUGH_DATA;
    1953                 : 
    1954               0 :         memcpy( &nRingCount, pabyData + 4, 4 );
    1955               0 :         if (NEED_SWAP_SPATIALITE())
    1956               0 :             CPL_SWAP32PTR( &nRingCount );
    1957                 : 
    1958               0 :         if (nRingCount < 0 || nRingCount > INT_MAX / 4)
    1959               0 :             return OGRERR_CORRUPT_DATA;
    1960                 : 
    1961                 :         // Each ring has a minimum of 4 bytes 
    1962               0 :         if (nBytes - 8 < nRingCount * 4)
    1963               0 :             return OGRERR_NOT_ENOUGH_DATA;
    1964                 : 
    1965               0 :         nNextByte = 8;
    1966                 :         
    1967               0 :         poGeom = poPoly = new OGRPolygon();
    1968                 : 
    1969               0 :         for( iRing = 0; iRing < nRingCount; iRing++ )
    1970                 :         {
    1971               0 :             if( nBytes - nNextByte < 4 )
    1972               0 :                 return OGRERR_NOT_ENOUGH_DATA;
    1973                 : 
    1974               0 :             memcpy( &nPointCount, pabyData + nNextByte, 4 );
    1975               0 :             if (NEED_SWAP_SPATIALITE())
    1976               0 :                 CPL_SWAP32PTR( &nPointCount );
    1977                 : 
    1978               0 :             if( nPointCount < 0 || nPointCount - 2 > (INT_MAX - 32 * 2) / 20)
    1979               0 :                 return OGRERR_CORRUPT_DATA;
    1980                 : 
    1981               0 :             compressedSize = 32 * 2;                   // first and last Points
    1982                 :             /* Note 20 is not an error : x,y,z are float and the m is a double */
    1983               0 :             compressedSize += 20 * (nPointCount - 2);  // intermediate Points
    1984                 : 
    1985               0 :             nNextByte += 4;
    1986               0 :             adfTupleBase[0] = 0.0;
    1987               0 :             adfTupleBase[1] = 0.0;
    1988               0 :             adfTupleBase[2] = 0.0;
    1989                 : 
    1990               0 :             if (nBytes - nNextByte < compressedSize )
    1991               0 :                 return OGRERR_NOT_ENOUGH_DATA;
    1992                 : 
    1993               0 :             poLR = new OGRLinearRing();
    1994               0 :             poLR->setNumPoints( nPointCount );
    1995                 :             
    1996               0 :             for( iPoint = 0; iPoint < nPointCount; iPoint++ )
    1997                 :             {
    1998               0 :                 if ( iPoint == 0 || iPoint == (nPointCount - 1 ) )
    1999                 :                 {
    2000                 :                     // first and last Points are uncompressed
    2001               0 :                     memcpy( adfTuple, pabyData + nNextByte, 3*8 );
    2002               0 :                     nNextByte += 4 * 8;
    2003                 : 
    2004               0 :                     if (NEED_SWAP_SPATIALITE())
    2005                 :                     {
    2006               0 :                         CPL_SWAP64PTR( adfTuple );
    2007               0 :                         CPL_SWAP64PTR( adfTuple + 1 );
    2008               0 :                         CPL_SWAP64PTR( adfTuple + 2 );
    2009                 :                     }
    2010                 :                 }
    2011                 :                 else
    2012                 :                 {
    2013                 :                     // any other intermediate Point is compressed 
    2014               0 :                     memcpy( asfTuple, pabyData + nNextByte, 3*4 );
    2015               0 :                     nNextByte += 3 * 4 + 8;
    2016                 : 
    2017               0 :                     if (NEED_SWAP_SPATIALITE())
    2018                 :                     {
    2019               0 :                         CPL_SWAP32PTR( asfTuple );
    2020               0 :                         CPL_SWAP32PTR( asfTuple + 1 );
    2021               0 :                         CPL_SWAP32PTR( asfTuple + 2 );
    2022                 :                     }
    2023               0 :                     adfTuple[0] = asfTuple[0] + adfTupleBase[0];
    2024               0 :                     adfTuple[1] = asfTuple[1] + adfTupleBase[1];
    2025               0 :                     adfTuple[2] = asfTuple[2] + adfTupleBase[2];
    2026                 :                 }
    2027                 : 
    2028               0 :                 poLR->setPoint( iPoint, adfTuple[0], adfTuple[1], adfTuple[2] );
    2029               0 :                 adfTupleBase[0] = adfTuple[0];
    2030               0 :                 adfTupleBase[1] = adfTuple[1];
    2031               0 :                 adfTupleBase[2] = adfTuple[2];
    2032                 :             }
    2033                 : 
    2034               0 :             poPoly->addRingDirectly( poLR );
    2035                 :         }
    2036                 : 
    2037               0 :         if( pnBytesConsumed )
    2038               0 :             *pnBytesConsumed = nNextByte;
    2039                 :     }
    2040                 : 
    2041                 : /* -------------------------------------------------------------------- */
    2042                 : /*      GeometryCollections of various kinds.                           */
    2043                 : /* -------------------------------------------------------------------- */
    2044             134 :     else if( ( nGType >= OGRSpliteMultiPointXY &&
    2045                 :                nGType <= OGRSpliteGeometryCollectionXY ) ||       // XY types
    2046                 :              ( nGType >= OGRSpliteMultiPointXYZ &&
    2047                 :                nGType <= OGRSpliteGeometryCollectionXYZ ) ||      // XYZ types
    2048                 :              ( nGType >= OGRSpliteMultiPointXYM &&
    2049                 :                nGType <= OGRSpliteGeometryCollectionXYM ) ||      // XYM types 
    2050                 :              ( nGType >= OGRSpliteMultiPointXYZM &&
    2051                 :                nGType <= OGRSpliteGeometryCollectionXYZM ) ||     // XYZM types
    2052                 :              ( nGType >= OGRSpliteComprMultiLineStringXY &&
    2053                 :                nGType <= OGRSpliteComprGeometryCollectionXY ) ||  // XY compressed
    2054                 :              ( nGType >= OGRSpliteComprMultiLineStringXYZ &&
    2055                 :                nGType <= OGRSpliteComprGeometryCollectionXYZ ) || // XYZ compressed
    2056                 :              ( nGType >= OGRSpliteComprMultiLineStringXYM &&
    2057                 :                nGType <= OGRSpliteComprGeometryCollectionXYM ) || // XYM compressed
    2058                 :              ( nGType >= OGRSpliteComprMultiLineStringXYZM &&
    2059                 :                nGType <= OGRSpliteComprGeometryCollectionXYZM ) ) // XYZM compressed
    2060                 :     {
    2061              67 :         OGRGeometryCollection *poGC = NULL;
    2062              67 :         GInt32 nGeomCount = 0;
    2063              67 :         int iGeom = 0;
    2064              67 :         int nBytesUsed = 0;
    2065                 : 
    2066              67 :         switch ( nGType )
    2067                 :         {
    2068                 :             case OGRSpliteMultiPointXY:
    2069                 :             case OGRSpliteMultiPointXYZ: 
    2070                 :             case OGRSpliteMultiPointXYM: 
    2071                 :             case OGRSpliteMultiPointXYZM:
    2072              10 :                 poGC = new OGRMultiPoint();
    2073              10 :                 break;
    2074                 :             case OGRSpliteMultiLineStringXY: 
    2075                 :             case OGRSpliteMultiLineStringXYZ: 
    2076                 :             case OGRSpliteMultiLineStringXYM: 
    2077                 :             case OGRSpliteMultiLineStringXYZM:
    2078                 :             case OGRSpliteComprMultiLineStringXY: 
    2079                 :             case OGRSpliteComprMultiLineStringXYZ: 
    2080                 :             case OGRSpliteComprMultiLineStringXYM: 
    2081                 :             case OGRSpliteComprMultiLineStringXYZM:
    2082              10 :                 poGC = new OGRMultiLineString();
    2083              10 :                 break;
    2084                 :             case OGRSpliteMultiPolygonXY: 
    2085                 :             case OGRSpliteMultiPolygonXYZ: 
    2086                 :             case OGRSpliteMultiPolygonXYM: 
    2087                 :             case OGRSpliteMultiPolygonXYZM:
    2088                 :             case OGRSpliteComprMultiPolygonXY: 
    2089                 :             case OGRSpliteComprMultiPolygonXYZ: 
    2090                 :             case OGRSpliteComprMultiPolygonXYM: 
    2091                 :             case OGRSpliteComprMultiPolygonXYZM:
    2092              23 :                 poGC = new OGRMultiPolygon();
    2093              23 :                 break;
    2094                 :             case OGRSpliteGeometryCollectionXY: 
    2095                 :             case OGRSpliteGeometryCollectionXYZ: 
    2096                 :             case OGRSpliteGeometryCollectionXYM: 
    2097                 :             case OGRSpliteGeometryCollectionXYZM:
    2098                 :             case OGRSpliteComprGeometryCollectionXY: 
    2099                 :             case OGRSpliteComprGeometryCollectionXYZ: 
    2100                 :             case OGRSpliteComprGeometryCollectionXYM: 
    2101                 :             case OGRSpliteComprGeometryCollectionXYZM:
    2102              24 :                 poGC = new OGRGeometryCollection();
    2103                 :                 break;
    2104                 :         }
    2105                 : 
    2106              67 :         assert(NULL != poGC);
    2107                 : 
    2108              67 :         if( nBytes < 8 )
    2109               0 :             return OGRERR_NOT_ENOUGH_DATA;
    2110                 : 
    2111              67 :         memcpy( &nGeomCount, pabyData + 4, 4 );
    2112              67 :         if (NEED_SWAP_SPATIALITE())
    2113               0 :             CPL_SWAP32PTR( &nGeomCount );
    2114                 : 
    2115              67 :         if (nGeomCount < 0 || nGeomCount > INT_MAX / 9)
    2116               0 :             return OGRERR_CORRUPT_DATA;
    2117                 : 
    2118                 :         // Each sub geometry takes at least 9 bytes
    2119              67 :         if (nBytes - 8 < nGeomCount * 9)
    2120               0 :             return OGRERR_NOT_ENOUGH_DATA;
    2121                 : 
    2122              67 :         nBytesUsed = 8;
    2123                 : 
    2124             152 :         for( iGeom = 0; iGeom < nGeomCount; iGeom++ )
    2125                 :         {
    2126                 :             int nThisGeomSize;
    2127              85 :             OGRGeometry *poThisGeom = NULL;
    2128                 : 
    2129              85 :             if (nBytes - nBytesUsed < 5)
    2130               0 :                 return OGRERR_NOT_ENOUGH_DATA;
    2131                 : 
    2132              85 :             if (pabyData[nBytesUsed] != 0x69)
    2133               0 :                 return OGRERR_CORRUPT_DATA;
    2134                 : 
    2135              85 :             nBytesUsed ++;
    2136                 : 
    2137                 :             eErr = createFromSpatialiteInternal( pabyData + nBytesUsed,
    2138                 :                                                  &poThisGeom, nBytes - nBytesUsed,
    2139              85 :                                                  eByteOrder, &nThisGeomSize, nRecLevel + 1);
    2140              85 :             if( eErr != OGRERR_NONE )
    2141                 :             {
    2142               0 :                 delete poGC;
    2143               0 :                 return eErr;
    2144                 :             }
    2145                 : 
    2146              85 :             nBytesUsed += nThisGeomSize;
    2147              85 :             eErr = poGC->addGeometryDirectly( poThisGeom );
    2148              85 :             if( eErr != OGRERR_NONE )
    2149                 :             {
    2150               0 :                 delete poGC;
    2151               0 :                 return eErr;
    2152                 :             }
    2153                 :         }
    2154                 : 
    2155              67 :         poGeom = poGC;
    2156              67 :         if( pnBytesConsumed )
    2157               0 :             *pnBytesConsumed = nBytesUsed;
    2158                 :     }
    2159                 : 
    2160                 : /* -------------------------------------------------------------------- */
    2161                 : /*      Currently unsupported geometry.                                 */
    2162                 : /* -------------------------------------------------------------------- */
    2163                 :     else
    2164                 :     {
    2165               0 :         return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
    2166                 :     }
    2167                 : 
    2168                 : /* -------------------------------------------------------------------- */
    2169                 : /*      Assign spatial reference system.                                */
    2170                 : /* -------------------------------------------------------------------- */
    2171            1380 :     if( eErr == OGRERR_NONE )
    2172                 :     {
    2173            1380 :         *ppoReturn = poGeom;
    2174                 :     }
    2175                 :     else
    2176                 :     {
    2177               0 :         delete poGeom;
    2178                 :     }
    2179                 : 
    2180            1380 :     return eErr;
    2181                 : }
    2182                 : 
    2183                 : /************************************************************************/
    2184                 : /*                      ImportSpatiaLiteGeometry()                      */
    2185                 : /************************************************************************/
    2186                 : 
    2187            1496 : OGRErr OGRSQLiteLayer::ImportSpatiaLiteGeometry( const GByte *pabyData,
    2188                 :                                                  int nBytes,
    2189                 :                                                  OGRGeometry **ppoGeometry )
    2190                 : 
    2191                 : {
    2192            1496 :     return ImportSpatiaLiteGeometry(pabyData, nBytes, ppoGeometry, NULL);
    2193                 : }
    2194                 : 
    2195                 : /************************************************************************/
    2196                 : /*                      ImportSpatiaLiteGeometry()                      */
    2197                 : /************************************************************************/
    2198                 : 
    2199            1512 : OGRErr OGRSQLiteLayer::ImportSpatiaLiteGeometry( const GByte *pabyData,
    2200                 :                                                  int nBytes,
    2201                 :                                                  OGRGeometry **ppoGeometry,
    2202                 :                                                  int* pnSRID )
    2203                 : 
    2204                 : {
    2205                 :     OGRwkbByteOrder eByteOrder;
    2206                 : 
    2207            1512 :     *ppoGeometry = NULL;
    2208                 : 
    2209            5459 :     if( nBytes < 44
    2210            1357 :         || pabyData[0] != 0
    2211            1295 :         || pabyData[38] != 0x7C
    2212            1295 :         || pabyData[nBytes-1] != 0xFE )
    2213             217 :         return OGRERR_CORRUPT_DATA;
    2214                 : 
    2215            1295 :     eByteOrder = (OGRwkbByteOrder) pabyData[1];
    2216                 : 
    2217                 : /* -------------------------------------------------------------------- */
    2218                 : /*      Decode the geometry type.                                       */
    2219                 : /* -------------------------------------------------------------------- */
    2220            1295 :     if( pnSRID != NULL )
    2221                 :     {
    2222                 :         int nSRID;
    2223               0 :         memcpy( &nSRID, pabyData + 2, 4 );
    2224               0 :         if (NEED_SWAP_SPATIALITE())
    2225               0 :             CPL_SWAP32PTR( &nSRID );
    2226               0 :         *pnSRID = nSRID;
    2227                 :     }
    2228                 : 
    2229                 :     return createFromSpatialiteInternal(pabyData + 39, ppoGeometry,
    2230            1295 :                                         nBytes - 39, eByteOrder, NULL, 0);
    2231                 : }
    2232                 : 
    2233                 : /************************************************************************/
    2234                 : /*                CanBeCompressedSpatialiteGeometry()                   */
    2235                 : /************************************************************************/
    2236                 : 
    2237              93 : int OGRSQLiteLayer::CanBeCompressedSpatialiteGeometry(const OGRGeometry *poGeometry)
    2238                 : {
    2239              93 :     switch (wkbFlatten(poGeometry->getGeometryType()))
    2240                 :     {
    2241                 :         case wkbLineString:
    2242                 :         case wkbLinearRing:
    2243                 :         {
    2244              40 :             int nPoints = ((OGRLineString*)poGeometry)->getNumPoints();
    2245              40 :             return nPoints >= 2;
    2246                 :         }
    2247                 : 
    2248                 :         case wkbPolygon:
    2249                 :         {
    2250              26 :             OGRPolygon* poPoly = (OGRPolygon*) poGeometry;
    2251              26 :             if (poPoly->getExteriorRing() != NULL)
    2252                 :             {
    2253              24 :                 if (!CanBeCompressedSpatialiteGeometry(poPoly->getExteriorRing()))
    2254               0 :                     return FALSE;
    2255                 : 
    2256              24 :                 int nInteriorRingCount = poPoly->getNumInteriorRings();
    2257              28 :                 for(int i=0;i<nInteriorRingCount;i++)
    2258                 :                 {
    2259               4 :                     if (!CanBeCompressedSpatialiteGeometry(poPoly->getInteriorRing(i)))
    2260               0 :                         return FALSE;
    2261                 :                 }
    2262                 :             }
    2263              26 :             return TRUE;
    2264                 :         }
    2265                 : 
    2266                 :         case wkbMultiPoint:
    2267                 :         case wkbMultiLineString:
    2268                 :         case wkbMultiPolygon:
    2269                 :         case wkbGeometryCollection:
    2270                 :         {
    2271              19 :             OGRGeometryCollection* poGeomCollection = (OGRGeometryCollection*) poGeometry;
    2272              19 :             int nParts = poGeomCollection->getNumGeometries();
    2273              33 :             for(int i=0;i<nParts;i++)
    2274                 :             {
    2275              20 :                 if (!CanBeCompressedSpatialiteGeometry(poGeomCollection->getGeometryRef(i)))
    2276               6 :                     return FALSE;
    2277                 :             }
    2278              13 :             return TRUE;
    2279                 :         }
    2280                 : 
    2281                 :         default:
    2282               8 :             return FALSE;
    2283                 :     }
    2284                 : }
    2285                 : 
    2286                 : /************************************************************************/
    2287                 : /*                  ComputeSpatiaLiteGeometrySize()                     */
    2288                 : /************************************************************************/
    2289                 : 
    2290             568 : int OGRSQLiteLayer::ComputeSpatiaLiteGeometrySize(const OGRGeometry *poGeometry,
    2291                 :                                                   int bHasM, int bSpatialite2D,
    2292                 :                                                   int bUseComprGeom)
    2293                 : {
    2294             568 :     switch (wkbFlatten(poGeometry->getGeometryType()))
    2295                 :     {
    2296                 :         case wkbPoint:
    2297             180 :             if ( bSpatialite2D == TRUE )
    2298               4 :                 return 16;
    2299             176 :             else if (poGeometry->getCoordinateDimension() == 3)
    2300                 :             {
    2301              10 :                 if (bHasM == TRUE)
    2302               0 :                     return 32;
    2303                 :                 else
    2304              10 :                     return 24;
    2305                 :             }
    2306                 :             else
    2307                 :             {
    2308             166 :                 if (bHasM == TRUE)
    2309               0 :                     return 24;
    2310                 :                 else
    2311             166 :                     return 16;
    2312                 :             }
    2313                 : 
    2314                 :         case wkbLineString:
    2315                 :         case wkbLinearRing:
    2316                 :         {
    2317             187 :             int nPoints = ((OGRLineString*)poGeometry)->getNumPoints();
    2318                 :             int nDimension;
    2319             187 :             int nPointsDouble = nPoints;
    2320             187 :             int nPointsFloat = 0;
    2321             187 :             if ( bSpatialite2D == TRUE )
    2322                 :             {
    2323              12 :                 nDimension = 2;
    2324              12 :                 bHasM = FALSE;
    2325                 :             }
    2326                 :             else
    2327                 :             {
    2328             175 :                 if ( bUseComprGeom && nPoints >= 2 )
    2329                 :                 {
    2330              24 :                     nPointsDouble = 2;
    2331              24 :                     nPointsFloat = nPoints - 2;
    2332                 :                 }
    2333             175 :                 nDimension = poGeometry->getCoordinateDimension();
    2334                 :             }
    2335             187 :             return 4 + nDimension * (8 * nPointsDouble + 4 * nPointsFloat) + ((bHasM) ? nPoints * 8 : 0);
    2336                 :         }
    2337                 : 
    2338                 :         case wkbPolygon:
    2339                 :         {
    2340             145 :             int nSize = 4;
    2341             145 :             OGRPolygon* poPoly = (OGRPolygon*) poGeometry;
    2342             145 :             bUseComprGeom = bUseComprGeom && !bSpatialite2D && CanBeCompressedSpatialiteGeometry(poGeometry);
    2343             145 :             if (poPoly->getExteriorRing() != NULL)
    2344                 :             {
    2345                 :                 nSize += ComputeSpatiaLiteGeometrySize(poPoly->getExteriorRing(),
    2346             141 :                                                        bHasM, bSpatialite2D, bUseComprGeom);
    2347                 : 
    2348             141 :                 int nInteriorRingCount = poPoly->getNumInteriorRings();
    2349             147 :                 for(int i=0;i<nInteriorRingCount;i++)
    2350                 :                     nSize += ComputeSpatiaLiteGeometrySize(poPoly->getInteriorRing(i),
    2351               6 :                                                            bHasM, bSpatialite2D, bUseComprGeom );
    2352                 :             }
    2353             145 :             return nSize;
    2354                 :         }
    2355                 : 
    2356                 :         case wkbMultiPoint:
    2357                 :         case wkbMultiLineString:
    2358                 :         case wkbMultiPolygon:
    2359                 :         case wkbGeometryCollection:
    2360                 :         {
    2361              56 :             int nSize = 4;
    2362              56 :             OGRGeometryCollection* poGeomCollection = (OGRGeometryCollection*) poGeometry;
    2363              56 :             int nParts = poGeomCollection->getNumGeometries();
    2364             128 :             for(int i=0;i<nParts;i++)
    2365                 :                 nSize += 5 + ComputeSpatiaLiteGeometrySize(poGeomCollection->getGeometryRef(i),
    2366              72 :                                                            bHasM, bSpatialite2D, bUseComprGeom );
    2367              56 :             return nSize;
    2368                 :         }
    2369                 : 
    2370                 :         default:
    2371               0 :             CPLError(CE_Failure, CPLE_AppDefined, "Unexpected geometry type");
    2372               0 :             return 0;
    2373                 :     }
    2374                 : }
    2375                 : 
    2376                 : /************************************************************************/
    2377                 : /*                    GetSpatialiteGeometryCode()                       */
    2378                 : /************************************************************************/
    2379                 : 
    2380             421 : int OGRSQLiteLayer::GetSpatialiteGeometryCode(const OGRGeometry *poGeometry,
    2381                 :                                               int bHasM, int bSpatialite2D,
    2382                 :                                               int bUseComprGeom,
    2383                 :                                               int bAcceptMultiGeom)
    2384                 : {
    2385             421 :     OGRwkbGeometryType eType = wkbFlatten(poGeometry->getGeometryType());
    2386             421 :     switch (eType)
    2387                 :     {
    2388                 :         case wkbPoint:
    2389             180 :             if ( bSpatialite2D == TRUE )
    2390               4 :                 return OGRSplitePointXY;
    2391             176 :             else if (poGeometry->getCoordinateDimension() == 3)
    2392                 :             {
    2393              10 :                 if (bHasM == TRUE)
    2394               0 :                     return OGRSplitePointXYZM;
    2395                 :                 else
    2396              10 :                     return OGRSplitePointXYZ;
    2397                 :              }
    2398                 :              else
    2399                 :              {
    2400             166 :                 if (bHasM == TRUE)
    2401               0 :                     return OGRSplitePointXYM;
    2402                 :                 else
    2403             166 :                     return OGRSplitePointXY;
    2404                 :             }
    2405                 :             break;
    2406                 : 
    2407                 :         case wkbLineString:
    2408                 :         case wkbLinearRing:
    2409              40 :             if ( bSpatialite2D == TRUE )
    2410               4 :                 return OGRSpliteLineStringXY;
    2411              36 :             else if (poGeometry->getCoordinateDimension() == 3)
    2412                 :             {
    2413              12 :                 if (bHasM == TRUE)
    2414               0 :                     return (bUseComprGeom) ? OGRSpliteComprLineStringXYZM : OGRSpliteLineStringXYZM;
    2415                 :                 else
    2416              12 :                     return (bUseComprGeom) ? OGRSpliteComprLineStringXYZ : OGRSpliteLineStringXYZ;
    2417                 :             }
    2418                 :             else
    2419                 :             {
    2420              24 :                 if (bHasM == TRUE)
    2421               0 :                     return (bUseComprGeom) ? OGRSpliteComprLineStringXYM : OGRSpliteLineStringXYM;
    2422                 :                 else
    2423              24 :                     return (bUseComprGeom) ? OGRSpliteComprLineStringXY : OGRSpliteLineStringXY;
    2424                 :             }
    2425                 :             break;
    2426                 : 
    2427                 :         case wkbPolygon:
    2428             145 :             if ( bSpatialite2D == TRUE )
    2429               8 :                 return OGRSplitePolygonXY;
    2430             137 :             else if (poGeometry->getCoordinateDimension() == 3)
    2431                 :             {
    2432              12 :                 if (bHasM == TRUE)
    2433               0 :                     return (bUseComprGeom) ? OGRSpliteComprPolygonXYZM : OGRSplitePolygonXYZM;
    2434                 :                 else
    2435              12 :                     return (bUseComprGeom) ? OGRSpliteComprPolygonXYZ : OGRSplitePolygonXYZ;
    2436                 :             }
    2437                 :             else
    2438                 :             {
    2439             125 :                 if (bHasM == TRUE)
    2440               0 :                     return (bUseComprGeom) ? OGRSpliteComprPolygonXYM : OGRSplitePolygonXYM;
    2441                 :                 else
    2442             125 :                     return (bUseComprGeom) ? OGRSpliteComprPolygonXY : OGRSplitePolygonXY;
    2443                 :             }
    2444                 :             break;
    2445                 : 
    2446                 :         default:
    2447                 :             break;
    2448                 :     }
    2449                 : 
    2450              56 :     if (!bAcceptMultiGeom)
    2451                 :     {
    2452               0 :         CPLError(CE_Failure, CPLE_AppDefined, "Unexpected geometry type");
    2453               0 :         return 0;
    2454                 :     }
    2455                 : 
    2456              56 :     switch (eType)
    2457                 :     {
    2458                 :         case wkbMultiPoint:
    2459              10 :             if ( bSpatialite2D == TRUE )
    2460               2 :                 return OGRSpliteMultiPointXY;
    2461               8 :             else if (poGeometry->getCoordinateDimension() == 3)
    2462                 :             {
    2463               2 :                 if (bHasM == TRUE)
    2464               0 :                     return OGRSpliteMultiPointXYZM;
    2465                 :                 else
    2466               2 :                     return OGRSpliteMultiPointXYZ;
    2467                 :             }
    2468                 :             else
    2469                 :             {
    2470               6 :                 if (bHasM == TRUE)
    2471               0 :                     return OGRSpliteMultiPointXYM;
    2472                 :                 else
    2473               6 :                     return OGRSpliteMultiPointXY;
    2474                 :             }
    2475                 :             break;
    2476                 : 
    2477                 :         case wkbMultiLineString:
    2478              10 :             if ( bSpatialite2D == TRUE )
    2479               2 :                 return OGRSpliteMultiLineStringXY;
    2480               8 :             else if (poGeometry->getCoordinateDimension() == 3)
    2481                 :             {
    2482               2 :                 if (bHasM == TRUE)
    2483               0 :                     return /*(bUseComprGeom) ? OGRSpliteComprMultiLineStringXYZM :*/ OGRSpliteMultiLineStringXYZM;
    2484                 :                 else
    2485               2 :                     return /*(bUseComprGeom) ? OGRSpliteComprMultiLineStringXYZ :*/ OGRSpliteMultiLineStringXYZ;
    2486                 :             }
    2487                 :             else
    2488                 :             {
    2489               6 :                 if (bHasM == TRUE)
    2490               0 :                     return /*(bUseComprGeom) ? OGRSpliteComprMultiLineStringXYM :*/ OGRSpliteMultiLineStringXYM;
    2491                 :                 else
    2492               6 :                     return /*(bUseComprGeom) ? OGRSpliteComprMultiLineStringXY :*/ OGRSpliteMultiLineStringXY;
    2493                 :             }
    2494                 :             break;
    2495                 : 
    2496                 :         case wkbMultiPolygon:
    2497              12 :             if ( bSpatialite2D == TRUE )
    2498               2 :                 return OGRSpliteMultiPolygonXY;
    2499              10 :             else if (poGeometry->getCoordinateDimension() == 3)
    2500                 :             {
    2501               2 :                 if (bHasM == TRUE)
    2502               0 :                     return /*(bUseComprGeom) ? OGRSpliteComprMultiPolygonXYZM :*/ OGRSpliteMultiPolygonXYZM;
    2503                 :                 else
    2504               2 :                     return /*(bUseComprGeom) ? OGRSpliteComprMultiPolygonXYZ :*/ OGRSpliteMultiPolygonXYZ;
    2505                 :             }
    2506                 :             else
    2507                 :             {
    2508               8 :                 if (bHasM == TRUE)
    2509               0 :                     return /*(bUseComprGeom) ? OGRSpliteComprMultiPolygonXYM :*/ OGRSpliteMultiPolygonXYM;
    2510                 :                 else
    2511               8 :                     return /*(bUseComprGeom) ? OGRSpliteComprMultiPolygonXY :*/ OGRSpliteMultiPolygonXY;
    2512                 :             }
    2513                 :             break;
    2514                 : 
    2515                 : 
    2516                 :         case wkbGeometryCollection:
    2517              24 :             if ( bSpatialite2D == TRUE )
    2518               3 :                 return OGRSpliteGeometryCollectionXY;
    2519              21 :             else if (poGeometry->getCoordinateDimension() == 3)
    2520                 :             {
    2521               8 :                 if (bHasM == TRUE)
    2522               0 :                     return /*(bUseComprGeom) ? OGRSpliteComprGeometryCollectionXYZM :*/ OGRSpliteGeometryCollectionXYZM;
    2523                 :                 else
    2524               8 :                     return /*(bUseComprGeom) ? OGRSpliteComprGeometryCollectionXYZ :*/ OGRSpliteGeometryCollectionXYZ;
    2525                 :             }
    2526                 :             else
    2527                 :             {
    2528              13 :                 if (bHasM == TRUE)
    2529               0 :                     return /*(bUseComprGeom) ? OGRSpliteComprGeometryCollectionXYM :*/ OGRSpliteGeometryCollectionXYM;
    2530                 :                 else
    2531              13 :                     return /*(bUseComprGeom) ? OGRSpliteComprGeometryCollectionXY :*/ OGRSpliteGeometryCollectionXY;
    2532                 :             }
    2533                 :             break;
    2534                 : 
    2535                 :         default:
    2536               0 :             CPLError(CE_Failure, CPLE_AppDefined, "Unexpected geometry type");
    2537               0 :             return 0;
    2538                 :     }
    2539                 : }
    2540                 : 
    2541                 : /************************************************************************/
    2542                 : /*                      ExportSpatiaLiteGeometry()                      */
    2543                 : /************************************************************************/
    2544                 : 
    2545             568 : int OGRSQLiteLayer::ExportSpatiaLiteGeometryInternal(const OGRGeometry *poGeometry,
    2546                 :                                                      OGRwkbByteOrder eByteOrder,
    2547                 :                                                      int bHasM, int bSpatialite2D,
    2548                 :                                                      int bUseComprGeom,
    2549                 :                                                      GByte* pabyData )
    2550                 : {
    2551             568 :     switch (wkbFlatten(poGeometry->getGeometryType()))
    2552                 :     {
    2553                 :         case wkbPoint:
    2554                 :         {
    2555             180 :             OGRPoint* poPoint = (OGRPoint*) poGeometry;
    2556             180 :             double x = poPoint->getX();
    2557             180 :             double y = poPoint->getY();
    2558             180 :             memcpy(pabyData, &x, 8);
    2559             180 :             memcpy(pabyData + 8, &y, 8);
    2560             180 :             if (NEED_SWAP_SPATIALITE())
    2561                 :             {
    2562               0 :                 CPL_SWAP64PTR( pabyData );
    2563               0 :                 CPL_SWAP64PTR( pabyData + 8 );
    2564                 :             }
    2565             180 :             if ( bSpatialite2D == TRUE )
    2566               4 :                 return 16;
    2567             176 :             else if (poGeometry->getCoordinateDimension() == 3)
    2568                 :             {
    2569              10 :                 double z = poPoint->getZ();
    2570              10 :                 memcpy(pabyData + 16, &z, 8);
    2571              10 :                 if (NEED_SWAP_SPATIALITE())
    2572               0 :                     CPL_SWAP64PTR( pabyData + 16 );
    2573              10 :                 if (bHasM == TRUE)
    2574                 :                 {
    2575               0 :                     double m = 0.0;
    2576               0 :                     memcpy(pabyData + 24, &m, 8);
    2577               0 :                     if (NEED_SWAP_SPATIALITE())
    2578               0 :                         CPL_SWAP64PTR( pabyData + 24 );
    2579               0 :                     return 32;
    2580                 :                 }
    2581                 :                 else
    2582              10 :                     return 24;
    2583                 :             }
    2584                 :             else
    2585                 :             {
    2586             166 :                 if (bHasM == TRUE)
    2587                 :                 {
    2588               0 :                     double m = 0.0;
    2589               0 :                     memcpy(pabyData + 16, &m, 8);
    2590               0 :                     if (NEED_SWAP_SPATIALITE())
    2591               0 :                         CPL_SWAP64PTR( pabyData + 16 );
    2592               0 :                     return 24;
    2593                 :                 }
    2594                 :                 else
    2595             166 :                     return 16;
    2596                 :             }
    2597                 :         }
    2598                 : 
    2599                 :         case wkbLineString:
    2600                 :         case wkbLinearRing:
    2601                 :         {
    2602             187 :             OGRLineString* poLineString = (OGRLineString*) poGeometry;
    2603             187 :             int nTotalSize = 4;
    2604             187 :             int nPointCount = poLineString->getNumPoints();
    2605             187 :             memcpy(pabyData, &nPointCount, 4);
    2606             187 :             if (NEED_SWAP_SPATIALITE())
    2607               0 :                 CPL_SWAP32PTR( pabyData );
    2608                 : 
    2609            2168 :             for(int i=0;i<nPointCount;i++)
    2610                 :             {
    2611            1981 :                 double x = poLineString->getX(i);
    2612            1981 :                 double y = poLineString->getY(i);
    2613                 : 
    2614            3918 :                 if (!bUseComprGeom || i == 0 || i == nPointCount - 1)
    2615                 :                 {
    2616            1937 :                     memcpy(pabyData + nTotalSize, &x, 8);
    2617            1937 :                     memcpy(pabyData + nTotalSize + 8, &y, 8);
    2618            1937 :                     if (NEED_SWAP_SPATIALITE())
    2619                 :                     {
    2620               0 :                         CPL_SWAP64PTR( pabyData + nTotalSize );
    2621               0 :                         CPL_SWAP64PTR( pabyData + nTotalSize + 8 );
    2622                 :                     }
    2623            1937 :                     if (!bSpatialite2D && poGeometry->getCoordinateDimension() == 3)
    2624                 :                     {
    2625              70 :                         double z = poLineString->getZ(i);
    2626              70 :                         memcpy(pabyData + nTotalSize + 16, &z, 8);
    2627              70 :                         if (NEED_SWAP_SPATIALITE())
    2628               0 :                             CPL_SWAP64PTR( pabyData + nTotalSize + 16 );
    2629              70 :                         if (bHasM == TRUE)
    2630                 :                         {
    2631               0 :                             double m = 0.0;
    2632               0 :                             memcpy(pabyData + nTotalSize + 24, &m, 8);
    2633               0 :                             if (NEED_SWAP_SPATIALITE())
    2634               0 :                                 CPL_SWAP64PTR( pabyData + nTotalSize + 24 );
    2635               0 :                             nTotalSize += 32;
    2636                 :                         }
    2637                 :                         else
    2638              70 :                             nTotalSize += 24;
    2639                 :                     }
    2640                 :                     else
    2641                 :                     {
    2642            1867 :                         if (bHasM == TRUE)
    2643                 :                         {
    2644               0 :                             double m = 0.0;
    2645               0 :                             memcpy(pabyData + nTotalSize + 16, &m, 8);
    2646               0 :                             if (NEED_SWAP_SPATIALITE())
    2647               0 :                                 CPL_SWAP64PTR( pabyData + nTotalSize + 16 );
    2648               0 :                             nTotalSize += 24;
    2649                 :                         }
    2650                 :                         else
    2651            1867 :                             nTotalSize += 16;
    2652                 :                     }
    2653                 :                 }
    2654                 :                 else /* Compressed intermediate points */
    2655                 :                 {
    2656              44 :                     float deltax = (float)(x - poLineString->getX(i-1));
    2657              44 :                     float deltay = (float)(y - poLineString->getY(i-1));
    2658              44 :                     memcpy(pabyData + nTotalSize, &deltax, 4);
    2659              44 :                     memcpy(pabyData + nTotalSize + 4, &deltay, 4);
    2660              44 :                     if (NEED_SWAP_SPATIALITE())
    2661                 :                     {
    2662               0 :                         CPL_SWAP32PTR( pabyData + nTotalSize );
    2663               0 :                         CPL_SWAP32PTR( pabyData + nTotalSize + 4 );
    2664                 :                     }
    2665              44 :                     if (poGeometry->getCoordinateDimension() == 3)
    2666                 :                     {
    2667              16 :                         double z = poLineString->getZ(i);
    2668              16 :                         float deltaz = (float)(z - poLineString->getZ(i-1));
    2669              16 :                         memcpy(pabyData + nTotalSize + 8, &deltaz, 4);
    2670              16 :                         if (NEED_SWAP_SPATIALITE())
    2671               0 :                             CPL_SWAP32PTR( pabyData + nTotalSize + 8 );
    2672              16 :                         if (bHasM == TRUE)
    2673                 :                         {
    2674               0 :                             double m = 0.0;
    2675               0 :                             memcpy(pabyData + nTotalSize + 12, &m, 8);
    2676               0 :                             if (NEED_SWAP_SPATIALITE())
    2677               0 :                                 CPL_SWAP64PTR( pabyData + nTotalSize + 12 );
    2678               0 :                             nTotalSize += 20;
    2679                 :                         }
    2680                 :                         else
    2681              16 :                             nTotalSize += 12;
    2682                 :                     }
    2683                 :                     else
    2684                 :                     {
    2685              28 :                         if (bHasM == TRUE)
    2686                 :                         {
    2687               0 :                             double m = 0.0;
    2688               0 :                             memcpy(pabyData + nTotalSize + 8, &m, 8);
    2689               0 :                             if (NEED_SWAP_SPATIALITE())
    2690               0 :                                 CPL_SWAP64PTR( pabyData + nTotalSize + 8 );
    2691               0 :                             nTotalSize += 16;
    2692                 :                         }
    2693                 :                         else
    2694              28 :                             nTotalSize += 8;
    2695                 :                     }
    2696                 :                 }
    2697                 :             }
    2698             187 :             return nTotalSize;
    2699                 :         }
    2700                 : 
    2701                 :         case wkbPolygon:
    2702                 :         {
    2703             145 :             OGRPolygon* poPoly = (OGRPolygon*) poGeometry;
    2704             145 :             int nParts = 0;
    2705             145 :             int nTotalSize = 4;
    2706             145 :             if (poPoly->getExteriorRing() != NULL)
    2707                 :             {
    2708             141 :                 int nInteriorRingCount = poPoly->getNumInteriorRings();
    2709             141 :                 nParts = 1 + nInteriorRingCount;
    2710             141 :                 memcpy(pabyData, &nParts, 4);
    2711             141 :                 if (NEED_SWAP_SPATIALITE())
    2712               0 :                     CPL_SWAP32PTR( pabyData );
    2713                 : 
    2714                 :                 nTotalSize += ExportSpatiaLiteGeometryInternal(poPoly->getExteriorRing(),
    2715                 :                                                               eByteOrder,
    2716                 :                                                               bHasM, bSpatialite2D,
    2717                 :                                                               bUseComprGeom,
    2718             141 :                                                               pabyData + nTotalSize);
    2719                 : 
    2720             147 :                 for(int i=0;i<nInteriorRingCount;i++)
    2721                 :                 {
    2722                 :                     nTotalSize += ExportSpatiaLiteGeometryInternal(poPoly->getInteriorRing(i),
    2723                 :                                                                    eByteOrder,
    2724                 :                                                                    bHasM, bSpatialite2D,
    2725                 :                                                                    bUseComprGeom,
    2726               6 :                                                                    pabyData + nTotalSize);
    2727                 :                 }
    2728                 :             }
    2729                 :             else
    2730                 :             {
    2731               4 :                 memset(pabyData, 0, 4);
    2732                 :             }
    2733             145 :             return nTotalSize;
    2734                 :         }
    2735                 : 
    2736                 :         case wkbMultiPoint:
    2737                 :         case wkbMultiLineString:
    2738                 :         case wkbMultiPolygon:
    2739                 :         case wkbGeometryCollection:
    2740                 :         {
    2741              56 :             OGRGeometryCollection* poGeomCollection = (OGRGeometryCollection*) poGeometry;
    2742              56 :             int nTotalSize = 4;
    2743              56 :             int nParts = poGeomCollection->getNumGeometries();
    2744              56 :             memcpy(pabyData, &nParts, 4);
    2745              56 :             if (NEED_SWAP_SPATIALITE())
    2746               0 :                 CPL_SWAP32PTR( pabyData );
    2747                 : 
    2748             128 :             for(int i=0;i<nParts;i++)
    2749                 :             {
    2750              72 :                 pabyData[nTotalSize] = 0x69;
    2751              72 :                 nTotalSize ++;
    2752                 :                 int nCode = GetSpatialiteGeometryCode(poGeomCollection->getGeometryRef(i),
    2753                 :                                                       bHasM, bSpatialite2D,
    2754              72 :                                                       bUseComprGeom, FALSE);
    2755              72 :                 if (nCode == 0)
    2756               0 :                     return 0;
    2757              72 :                 memcpy(pabyData + nTotalSize, &nCode, 4);
    2758              72 :                 if (NEED_SWAP_SPATIALITE())
    2759               0 :                     CPL_SWAP32PTR( pabyData + nTotalSize );
    2760              72 :                 nTotalSize += 4;
    2761                 :                 nTotalSize += ExportSpatiaLiteGeometryInternal(poGeomCollection->getGeometryRef(i),
    2762                 :                                                                eByteOrder,
    2763                 :                                                                bHasM, bSpatialite2D,
    2764                 :                                                                bUseComprGeom,
    2765              72 :                                                                pabyData + nTotalSize);
    2766                 :             }
    2767              56 :             return nTotalSize;
    2768                 :         }
    2769                 : 
    2770                 :         default:
    2771               0 :             return 0;
    2772                 :     }
    2773                 : }
    2774                 : 
    2775                 : 
    2776             349 : OGRErr OGRSQLiteLayer::ExportSpatiaLiteGeometry( const OGRGeometry *poGeometry,
    2777                 :                                                  GInt32 nSRID,
    2778                 :                                                  OGRwkbByteOrder eByteOrder,
    2779                 :                                                  int bHasM, int bSpatialite2D,
    2780                 :                                                  int bUseComprGeom,
    2781                 :                                                  GByte **ppabyData,
    2782                 :                                                  int *pnDataLenght )
    2783                 : 
    2784                 : {
    2785                 : 
    2786             349 :     bUseComprGeom = bUseComprGeom && !bSpatialite2D && CanBeCompressedSpatialiteGeometry(poGeometry);
    2787                 : 
    2788                 :     int     nDataLen = 44 + ComputeSpatiaLiteGeometrySize( poGeometry,
    2789                 :                                                            bHasM, 
    2790                 :                                                            bSpatialite2D,
    2791             349 :                                                            bUseComprGeom );
    2792             349 :     OGREnvelope sEnvelope;
    2793                 : 
    2794             349 :     *ppabyData =  (GByte *) CPLMalloc( nDataLen );
    2795                 : 
    2796             349 :     (*ppabyData)[0] = 0x00;
    2797             349 :     (*ppabyData)[1] = (GByte) eByteOrder;
    2798                 : 
    2799                 :     // Write out SRID
    2800             349 :     memcpy( *ppabyData + 2, &nSRID, 4 );
    2801                 : 
    2802                 :     // Write out the geometry bounding rectangle
    2803             349 :     poGeometry->getEnvelope( &sEnvelope );
    2804             349 :     memcpy( *ppabyData + 6, &sEnvelope.MinX, 8 );
    2805             349 :     memcpy( *ppabyData + 14, &sEnvelope.MinY, 8 );
    2806             349 :     memcpy( *ppabyData + 22, &sEnvelope.MaxX, 8 );
    2807             349 :     memcpy( *ppabyData + 30, &sEnvelope.MaxY, 8 );
    2808                 : 
    2809             349 :     (*ppabyData)[38] = 0x7C;
    2810                 : 
    2811                 :     int nCode = GetSpatialiteGeometryCode(poGeometry,
    2812                 :                                           bHasM, bSpatialite2D,
    2813             349 :                                           bUseComprGeom, TRUE);
    2814             349 :     if (nCode == 0)
    2815                 :     {
    2816               0 :         CPLFree(*ppabyData);
    2817               0 :         *ppabyData = NULL;
    2818               0 :         *pnDataLenght = 0;
    2819               0 :         return CE_Failure;
    2820                 :     }
    2821             349 :     memcpy( *ppabyData + 39, &nCode, 4 );
    2822                 : 
    2823                 :     int nWritten = ExportSpatiaLiteGeometryInternal(poGeometry, 
    2824                 :                                                     eByteOrder, 
    2825                 :                                                     bHasM, bSpatialite2D,
    2826                 :                                                     bUseComprGeom,
    2827             349 :                                                     *ppabyData + 43);
    2828             349 :     if (nWritten == 0)
    2829                 :     {
    2830               0 :         CPLFree(*ppabyData);
    2831               0 :         *ppabyData = NULL;
    2832               0 :         *pnDataLenght = 0;
    2833               0 :         return CE_Failure;
    2834                 :     }
    2835                 : 
    2836             349 :     (*ppabyData)[nDataLen - 1] = 0xFE;
    2837                 : 
    2838             349 :     if( NEED_SWAP_SPATIALITE() )
    2839                 :     {
    2840               0 :         CPL_SWAP32PTR( *ppabyData + 2 );
    2841               0 :         CPL_SWAP64PTR( *ppabyData + 6 );
    2842               0 :         CPL_SWAP64PTR( *ppabyData + 14 );
    2843               0 :         CPL_SWAP64PTR( *ppabyData + 22 );
    2844               0 :         CPL_SWAP64PTR( *ppabyData + 30 );
    2845               0 :         CPL_SWAP32PTR( *ppabyData + 39 );
    2846                 :     }
    2847                 : 
    2848             349 :     *pnDataLenght = nDataLen;
    2849                 : 
    2850             349 :     return CE_None;
    2851                 : }
    2852                 : 
    2853                 : /************************************************************************/
    2854                 : /*                           TestCapability()                           */
    2855                 : /************************************************************************/
    2856                 : 
    2857              66 : int OGRSQLiteLayer::TestCapability( const char * pszCap )
    2858                 : 
    2859                 : {
    2860              66 :     if( EQUAL(pszCap,OLCRandomRead) )
    2861               4 :         return FALSE;
    2862                 : 
    2863              62 :     else if( EQUAL(pszCap,OLCFastFeatureCount) )
    2864               0 :         return FALSE;
    2865                 : 
    2866              62 :     else if( EQUAL(pszCap,OLCFastSpatialFilter) )
    2867               0 :         return FALSE;
    2868                 : 
    2869              62 :     else if( EQUAL(pszCap,OLCIgnoreFields) )
    2870              11 :         return TRUE; 
    2871                 : 
    2872              51 :     else if( EQUAL(pszCap,OLCTransactions) )
    2873               9 :         return TRUE;
    2874                 : 
    2875                 :     else 
    2876              42 :         return FALSE;
    2877                 : }
    2878                 : 
    2879                 : /************************************************************************/
    2880                 : /*                           GetSpatialRef()                            */
    2881                 : /************************************************************************/
    2882                 : 
    2883              86 : OGRSpatialReference *OGRSQLiteLayer::GetSpatialRef()
    2884                 : 
    2885                 : {
    2886              86 :     return poSRS;
    2887                 : }
    2888                 : 
    2889                 : /************************************************************************/
    2890                 : /*                          StartTransaction()                          */
    2891                 : /************************************************************************/
    2892                 : 
    2893              35 : OGRErr OGRSQLiteLayer::StartTransaction()
    2894                 : 
    2895                 : {
    2896              35 :     return poDS->SoftStartTransaction();
    2897                 : }
    2898                 : 
    2899                 : /************************************************************************/
    2900                 : /*                         CommitTransaction()                          */
    2901                 : /************************************************************************/
    2902                 : 
    2903              24 : OGRErr OGRSQLiteLayer::CommitTransaction()
    2904                 : 
    2905                 : {
    2906              24 :     return poDS->SoftCommit();
    2907                 : }
    2908                 : 
    2909                 : /************************************************************************/
    2910                 : /*                        RollbackTransaction()                         */
    2911                 : /************************************************************************/
    2912                 : 
    2913              11 : OGRErr OGRSQLiteLayer::RollbackTransaction()
    2914                 : 
    2915                 : {
    2916              11 :     return poDS->SoftRollback();
    2917                 : }
    2918                 : 
    2919                 : /************************************************************************/
    2920                 : /*                           ClearStatement()                           */
    2921                 : /************************************************************************/
    2922                 : 
    2923            2592 : void OGRSQLiteLayer::ClearStatement()
    2924                 : 
    2925                 : {
    2926            2592 :     if( hStmt != NULL )
    2927                 :     {
    2928             543 :         CPLDebug( "OGR_SQLITE", "finalize %p", hStmt );
    2929             543 :         sqlite3_finalize( hStmt );
    2930             543 :         hStmt = NULL;
    2931                 :     }
    2932            2592 : }
    2933                 : 
    2934                 : /************************************************************************/
    2935                 : /*                    OGRSQLITEStringToDateTimeField()                  */
    2936                 : /************************************************************************/
    2937                 : 
    2938             306 : int OGRSQLITEStringToDateTimeField( OGRFeature* poFeature, int iField,
    2939                 :                                     const char* pszValue )
    2940                 : {
    2941             306 :     int nYear = 0, nMonth = 0, nDay = 0,
    2942             306 :         nHour = 0, nMinute = 0;
    2943             306 :     float fSecond = 0;
    2944                 : 
    2945                 :     /* YYYY-MM-DD HH:MM:SS or YYYY-MM-DD HH:MM:SS.SSS */
    2946             306 :     nYear = 0; nMonth = 0; nDay = 0; nHour = 0;
    2947             306 :     nMinute = 0; fSecond = 0;
    2948             306 :     if( sscanf(pszValue, "%04d-%02d-%02d %02d:%02d:%f",
    2949                 :                 &nYear, &nMonth, &nDay, &nHour, &nMinute, &fSecond) == 6 )
    2950                 :     {
    2951                 :         poFeature->SetField( iField, nYear, nMonth,
    2952               0 :                                 nDay, nHour, nMinute, (int)(fSecond + 0.5), 0 );
    2953               0 :         return TRUE;
    2954                 :     }
    2955                 : 
    2956                 :     /* YYYY-MM-DD HH:MM */
    2957             306 :     nYear = 0; nMonth = 0; nDay = 0; nHour = 0;
    2958             306 :     nMinute = 0;
    2959             306 :     if( sscanf(pszValue, "%04d-%02d-%02d %02d:%02d",
    2960                 :                 &nYear, &nMonth, &nDay, &nHour, &nMinute) == 5 )
    2961                 :     {
    2962                 :         poFeature->SetField( iField, nYear, nMonth,
    2963               4 :                                 nDay, nHour, nMinute, 0, 0 );
    2964               4 :         return TRUE;
    2965                 :     }
    2966                 : 
    2967                 :     /*  YYYY-MM-DDTHH:MM:SS or YYYY-MM-DDTHH:MM:SS.SSS */
    2968             302 :     nYear = 0; nMonth = 0; nDay = 0; nHour = 0;
    2969             302 :     nMinute = 0; fSecond = 0;
    2970             302 :     if( sscanf(pszValue, "%04d-%02d-%02dT%02d:%02d:%f",
    2971                 :                 &nYear, &nMonth, &nDay, &nHour, &nMinute, &fSecond) == 6 )
    2972                 :     {
    2973                 :         poFeature->SetField( iField, nYear, nMonth, nDay,
    2974              98 :                                 nHour, nMinute, (int)(fSecond + 0.5), 0 );
    2975              98 :         return TRUE;
    2976                 :     }
    2977                 : 
    2978                 :     /* YYYY-MM-DDTHH:MM */
    2979             204 :     nYear = 0; nMonth = 0; nDay = 0; nHour = 0;
    2980             204 :     nMinute = 0;
    2981             204 :     if( sscanf(pszValue, "%04d-%02d-%02dT%02d:%02d",
    2982                 :                 &nYear, &nMonth, &nDay, &nHour, &nMinute) == 5 )
    2983                 :     {
    2984                 :         poFeature->SetField( iField, nYear, nMonth, nDay,
    2985               0 :                                 nHour, nMinute, 0, 0 );
    2986               0 :         return TRUE;
    2987                 :     }
    2988                 : 
    2989                 :     /* YYYY-MM-DD */
    2990             204 :     nYear = 0; nMonth = 0; nDay = 0;
    2991             204 :     if( sscanf(pszValue, "%04d-%02d-%02d",
    2992                 :                 &nYear, &nMonth, &nDay) == 3 )
    2993                 :     {
    2994                 :         poFeature->SetField( iField, nYear, nMonth, nDay,
    2995             102 :                                 0, 0, 0, 0 );
    2996             102 :         return TRUE;
    2997                 :     }
    2998                 : 
    2999                 :     /*  HH:MM:SS or HH:MM:SS.SSS */
    3000             102 :     nDay = 0; nHour = 0; fSecond = 0;
    3001             102 :     if( sscanf(pszValue, "%02d:%02d:%f",
    3002                 :         &nHour, &nMinute, &fSecond) == 3 )
    3003                 :     {
    3004                 :         poFeature->SetField( iField, 0, 0, 0,
    3005              94 :                                 nHour, nMinute, (int)(fSecond + 0.5), 0 );
    3006              94 :         return TRUE;
    3007                 :     }
    3008                 : 
    3009                 :     /*  HH:MM */
    3010               8 :     nHour = 0; nMinute = 0;
    3011               8 :     if( sscanf(pszValue, "%02d:%02d", &nHour, &nMinute) == 2 )
    3012                 :     {
    3013                 :         poFeature->SetField( iField, 0, 0, 0,
    3014               8 :                                 nHour, nMinute, 0, 0 );
    3015               8 :         return TRUE;
    3016                 :     }
    3017                 : 
    3018               0 :     return FALSE;
    3019                 : }

Generated by: LCOV version 1.7