LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/sqlite - ogrsqlitelayer.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 1300 784 60.3 %
Date: 2012-12-26 Functions: 28 25 89.3 %

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

Generated by: LCOV version 1.7