LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/sqlite - ogrsqlitelayer.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 1206 680 56.4 %
Date: 2012-04-28 Functions: 25 21 84.0 %

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

Generated by: LCOV version 1.7