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