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 : }
|