1 : /******************************************************************************
2 : * $Id: ogrmemlayer.cpp 24174 2012-03-29 21:10:56Z 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 24174 2012-03-29 21:10:56Z rouault $");
35 :
36 : /************************************************************************/
37 : /* OGRMemLayer() */
38 : /************************************************************************/
39 :
40 602 : OGRMemLayer::OGRMemLayer( const char * pszName, OGRSpatialReference *poSRSIn,
41 602 : OGRwkbGeometryType eReqType )
42 :
43 : {
44 602 : if( poSRSIn == NULL )
45 558 : poSRS = NULL;
46 : else
47 44 : poSRS = poSRSIn->Clone();
48 :
49 602 : iNextReadFID = 0;
50 602 : iNextCreateFID = 0;
51 :
52 602 : nFeatureCount = 0;
53 602 : nMaxFeatureCount = 0;
54 602 : papoFeatures = NULL;
55 :
56 602 : poFeatureDefn = new OGRFeatureDefn( pszName );
57 602 : poFeatureDefn->SetGeomType( eReqType );
58 602 : poFeatureDefn->Reference();
59 :
60 602 : bUpdatable = TRUE;
61 602 : bAdvertizeUTF8 = FALSE;
62 602 : bHasHoles = FALSE;
63 602 : }
64 :
65 : /************************************************************************/
66 : /* ~OGRMemLayer() */
67 : /************************************************************************/
68 :
69 602 : OGRMemLayer::~OGRMemLayer()
70 :
71 : {
72 602 : if( m_nFeaturesRead > 0 && poFeatureDefn != NULL )
73 : {
74 : CPLDebug( "Mem", "%d features read on layer '%s'.",
75 : (int) m_nFeaturesRead,
76 370 : poFeatureDefn->GetName() );
77 : }
78 :
79 7402 : for( int i = 0; i < nMaxFeatureCount; i++ )
80 : {
81 6800 : if( papoFeatures[i] != NULL )
82 3052 : delete papoFeatures[i];
83 : }
84 602 : CPLFree( papoFeatures );
85 :
86 602 : if( poFeatureDefn )
87 602 : poFeatureDefn->Release();
88 :
89 602 : if( poSRS )
90 44 : poSRS->Release();
91 602 : }
92 :
93 : /************************************************************************/
94 : /* ResetReading() */
95 : /************************************************************************/
96 :
97 1166 : void OGRMemLayer::ResetReading()
98 :
99 : {
100 1166 : iNextReadFID = 0;
101 1166 : }
102 :
103 : /************************************************************************/
104 : /* GetNextFeature() */
105 : /************************************************************************/
106 :
107 3992 : OGRFeature *OGRMemLayer::GetNextFeature()
108 :
109 : {
110 12628 : while( iNextReadFID < nMaxFeatureCount )
111 : {
112 8088 : OGRFeature *poFeature = papoFeatures[iNextReadFID++];
113 :
114 8088 : if( poFeature == NULL )
115 3886 : continue;
116 :
117 4202 : if( (m_poFilterGeom == NULL
118 : || FilterGeometry( poFeature->GetGeometryRef() ) )
119 : && (m_poAttrQuery == NULL
120 : || m_poAttrQuery->Evaluate( poFeature ) ) )
121 : {
122 3444 : m_nFeaturesRead++;
123 3444 : return poFeature->Clone();
124 : }
125 : }
126 :
127 548 : return NULL;
128 : }
129 :
130 : /************************************************************************/
131 : /* SetNextByIndex() */
132 : /************************************************************************/
133 :
134 612 : OGRErr OGRMemLayer::SetNextByIndex( long nIndex )
135 :
136 : {
137 612 : if( m_poFilterGeom != NULL || m_poAttrQuery != NULL || bHasHoles )
138 2 : return OGRLayer::SetNextByIndex( nIndex );
139 :
140 610 : if (nIndex < 0 || nIndex >= nMaxFeatureCount)
141 4 : return OGRERR_FAILURE;
142 :
143 606 : iNextReadFID = nIndex;
144 :
145 606 : return OGRERR_NONE;
146 : }
147 :
148 : /************************************************************************/
149 : /* GetFeature() */
150 : /************************************************************************/
151 :
152 26 : OGRFeature *OGRMemLayer::GetFeature( long nFeatureId )
153 :
154 : {
155 26 : if( nFeatureId < 0 || nFeatureId >= nMaxFeatureCount )
156 4 : return NULL;
157 22 : else if( papoFeatures[nFeatureId] == NULL )
158 2 : return NULL;
159 : else
160 20 : return papoFeatures[nFeatureId]->Clone();
161 : }
162 :
163 : /************************************************************************/
164 : /* SetFeature() */
165 : /************************************************************************/
166 :
167 3280 : OGRErr OGRMemLayer::SetFeature( OGRFeature *poFeature )
168 :
169 : {
170 3280 : if (!bUpdatable)
171 0 : return OGRERR_FAILURE;
172 :
173 3280 : if( poFeature == NULL )
174 0 : return OGRERR_FAILURE;
175 :
176 3280 : if( poFeature->GetFID() == OGRNullFID )
177 : {
178 8498 : while( iNextCreateFID < nMaxFeatureCount
179 2518 : && papoFeatures[iNextCreateFID] != NULL )
180 0 : iNextCreateFID++;
181 2990 : poFeature->SetFID( iNextCreateFID++ );
182 : }
183 290 : else if ( poFeature->GetFID() < OGRNullFID )
184 : {
185 : CPLError(CE_Failure, CPLE_NotSupported,
186 2 : "negative FID are not supported");
187 2 : return OGRERR_FAILURE;
188 : }
189 :
190 3278 : if( poFeature->GetFID() >= nMaxFeatureCount )
191 : {
192 536 : int nNewCount = MAX(2*nMaxFeatureCount+10, poFeature->GetFID() + 1 );
193 :
194 : OGRFeature** papoNewFeatures = (OGRFeature **)
195 536 : VSIRealloc( papoFeatures, sizeof(OGRFeature *) * nNewCount);
196 536 : 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 536 : papoFeatures = papoNewFeatures;
203 : memset( papoFeatures + nMaxFeatureCount, 0,
204 536 : sizeof(OGRFeature *) * (nNewCount - nMaxFeatureCount) );
205 536 : nMaxFeatureCount = nNewCount;
206 : }
207 :
208 3278 : if( papoFeatures[poFeature->GetFID()] != NULL )
209 : {
210 224 : delete papoFeatures[poFeature->GetFID()];
211 224 : papoFeatures[poFeature->GetFID()] = NULL;
212 224 : nFeatureCount--;
213 : }
214 :
215 3278 : papoFeatures[poFeature->GetFID()] = poFeature->Clone();
216 3278 : nFeatureCount++;
217 :
218 3278 : return OGRERR_NONE;
219 : }
220 :
221 : /************************************************************************/
222 : /* CreateFeature() */
223 : /************************************************************************/
224 :
225 3054 : OGRErr OGRMemLayer::CreateFeature( OGRFeature *poFeature )
226 :
227 : {
228 3054 : if (!bUpdatable)
229 0 : return OGRERR_FAILURE;
230 :
231 3054 : if( poFeature->GetFID() != OGRNullFID &&
232 : poFeature->GetFID() != iNextCreateFID )
233 76 : bHasHoles = TRUE;
234 :
235 3054 : if( poFeature->GetFID() != OGRNullFID
236 : && poFeature->GetFID() >= 0
237 : && poFeature->GetFID() < nMaxFeatureCount )
238 : {
239 12 : if( papoFeatures[poFeature->GetFID()] != NULL )
240 12 : poFeature->SetFID( OGRNullFID );
241 : }
242 :
243 3054 : if( poFeature->GetFID() > 10000000 )
244 0 : poFeature->SetFID( OGRNullFID );
245 :
246 3054 : return SetFeature( poFeature );
247 : }
248 :
249 : /************************************************************************/
250 : /* DeleteFeature() */
251 : /************************************************************************/
252 :
253 4 : OGRErr OGRMemLayer::DeleteFeature( long nFID )
254 :
255 : {
256 4 : if (!bUpdatable)
257 0 : return OGRERR_FAILURE;
258 :
259 8 : if( nFID < 0 || nFID >= nMaxFeatureCount
260 4 : || papoFeatures[nFID] == NULL )
261 : {
262 2 : return OGRERR_FAILURE;
263 : }
264 : else
265 : {
266 2 : bHasHoles = TRUE;
267 :
268 2 : delete papoFeatures[nFID];
269 2 : papoFeatures[nFID] = NULL;
270 2 : nFeatureCount--;
271 2 : return OGRERR_NONE;
272 : }
273 : }
274 :
275 : /************************************************************************/
276 : /* GetFeatureCount() */
277 : /* */
278 : /* If a spatial filter is in effect, we turn control over to */
279 : /* the generic counter. Otherwise we return the total count. */
280 : /* Eventually we should consider implementing a more efficient */
281 : /* way of counting features matching a spatial query. */
282 : /************************************************************************/
283 :
284 530 : int OGRMemLayer::GetFeatureCount( int bForce )
285 :
286 : {
287 530 : if( m_poFilterGeom != NULL || m_poAttrQuery != NULL )
288 54 : return OGRLayer::GetFeatureCount( bForce );
289 : else
290 476 : return nFeatureCount;
291 : }
292 :
293 : /************************************************************************/
294 : /* TestCapability() */
295 : /************************************************************************/
296 :
297 292 : int OGRMemLayer::TestCapability( const char * pszCap )
298 :
299 : {
300 292 : if( EQUAL(pszCap,OLCRandomRead) )
301 34 : return TRUE;
302 :
303 258 : else if( EQUAL(pszCap,OLCSequentialWrite)
304 : || EQUAL(pszCap,OLCRandomWrite) )
305 72 : return bUpdatable;
306 :
307 186 : else if( EQUAL(pszCap,OLCFastFeatureCount) )
308 2 : return m_poFilterGeom == NULL && m_poAttrQuery == NULL;
309 :
310 184 : else if( EQUAL(pszCap,OLCFastSpatialFilter) )
311 2 : return FALSE;
312 :
313 182 : else if( EQUAL(pszCap,OLCDeleteFeature) )
314 34 : return bUpdatable;
315 :
316 148 : else if( EQUAL(pszCap,OLCCreateField) ||
317 : EQUAL(pszCap,OLCDeleteField) ||
318 : EQUAL(pszCap,OLCReorderFields) ||
319 : EQUAL(pszCap,OLCAlterFieldDefn) )
320 6 : return bUpdatable;
321 :
322 142 : else if( EQUAL(pszCap,OLCFastSetNextByIndex) )
323 36 : return m_poFilterGeom == NULL && m_poAttrQuery == NULL && !bHasHoles;
324 :
325 106 : else if( EQUAL(pszCap,OLCStringsAsUTF8) )
326 32 : return bAdvertizeUTF8;
327 :
328 : else
329 74 : return FALSE;
330 : }
331 :
332 : /************************************************************************/
333 : /* CreateField() */
334 : /************************************************************************/
335 :
336 1586 : OGRErr OGRMemLayer::CreateField( OGRFieldDefn *poField, int bApproxOK )
337 :
338 : {
339 1586 : if (!bUpdatable)
340 0 : return OGRERR_FAILURE;
341 :
342 : /* -------------------------------------------------------------------- */
343 : /* simple case, no features exist yet. */
344 : /* -------------------------------------------------------------------- */
345 1586 : if( nFeatureCount == 0 )
346 : {
347 1194 : poFeatureDefn->AddFieldDefn( poField );
348 1194 : return OGRERR_NONE;
349 : }
350 :
351 : /* -------------------------------------------------------------------- */
352 : /* Add field definition and setup remap definition. */
353 : /* -------------------------------------------------------------------- */
354 : int *panRemap;
355 : int i;
356 :
357 392 : poFeatureDefn->AddFieldDefn( poField );
358 :
359 392 : panRemap = (int *) CPLMalloc(sizeof(int) * poFeatureDefn->GetFieldCount());
360 2544 : for( i = 0; i < poFeatureDefn->GetFieldCount(); i++ )
361 : {
362 2152 : if( i < poFeatureDefn->GetFieldCount() - 1 )
363 1760 : panRemap[i] = i;
364 : else
365 392 : panRemap[i] = -1;
366 : }
367 :
368 : /* -------------------------------------------------------------------- */
369 : /* Remap all the internal features. Hopefully there aren't any */
370 : /* external features referring to our OGRFeatureDefn! */
371 : /* -------------------------------------------------------------------- */
372 4352 : for( i = 0; i < nMaxFeatureCount; i++ )
373 : {
374 3960 : if( papoFeatures[i] != NULL )
375 792 : papoFeatures[i]->RemapFields( NULL, panRemap );
376 : }
377 :
378 392 : CPLFree( panRemap );
379 :
380 392 : return OGRERR_NONE;
381 : }
382 :
383 : /************************************************************************/
384 : /* DeleteField() */
385 : /************************************************************************/
386 :
387 20 : OGRErr OGRMemLayer::DeleteField( int iField )
388 : {
389 20 : if (!bUpdatable)
390 0 : return OGRERR_FAILURE;
391 :
392 20 : if (iField < 0 || iField >= poFeatureDefn->GetFieldCount())
393 : {
394 : CPLError( CE_Failure, CPLE_NotSupported,
395 4 : "Invalid field index");
396 4 : return OGRERR_FAILURE;
397 : }
398 :
399 : /* -------------------------------------------------------------------- */
400 : /* Update all the internal features. Hopefully there aren't any */
401 : /* external features referring to our OGRFeatureDefn! */
402 : /* -------------------------------------------------------------------- */
403 136 : for( int i = 0; i < nMaxFeatureCount; i++ )
404 : {
405 120 : if( papoFeatures[i] == NULL )
406 72 : continue;
407 :
408 48 : OGRField* poFieldRaw = papoFeatures[i]->GetRawFieldRef(iField);
409 48 : if( papoFeatures[i]->IsFieldSet(iField) )
410 : {
411 : /* Little trick to unallocate the field */
412 : OGRField sField;
413 24 : sField.Set.nMarker1 = OGRUnsetMarker;
414 24 : sField.Set.nMarker2 = OGRUnsetMarker;
415 24 : papoFeatures[i]->SetField(iField, &sField);
416 : }
417 :
418 48 : if (iField < poFeatureDefn->GetFieldCount() - 1)
419 : {
420 : memmove( poFieldRaw, poFieldRaw + 1,
421 24 : sizeof(OGRField) * (poFeatureDefn->GetFieldCount() - 1 - iField) );
422 : }
423 : }
424 :
425 16 : return poFeatureDefn->DeleteFieldDefn( iField );
426 : }
427 :
428 : /************************************************************************/
429 : /* ReorderFields() */
430 : /************************************************************************/
431 :
432 24 : OGRErr OGRMemLayer::ReorderFields( int* panMap )
433 : {
434 24 : if (!bUpdatable)
435 0 : return OGRERR_FAILURE;
436 :
437 24 : if (poFeatureDefn->GetFieldCount() == 0)
438 2 : return OGRERR_NONE;
439 :
440 22 : OGRErr eErr = OGRCheckPermutation(panMap, poFeatureDefn->GetFieldCount());
441 22 : if (eErr != OGRERR_NONE)
442 2 : return eErr;
443 :
444 : /* -------------------------------------------------------------------- */
445 : /* Remap all the internal features. Hopefully there aren't any */
446 : /* external features referring to our OGRFeatureDefn! */
447 : /* -------------------------------------------------------------------- */
448 220 : for( int i = 0; i < nMaxFeatureCount; i++ )
449 : {
450 200 : if( papoFeatures[i] != NULL )
451 80 : papoFeatures[i]->RemapFields( NULL, panMap );
452 : }
453 :
454 20 : return poFeatureDefn->ReorderFieldDefns( panMap );
455 : }
456 :
457 : /************************************************************************/
458 : /* AlterFieldDefn() */
459 : /************************************************************************/
460 :
461 126 : OGRErr OGRMemLayer::AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nFlags )
462 : {
463 126 : if (!bUpdatable)
464 0 : return OGRERR_FAILURE;
465 :
466 126 : if (iField < 0 || iField >= poFeatureDefn->GetFieldCount())
467 : {
468 : CPLError( CE_Failure, CPLE_NotSupported,
469 4 : "Invalid field index");
470 4 : return OGRERR_FAILURE;
471 : }
472 :
473 122 : OGRFieldDefn* poFieldDefn = poFeatureDefn->GetFieldDefn(iField);
474 :
475 122 : if ((nFlags & ALTER_TYPE_FLAG) &&
476 : poFieldDefn->GetType() != poNewFieldDefn->GetType())
477 : {
478 104 : if ((poNewFieldDefn->GetType() == OFTDate ||
479 : poNewFieldDefn->GetType() == OFTTime ||
480 : poNewFieldDefn->GetType() == OFTDateTime) &&
481 : (poFieldDefn->GetType() == OFTDate ||
482 : poFieldDefn->GetType() == OFTTime ||
483 : poFieldDefn->GetType() == OFTDateTime))
484 : {
485 : /* do nothing on features */
486 : }
487 82 : else if (poNewFieldDefn->GetType() == OFTReal &&
488 : poFieldDefn->GetType() == OFTInteger)
489 : {
490 : /* -------------------------------------------------------------------- */
491 : /* Update all the internal features. Hopefully there aren't any */
492 : /* external features referring to our OGRFeatureDefn! */
493 : /* -------------------------------------------------------------------- */
494 264 : for( int i = 0; i < nMaxFeatureCount; i++ )
495 : {
496 240 : if( papoFeatures[i] == NULL )
497 216 : continue;
498 :
499 24 : OGRField* poFieldRaw = papoFeatures[i]->GetRawFieldRef(iField);
500 24 : if( papoFeatures[i]->IsFieldSet(iField) )
501 : {
502 24 : poFieldRaw->Real = poFieldRaw->Integer;
503 : }
504 : }
505 : }
506 : else
507 : {
508 58 : if (poNewFieldDefn->GetType() != OFTString)
509 : {
510 : CPLError( CE_Failure, CPLE_NotSupported,
511 0 : "Can only convert from OFTInteger to OFTReal, or from anything to OFTString");
512 0 : return OGRERR_FAILURE;
513 : }
514 :
515 : /* -------------------------------------------------------------------- */
516 : /* Update all the internal features. Hopefully there aren't any */
517 : /* external features referring to our OGRFeatureDefn! */
518 : /* -------------------------------------------------------------------- */
519 1198 : for( int i = 0; i < nMaxFeatureCount; i++ )
520 : {
521 1140 : if( papoFeatures[i] == NULL )
522 722 : continue;
523 :
524 418 : OGRField* poFieldRaw = papoFeatures[i]->GetRawFieldRef(iField);
525 418 : if( papoFeatures[i]->IsFieldSet(iField) )
526 : {
527 38 : char* pszVal = CPLStrdup(papoFeatures[i]->GetFieldAsString(iField));
528 :
529 : /* Little trick to unallocate the field */
530 : OGRField sField;
531 38 : sField.Set.nMarker1 = OGRUnsetMarker;
532 38 : sField.Set.nMarker2 = OGRUnsetMarker;
533 38 : papoFeatures[i]->SetField(iField, &sField);
534 :
535 38 : poFieldRaw->String = pszVal;
536 : }
537 : }
538 : }
539 :
540 104 : poFieldDefn->SetType(poNewFieldDefn->GetType());
541 : }
542 :
543 122 : if (nFlags & ALTER_NAME_FLAG)
544 18 : poFieldDefn->SetName(poNewFieldDefn->GetNameRef());
545 122 : if (nFlags & ALTER_WIDTH_PRECISION_FLAG)
546 : {
547 22 : poFieldDefn->SetWidth(poNewFieldDefn->GetWidth());
548 22 : poFieldDefn->SetPrecision(poNewFieldDefn->GetPrecision());
549 : }
550 :
551 122 : return OGRERR_NONE;
552 : }
553 :
554 : /************************************************************************/
555 : /* GetSpatialRef() */
556 : /************************************************************************/
557 :
558 768 : OGRSpatialReference *OGRMemLayer::GetSpatialRef()
559 :
560 : {
561 768 : return poSRS;
562 : }
|