LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/sqlite - ogrsqlitelayer.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 1206 679 56.3 %
Date: 2011-12-18 Functions: 25 21 84.0 %

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

Generated by: LCOV version 1.7