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