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