1 : /******************************************************************************
2 : * $Id: ogrmemlayer.cpp 24804 2012-08-19 13:27:13Z rouault $
3 : *
4 : * Project: OpenGIS Simple Features Reference Implementation
5 : * Purpose: Implements OGRMemLayer class.
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2003, Frank Warmerdam <warmerdam@pobox.com>
10 : *
11 : * Permission is hereby granted, free of charge, to any person obtaining a
12 : * copy of this software and associated documentation files (the "Software"),
13 : * to deal in the Software without restriction, including without limitation
14 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 : * and/or sell copies of the Software, and to permit persons to whom the
16 : * Software is furnished to do so, subject to the following conditions:
17 : *
18 : * The above copyright notice and this permission notice shall be included
19 : * in all copies or substantial portions of the Software.
20 : *
21 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 : * DEALINGS IN THE SOFTWARE.
28 : ****************************************************************************/
29 :
30 : #include "ogr_mem.h"
31 : #include "cpl_conv.h"
32 : #include "ogr_p.h"
33 :
34 : CPL_CVSID("$Id: ogrmemlayer.cpp 24804 2012-08-19 13:27:13Z rouault $");
35 :
36 : /************************************************************************/
37 : /* OGRMemLayer() */
38 : /************************************************************************/
39 :
40 328 : OGRMemLayer::OGRMemLayer( const char * pszName, OGRSpatialReference *poSRSIn,
41 328 : OGRwkbGeometryType eReqType )
42 :
43 : {
44 328 : if( poSRSIn == NULL )
45 290 : poSRS = NULL;
46 : else
47 38 : poSRS = poSRSIn->Clone();
48 :
49 328 : iNextReadFID = 0;
50 328 : iNextCreateFID = 0;
51 :
52 328 : nFeatureCount = 0;
53 328 : nMaxFeatureCount = 0;
54 328 : papoFeatures = NULL;
55 :
56 328 : poFeatureDefn = new OGRFeatureDefn( pszName );
57 328 : poFeatureDefn->SetGeomType( eReqType );
58 328 : poFeatureDefn->Reference();
59 :
60 328 : bUpdatable = TRUE;
61 328 : bAdvertizeUTF8 = FALSE;
62 328 : bHasHoles = FALSE;
63 328 : }
64 :
65 : /************************************************************************/
66 : /* ~OGRMemLayer() */
67 : /************************************************************************/
68 :
69 328 : OGRMemLayer::~OGRMemLayer()
70 :
71 : {
72 328 : if( m_nFeaturesRead > 0 && poFeatureDefn != NULL )
73 : {
74 : CPLDebug( "Mem", "%d features read on layer '%s'.",
75 : (int) m_nFeaturesRead,
76 206 : poFeatureDefn->GetName() );
77 : }
78 :
79 8052 : for( int i = 0; i < nMaxFeatureCount; i++ )
80 : {
81 7724 : if( papoFeatures[i] != NULL )
82 1625 : delete papoFeatures[i];
83 : }
84 328 : CPLFree( papoFeatures );
85 :
86 328 : if( poFeatureDefn )
87 328 : poFeatureDefn->Release();
88 :
89 328 : if( poSRS )
90 38 : poSRS->Release();
91 328 : }
92 :
93 : /************************************************************************/
94 : /* ResetReading() */
95 : /************************************************************************/
96 :
97 1115 : void OGRMemLayer::ResetReading()
98 :
99 : {
100 1115 : iNextReadFID = 0;
101 1115 : }
102 :
103 : /************************************************************************/
104 : /* GetNextFeature() */
105 : /************************************************************************/
106 :
107 2392 : OGRFeature *OGRMemLayer::GetNextFeature()
108 :
109 : {
110 20566 : while( iNextReadFID < nMaxFeatureCount )
111 : {
112 17753 : OGRFeature *poFeature = papoFeatures[iNextReadFID++];
113 :
114 17753 : if( poFeature == NULL )
115 15189 : continue;
116 :
117 2564 : if( (m_poFilterGeom == NULL
118 : || FilterGeometry( poFeature->GetGeometryRef() ) )
119 : && (m_poAttrQuery == NULL
120 : || m_poAttrQuery->Evaluate( poFeature ) ) )
121 : {
122 1971 : m_nFeaturesRead++;
123 1971 : return poFeature->Clone();
124 : }
125 : }
126 :
127 421 : return NULL;
128 : }
129 :
130 : /************************************************************************/
131 : /* SetNextByIndex() */
132 : /************************************************************************/
133 :
134 338 : OGRErr OGRMemLayer::SetNextByIndex( long nIndex )
135 :
136 : {
137 338 : if( m_poFilterGeom != NULL || m_poAttrQuery != NULL || bHasHoles )
138 1 : return OGRLayer::SetNextByIndex( nIndex );
139 :
140 337 : if (nIndex < 0 || nIndex >= nMaxFeatureCount)
141 34 : return OGRERR_FAILURE;
142 :
143 303 : iNextReadFID = nIndex;
144 :
145 303 : return OGRERR_NONE;
146 : }
147 :
148 : /************************************************************************/
149 : /* GetFeature() */
150 : /************************************************************************/
151 :
152 45 : OGRFeature *OGRMemLayer::GetFeature( long nFeatureId )
153 :
154 : {
155 45 : if( nFeatureId < 0 || nFeatureId >= nMaxFeatureCount )
156 34 : return NULL;
157 11 : else if( papoFeatures[nFeatureId] == NULL )
158 1 : return NULL;
159 : else
160 10 : return papoFeatures[nFeatureId]->Clone();
161 : }
162 :
163 : /************************************************************************/
164 : /* SetFeature() */
165 : /************************************************************************/
166 :
167 1776 : OGRErr OGRMemLayer::SetFeature( OGRFeature *poFeature )
168 :
169 : {
170 1776 : if (!bUpdatable)
171 0 : return OGRERR_FAILURE;
172 :
173 1776 : if( poFeature == NULL )
174 0 : return OGRERR_FAILURE;
175 :
176 1776 : if( poFeature->GetFID() == OGRNullFID )
177 : {
178 4585 : while( iNextCreateFID < nMaxFeatureCount
179 1351 : && papoFeatures[iNextCreateFID] != NULL )
180 0 : iNextCreateFID++;
181 1617 : poFeature->SetFID( iNextCreateFID++ );
182 : }
183 159 : else if ( poFeature->GetFID() < OGRNullFID )
184 : {
185 : CPLError(CE_Failure, CPLE_NotSupported,
186 1 : "negative FID are not supported");
187 1 : return OGRERR_FAILURE;
188 : }
189 :
190 1775 : if( poFeature->GetFID() >= nMaxFeatureCount )
191 : {
192 302 : int nNewCount = MAX(2*nMaxFeatureCount+10, poFeature->GetFID() + 1 );
193 :
194 : OGRFeature** papoNewFeatures = (OGRFeature **)
195 302 : VSIRealloc( papoFeatures, sizeof(OGRFeature *) * nNewCount);
196 302 : if (papoNewFeatures == NULL)
197 : {
198 : CPLError(CE_Failure, CPLE_OutOfMemory,
199 0 : "Cannot allocate array of %d elements", nNewCount);
200 0 : return OGRERR_FAILURE;
201 : }
202 302 : papoFeatures = papoNewFeatures;
203 : memset( papoFeatures + nMaxFeatureCount, 0,
204 302 : sizeof(OGRFeature *) * (nNewCount - nMaxFeatureCount) );
205 302 : nMaxFeatureCount = nNewCount;
206 : }
207 :
208 1775 : if( papoFeatures[poFeature->GetFID()] != NULL )
209 : {
210 122 : delete papoFeatures[poFeature->GetFID()];
211 122 : papoFeatures[poFeature->GetFID()] = NULL;
212 122 : nFeatureCount--;
213 : }
214 :
215 1775 : papoFeatures[poFeature->GetFID()] = poFeature->Clone();
216 1775 : OGRGeometry* poGeom = papoFeatures[poFeature->GetFID()]->GetGeometryRef();
217 1775 : if( poGeom != NULL && poGeom->getSpatialReference() == NULL )
218 273 : poGeom->assignSpatialReference(GetSpatialRef());
219 1775 : nFeatureCount++;
220 :
221 1775 : return OGRERR_NONE;
222 : }
223 :
224 : /************************************************************************/
225 : /* CreateFeature() */
226 : /************************************************************************/
227 :
228 1653 : OGRErr OGRMemLayer::CreateFeature( OGRFeature *poFeature )
229 :
230 : {
231 1653 : if (!bUpdatable)
232 0 : return OGRERR_FAILURE;
233 :
234 1653 : if( poFeature->GetFID() != OGRNullFID &&
235 : poFeature->GetFID() != iNextCreateFID )
236 42 : bHasHoles = TRUE;
237 :
238 1653 : if( poFeature->GetFID() != OGRNullFID
239 : && poFeature->GetFID() >= 0
240 : && poFeature->GetFID() < nMaxFeatureCount )
241 : {
242 6 : if( papoFeatures[poFeature->GetFID()] != NULL )
243 6 : poFeature->SetFID( OGRNullFID );
244 : }
245 :
246 1653 : if( poFeature->GetFID() > 10000000 )
247 0 : poFeature->SetFID( OGRNullFID );
248 :
249 1653 : return SetFeature( poFeature );
250 : }
251 :
252 : /************************************************************************/
253 : /* DeleteFeature() */
254 : /************************************************************************/
255 :
256 29 : OGRErr OGRMemLayer::DeleteFeature( long nFID )
257 :
258 : {
259 29 : if (!bUpdatable)
260 0 : return OGRERR_FAILURE;
261 :
262 58 : if( nFID < 0 || nFID >= nMaxFeatureCount
263 29 : || papoFeatures[nFID] == NULL )
264 : {
265 1 : return OGRERR_FAILURE;
266 : }
267 : else
268 : {
269 28 : bHasHoles = TRUE;
270 :
271 28 : delete papoFeatures[nFID];
272 28 : papoFeatures[nFID] = NULL;
273 28 : nFeatureCount--;
274 28 : return OGRERR_NONE;
275 : }
276 : }
277 :
278 : /************************************************************************/
279 : /* GetFeatureCount() */
280 : /* */
281 : /* If a spatial filter is in effect, we turn control over to */
282 : /* the generic counter. Otherwise we return the total count. */
283 : /* Eventually we should consider implementing a more efficient */
284 : /* way of counting features matching a spatial query. */
285 : /************************************************************************/
286 :
287 326 : int OGRMemLayer::GetFeatureCount( int bForce )
288 :
289 : {
290 326 : if( m_poFilterGeom != NULL || m_poAttrQuery != NULL )
291 27 : return OGRLayer::GetFeatureCount( bForce );
292 : else
293 299 : return nFeatureCount;
294 : }
295 :
296 : /************************************************************************/
297 : /* TestCapability() */
298 : /************************************************************************/
299 :
300 374 : int OGRMemLayer::TestCapability( const char * pszCap )
301 :
302 : {
303 374 : if( EQUAL(pszCap,OLCRandomRead) )
304 17 : return TRUE;
305 :
306 357 : else if( EQUAL(pszCap,OLCSequentialWrite)
307 : || EQUAL(pszCap,OLCRandomWrite) )
308 36 : return bUpdatable;
309 :
310 321 : else if( EQUAL(pszCap,OLCFastFeatureCount) )
311 197 : return m_poFilterGeom == NULL && m_poAttrQuery == NULL;
312 :
313 124 : else if( EQUAL(pszCap,OLCFastSpatialFilter) )
314 1 : return FALSE;
315 :
316 123 : else if( EQUAL(pszCap,OLCDeleteFeature) )
317 17 : return bUpdatable;
318 :
319 106 : else if( EQUAL(pszCap,OLCCreateField) ||
320 : EQUAL(pszCap,OLCDeleteField) ||
321 : EQUAL(pszCap,OLCReorderFields) ||
322 : EQUAL(pszCap,OLCAlterFieldDefn) )
323 3 : return bUpdatable;
324 :
325 103 : else if( EQUAL(pszCap,OLCFastSetNextByIndex) )
326 18 : return m_poFilterGeom == NULL && m_poAttrQuery == NULL && !bHasHoles;
327 :
328 85 : else if( EQUAL(pszCap,OLCStringsAsUTF8) )
329 16 : return bAdvertizeUTF8;
330 :
331 : else
332 69 : return FALSE;
333 : }
334 :
335 : /************************************************************************/
336 : /* CreateField() */
337 : /************************************************************************/
338 :
339 854 : OGRErr OGRMemLayer::CreateField( OGRFieldDefn *poField, int bApproxOK )
340 :
341 : {
342 854 : if (!bUpdatable)
343 0 : return OGRERR_FAILURE;
344 :
345 : /* -------------------------------------------------------------------- */
346 : /* simple case, no features exist yet. */
347 : /* -------------------------------------------------------------------- */
348 854 : if( nFeatureCount == 0 )
349 : {
350 659 : poFeatureDefn->AddFieldDefn( poField );
351 659 : return OGRERR_NONE;
352 : }
353 :
354 : /* -------------------------------------------------------------------- */
355 : /* Add field definition and setup remap definition. */
356 : /* -------------------------------------------------------------------- */
357 : int *panRemap;
358 : int i;
359 :
360 195 : poFeatureDefn->AddFieldDefn( poField );
361 :
362 195 : panRemap = (int *) CPLMalloc(sizeof(int) * poFeatureDefn->GetFieldCount());
363 1272 : for( i = 0; i < poFeatureDefn->GetFieldCount(); i++ )
364 : {
365 1077 : if( i < poFeatureDefn->GetFieldCount() - 1 )
366 882 : panRemap[i] = i;
367 : else
368 195 : panRemap[i] = -1;
369 : }
370 :
371 : /* -------------------------------------------------------------------- */
372 : /* Remap all the internal features. Hopefully there aren't any */
373 : /* external features referring to our OGRFeatureDefn! */
374 : /* -------------------------------------------------------------------- */
375 2165 : for( i = 0; i < nMaxFeatureCount; i++ )
376 : {
377 1970 : if( papoFeatures[i] != NULL )
378 395 : papoFeatures[i]->RemapFields( NULL, panRemap );
379 : }
380 :
381 195 : CPLFree( panRemap );
382 :
383 195 : return OGRERR_NONE;
384 : }
385 :
386 : /************************************************************************/
387 : /* DeleteField() */
388 : /************************************************************************/
389 :
390 10 : OGRErr OGRMemLayer::DeleteField( int iField )
391 : {
392 10 : if (!bUpdatable)
393 0 : return OGRERR_FAILURE;
394 :
395 10 : if (iField < 0 || iField >= poFeatureDefn->GetFieldCount())
396 : {
397 : CPLError( CE_Failure, CPLE_NotSupported,
398 2 : "Invalid field index");
399 2 : return OGRERR_FAILURE;
400 : }
401 :
402 : /* -------------------------------------------------------------------- */
403 : /* Update all the internal features. Hopefully there aren't any */
404 : /* external features referring to our OGRFeatureDefn! */
405 : /* -------------------------------------------------------------------- */
406 68 : for( int i = 0; i < nMaxFeatureCount; i++ )
407 : {
408 60 : if( papoFeatures[i] == NULL )
409 36 : continue;
410 :
411 24 : OGRField* poFieldRaw = papoFeatures[i]->GetRawFieldRef(iField);
412 24 : if( papoFeatures[i]->IsFieldSet(iField) )
413 : {
414 : /* Little trick to unallocate the field */
415 : OGRField sField;
416 12 : sField.Set.nMarker1 = OGRUnsetMarker;
417 12 : sField.Set.nMarker2 = OGRUnsetMarker;
418 12 : papoFeatures[i]->SetField(iField, &sField);
419 : }
420 :
421 24 : if (iField < poFeatureDefn->GetFieldCount() - 1)
422 : {
423 : memmove( poFieldRaw, poFieldRaw + 1,
424 12 : sizeof(OGRField) * (poFeatureDefn->GetFieldCount() - 1 - iField) );
425 : }
426 : }
427 :
428 8 : return poFeatureDefn->DeleteFieldDefn( iField );
429 : }
430 :
431 : /************************************************************************/
432 : /* ReorderFields() */
433 : /************************************************************************/
434 :
435 12 : OGRErr OGRMemLayer::ReorderFields( int* panMap )
436 : {
437 12 : if (!bUpdatable)
438 0 : return OGRERR_FAILURE;
439 :
440 12 : if (poFeatureDefn->GetFieldCount() == 0)
441 1 : return OGRERR_NONE;
442 :
443 11 : OGRErr eErr = OGRCheckPermutation(panMap, poFeatureDefn->GetFieldCount());
444 11 : if (eErr != OGRERR_NONE)
445 1 : return eErr;
446 :
447 : /* -------------------------------------------------------------------- */
448 : /* Remap all the internal features. Hopefully there aren't any */
449 : /* external features referring to our OGRFeatureDefn! */
450 : /* -------------------------------------------------------------------- */
451 110 : for( int i = 0; i < nMaxFeatureCount; i++ )
452 : {
453 100 : if( papoFeatures[i] != NULL )
454 40 : papoFeatures[i]->RemapFields( NULL, panMap );
455 : }
456 :
457 10 : return poFeatureDefn->ReorderFieldDefns( panMap );
458 : }
459 :
460 : /************************************************************************/
461 : /* AlterFieldDefn() */
462 : /************************************************************************/
463 :
464 55 : OGRErr OGRMemLayer::AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nFlags )
465 : {
466 55 : if (!bUpdatable)
467 0 : return OGRERR_FAILURE;
468 :
469 55 : if (iField < 0 || iField >= poFeatureDefn->GetFieldCount())
470 : {
471 : CPLError( CE_Failure, CPLE_NotSupported,
472 2 : "Invalid field index");
473 2 : return OGRERR_FAILURE;
474 : }
475 :
476 53 : OGRFieldDefn* poFieldDefn = poFeatureDefn->GetFieldDefn(iField);
477 :
478 53 : if ((nFlags & ALTER_TYPE_FLAG) &&
479 : poFieldDefn->GetType() != poNewFieldDefn->GetType())
480 : {
481 44 : if ((poNewFieldDefn->GetType() == OFTDate ||
482 : poNewFieldDefn->GetType() == OFTTime ||
483 : poNewFieldDefn->GetType() == OFTDateTime) &&
484 : (poFieldDefn->GetType() == OFTDate ||
485 : poFieldDefn->GetType() == OFTTime ||
486 : poFieldDefn->GetType() == OFTDateTime))
487 : {
488 : /* do nothing on features */
489 : }
490 33 : else if (poNewFieldDefn->GetType() == OFTReal &&
491 : poFieldDefn->GetType() == OFTInteger)
492 : {
493 : /* -------------------------------------------------------------------- */
494 : /* Update all the internal features. Hopefully there aren't any */
495 : /* external features referring to our OGRFeatureDefn! */
496 : /* -------------------------------------------------------------------- */
497 132 : for( int i = 0; i < nMaxFeatureCount; i++ )
498 : {
499 120 : if( papoFeatures[i] == NULL )
500 108 : continue;
501 :
502 12 : OGRField* poFieldRaw = papoFeatures[i]->GetRawFieldRef(iField);
503 12 : if( papoFeatures[i]->IsFieldSet(iField) )
504 : {
505 12 : poFieldRaw->Real = poFieldRaw->Integer;
506 : }
507 : }
508 : }
509 : else
510 : {
511 21 : if (poNewFieldDefn->GetType() != OFTString)
512 : {
513 : CPLError( CE_Failure, CPLE_NotSupported,
514 0 : "Can only convert from OFTInteger to OFTReal, or from anything to OFTString");
515 0 : return OGRERR_FAILURE;
516 : }
517 :
518 : /* -------------------------------------------------------------------- */
519 : /* Update all the internal features. Hopefully there aren't any */
520 : /* external features referring to our OGRFeatureDefn! */
521 : /* -------------------------------------------------------------------- */
522 511 : for( int i = 0; i < nMaxFeatureCount; i++ )
523 : {
524 490 : if( papoFeatures[i] == NULL )
525 297 : continue;
526 :
527 193 : OGRField* poFieldRaw = papoFeatures[i]->GetRawFieldRef(iField);
528 193 : if( papoFeatures[i]->IsFieldSet(iField) )
529 : {
530 19 : char* pszVal = CPLStrdup(papoFeatures[i]->GetFieldAsString(iField));
531 :
532 : /* Little trick to unallocate the field */
533 : OGRField sField;
534 19 : sField.Set.nMarker1 = OGRUnsetMarker;
535 19 : sField.Set.nMarker2 = OGRUnsetMarker;
536 19 : papoFeatures[i]->SetField(iField, &sField);
537 :
538 19 : poFieldRaw->String = pszVal;
539 : }
540 : }
541 : }
542 :
543 44 : poFieldDefn->SetType(poNewFieldDefn->GetType());
544 : }
545 :
546 53 : if (nFlags & ALTER_NAME_FLAG)
547 9 : poFieldDefn->SetName(poNewFieldDefn->GetNameRef());
548 53 : if (nFlags & ALTER_WIDTH_PRECISION_FLAG)
549 : {
550 11 : poFieldDefn->SetWidth(poNewFieldDefn->GetWidth());
551 11 : poFieldDefn->SetPrecision(poNewFieldDefn->GetPrecision());
552 : }
553 :
554 53 : return OGRERR_NONE;
555 : }
556 :
557 : /************************************************************************/
558 : /* GetSpatialRef() */
559 : /************************************************************************/
560 :
561 823 : OGRSpatialReference *OGRMemLayer::GetSpatialRef()
562 :
563 : {
564 823 : return poSRS;
565 : }
|