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