1 : /******************************************************************************
2 : * $Id: ogrmemlayer.cpp 17807 2009-10-13 18:18:09Z 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 :
33 : CPL_CVSID("$Id: ogrmemlayer.cpp 17807 2009-10-13 18:18:09Z rouault $");
34 :
35 : /************************************************************************/
36 : /* OGRMemLayer() */
37 : /************************************************************************/
38 :
39 12 : OGRMemLayer::OGRMemLayer( const char * pszName, OGRSpatialReference *poSRSIn,
40 12 : OGRwkbGeometryType eReqType )
41 :
42 : {
43 12 : if( poSRSIn == NULL )
44 10 : poSRS = NULL;
45 : else
46 2 : poSRS = poSRSIn->Clone();
47 :
48 12 : iNextReadFID = 0;
49 12 : iNextCreateFID = 0;
50 :
51 12 : nFeatureCount = 0;
52 12 : nMaxFeatureCount = 0;
53 12 : papoFeatures = NULL;
54 :
55 12 : poFeatureDefn = new OGRFeatureDefn( pszName );
56 12 : poFeatureDefn->SetGeomType( eReqType );
57 12 : poFeatureDefn->Reference();
58 12 : }
59 :
60 : /************************************************************************/
61 : /* ~OGRMemLayer() */
62 : /************************************************************************/
63 :
64 24 : OGRMemLayer::~OGRMemLayer()
65 :
66 : {
67 12 : if( m_nFeaturesRead > 0 && poFeatureDefn != NULL )
68 : {
69 : CPLDebug( "Mem", "%d features read on layer '%s'.",
70 : (int) m_nFeaturesRead,
71 8 : poFeatureDefn->GetName() );
72 : }
73 :
74 312 : for( int i = 0; i < nMaxFeatureCount; i++ )
75 : {
76 300 : if( papoFeatures[i] != NULL )
77 185 : delete papoFeatures[i];
78 : }
79 12 : CPLFree( papoFeatures );
80 :
81 12 : if( poFeatureDefn )
82 12 : poFeatureDefn->Release();
83 :
84 12 : if( poSRS )
85 2 : poSRS->Release();
86 24 : }
87 :
88 : /************************************************************************/
89 : /* ResetReading() */
90 : /************************************************************************/
91 :
92 36 : void OGRMemLayer::ResetReading()
93 :
94 : {
95 36 : iNextReadFID = 0;
96 36 : }
97 :
98 : /************************************************************************/
99 : /* GetNextFeature() */
100 : /************************************************************************/
101 :
102 99 : OGRFeature *OGRMemLayer::GetNextFeature()
103 :
104 : {
105 594 : while( iNextReadFID < nMaxFeatureCount )
106 : {
107 484 : OGRFeature *poFeature = papoFeatures[iNextReadFID++];
108 :
109 484 : if( poFeature == NULL )
110 111 : continue;
111 :
112 373 : if( (m_poFilterGeom == NULL
113 : || FilterGeometry( poFeature->GetGeometryRef() ) )
114 : && (m_poAttrQuery == NULL
115 : || m_poAttrQuery->Evaluate( poFeature ) ) )
116 : {
117 88 : m_nFeaturesRead++;
118 88 : return poFeature->Clone();
119 : }
120 : }
121 :
122 11 : return NULL;
123 : }
124 :
125 : /************************************************************************/
126 : /* SetNextByIndex() */
127 : /************************************************************************/
128 :
129 0 : OGRErr OGRMemLayer::SetNextByIndex( long nIndex )
130 :
131 : {
132 0 : if( m_poFilterGeom != NULL || m_poAttrQuery != NULL )
133 0 : return OGRLayer::SetNextByIndex( nIndex );
134 :
135 0 : if (iNextReadFID < 0 || iNextReadFID >= nMaxFeatureCount)
136 0 : return OGRERR_FAILURE;
137 :
138 0 : iNextReadFID = nIndex;
139 :
140 0 : return OGRERR_NONE;
141 : }
142 :
143 : /************************************************************************/
144 : /* GetFeature() */
145 : /************************************************************************/
146 :
147 3 : OGRFeature *OGRMemLayer::GetFeature( long nFeatureId )
148 :
149 : {
150 3 : if( nFeatureId < 0 || nFeatureId >= nMaxFeatureCount )
151 0 : return NULL;
152 3 : else if( papoFeatures[nFeatureId] == NULL )
153 1 : return NULL;
154 : else
155 2 : return papoFeatures[nFeatureId]->Clone();
156 : }
157 :
158 : /************************************************************************/
159 : /* SetFeature() */
160 : /************************************************************************/
161 :
162 188 : OGRErr OGRMemLayer::SetFeature( OGRFeature *poFeature )
163 :
164 : {
165 188 : if( poFeature == NULL )
166 0 : return OGRERR_FAILURE;
167 :
168 188 : if( poFeature->GetFID() == OGRNullFID )
169 : {
170 542 : while( iNextCreateFID < nMaxFeatureCount
171 170 : && papoFeatures[iNextCreateFID] != NULL )
172 0 : iNextCreateFID++;
173 186 : poFeature->SetFID( iNextCreateFID++ );
174 : }
175 2 : else if ( poFeature->GetFID() < OGRNullFID )
176 : {
177 : CPLError(CE_Failure, CPLE_NotSupported,
178 0 : "negative FID are not supported");
179 0 : return OGRERR_FAILURE;
180 : }
181 :
182 188 : if( poFeature->GetFID() >= nMaxFeatureCount )
183 : {
184 16 : int nNewCount = MAX(2*nMaxFeatureCount+10, poFeature->GetFID() + 1 );
185 :
186 : OGRFeature** papoNewFeatures = (OGRFeature **)
187 16 : VSIRealloc( papoFeatures, sizeof(OGRFeature *) * nNewCount);
188 16 : if (papoNewFeatures == NULL)
189 : {
190 : CPLError(CE_Failure, CPLE_OutOfMemory,
191 0 : "Cannot allocate array of %d elements", nNewCount);
192 0 : return OGRERR_FAILURE;
193 : }
194 16 : papoFeatures = papoNewFeatures;
195 : memset( papoFeatures + nMaxFeatureCount, 0,
196 16 : sizeof(OGRFeature *) * (nNewCount - nMaxFeatureCount) );
197 16 : nMaxFeatureCount = nNewCount;
198 : }
199 :
200 188 : if( papoFeatures[poFeature->GetFID()] != NULL )
201 : {
202 2 : delete papoFeatures[poFeature->GetFID()];
203 2 : papoFeatures[poFeature->GetFID()] = NULL;
204 2 : nFeatureCount--;
205 : }
206 :
207 188 : papoFeatures[poFeature->GetFID()] = poFeature->Clone();
208 188 : nFeatureCount++;
209 :
210 188 : return OGRERR_NONE;
211 : }
212 :
213 : /************************************************************************/
214 : /* CreateFeature() */
215 : /************************************************************************/
216 :
217 186 : OGRErr OGRMemLayer::CreateFeature( OGRFeature *poFeature )
218 :
219 : {
220 186 : if( poFeature->GetFID() != OGRNullFID
221 : && poFeature->GetFID() >= 0
222 : && poFeature->GetFID() < nMaxFeatureCount )
223 : {
224 6 : if( papoFeatures[poFeature->GetFID()] != NULL )
225 6 : poFeature->SetFID( OGRNullFID );
226 : }
227 :
228 186 : if( poFeature->GetFID() > 10000000 )
229 0 : poFeature->SetFID( OGRNullFID );
230 :
231 186 : return SetFeature( poFeature );
232 : }
233 :
234 : /************************************************************************/
235 : /* DeleteFeature() */
236 : /************************************************************************/
237 :
238 1 : OGRErr OGRMemLayer::DeleteFeature( long nFID )
239 :
240 : {
241 2 : if( nFID < 0 || nFID >= nMaxFeatureCount
242 1 : || papoFeatures[nFID] == NULL )
243 : {
244 0 : return OGRERR_FAILURE;
245 : }
246 : else
247 : {
248 1 : delete papoFeatures[nFID];
249 1 : papoFeatures[nFID] = NULL;
250 1 : nFeatureCount--;
251 1 : return OGRERR_NONE;
252 : }
253 : }
254 :
255 : /************************************************************************/
256 : /* GetFeatureCount() */
257 : /* */
258 : /* If a spatial filter is in effect, we turn control over to */
259 : /* the generic counter. Otherwise we return the total count. */
260 : /* Eventually we should consider implementing a more efficient */
261 : /* way of counting features matching a spatial query. */
262 : /************************************************************************/
263 :
264 9 : int OGRMemLayer::GetFeatureCount( int bForce )
265 :
266 : {
267 9 : if( m_poFilterGeom != NULL || m_poAttrQuery != NULL )
268 1 : return OGRLayer::GetFeatureCount( bForce );
269 : else
270 8 : return nFeatureCount;
271 : }
272 :
273 : /************************************************************************/
274 : /* TestCapability() */
275 : /************************************************************************/
276 :
277 4 : int OGRMemLayer::TestCapability( const char * pszCap )
278 :
279 : {
280 4 : if( EQUAL(pszCap,OLCRandomRead) )
281 0 : return TRUE;
282 :
283 4 : else if( EQUAL(pszCap,OLCSequentialWrite)
284 : || EQUAL(pszCap,OLCRandomWrite) )
285 3 : return TRUE;
286 :
287 1 : else if( EQUAL(pszCap,OLCFastFeatureCount) )
288 0 : return m_poFilterGeom == NULL && m_poAttrQuery == NULL;
289 :
290 1 : else if( EQUAL(pszCap,OLCFastSpatialFilter) )
291 0 : return FALSE;
292 :
293 1 : else if( EQUAL(pszCap,OLCDeleteFeature) )
294 1 : return TRUE;
295 :
296 0 : else if( EQUAL(pszCap,OLCCreateField) )
297 0 : return TRUE;
298 :
299 0 : else if( EQUAL(pszCap,OLCFastSetNextByIndex) )
300 0 : return m_poFilterGeom == NULL && m_poAttrQuery == NULL;
301 :
302 : else
303 0 : return FALSE;
304 : }
305 :
306 : /************************************************************************/
307 : /* CreateField() */
308 : /************************************************************************/
309 :
310 14 : OGRErr OGRMemLayer::CreateField( OGRFieldDefn *poField, int bApproxOK )
311 :
312 : {
313 : /* -------------------------------------------------------------------- */
314 : /* simple case, no features exist yet. */
315 : /* -------------------------------------------------------------------- */
316 14 : if( nFeatureCount == 0 )
317 : {
318 13 : poFeatureDefn->AddFieldDefn( poField );
319 13 : return OGRERR_NONE;
320 : }
321 :
322 : /* -------------------------------------------------------------------- */
323 : /* Add field definition and setup remap definition. */
324 : /* -------------------------------------------------------------------- */
325 : int *panRemap;
326 : int i;
327 :
328 1 : poFeatureDefn->AddFieldDefn( poField );
329 :
330 1 : panRemap = (int *) CPLMalloc(sizeof(int) * poFeatureDefn->GetFieldCount());
331 6 : for( i = 0; i < poFeatureDefn->GetFieldCount(); i++ )
332 : {
333 5 : if( i < poFeatureDefn->GetFieldCount() - 1 )
334 4 : panRemap[i] = i;
335 : else
336 1 : panRemap[i] = -1;
337 : }
338 :
339 : /* -------------------------------------------------------------------- */
340 : /* Remap all the internal features. Hopefully there aren't any */
341 : /* external features referring to our OGRFeatureDefn! */
342 : /* -------------------------------------------------------------------- */
343 31 : for( i = 0; i < nMaxFeatureCount; i++ )
344 : {
345 30 : if( papoFeatures[i] != NULL )
346 17 : papoFeatures[i]->RemapFields( NULL, panRemap );
347 : }
348 :
349 1 : CPLFree( panRemap );
350 :
351 1 : return OGRERR_NONE;
352 : }
353 :
354 : /************************************************************************/
355 : /* GetSpatialRef() */
356 : /************************************************************************/
357 :
358 2 : OGRSpatialReference *OGRMemLayer::GetSpatialRef()
359 :
360 : {
361 2 : return poSRS;
362 : }
|