1 : /******************************************************************************
2 : * $Id: ogrreclayer.cpp 25185 2012-10-27 19:40:46Z rouault $
3 : *
4 : * Project: EPIInfo .REC Reader
5 : * Purpose: Implements OGRRECLayer 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_rec.h"
31 : #include "cpl_conv.h"
32 : #include "cpl_string.h"
33 :
34 : CPL_CVSID("$Id: ogrreclayer.cpp 25185 2012-10-27 19:40:46Z rouault $");
35 :
36 : /************************************************************************/
37 : /* OGRRECLayer() */
38 : /* */
39 : /* Note that the OGRRECLayer assumes ownership of the passed */
40 : /* file pointer. */
41 : /************************************************************************/
42 :
43 1 : OGRRECLayer::OGRRECLayer( const char *pszLayerNameIn,
44 1 : FILE * fp, int nFieldCountIn )
45 :
46 : {
47 1 : fpREC = fp;
48 1 : bIsValid = FALSE;
49 1 : nStartOfData = 0;
50 :
51 1 : nNextFID = 1;
52 :
53 1 : poFeatureDefn = new OGRFeatureDefn( pszLayerNameIn );
54 1 : poFeatureDefn->Reference();
55 :
56 1 : nFieldCount = 0;
57 1 : panFieldOffset = (int *) CPLCalloc(sizeof(int),nFieldCountIn);
58 1 : panFieldWidth = (int *) CPLCalloc(sizeof(int),nFieldCountIn);
59 :
60 : /* -------------------------------------------------------------------- */
61 : /* Read field definition lines. */
62 : /* -------------------------------------------------------------------- */
63 : int iField;
64 :
65 1 : for( nFieldCount=0, iField = 0; iField < nFieldCountIn; iField++ )
66 : {
67 2 : const char *pszLine = CPLReadLine( fp );
68 : int nTypeCode;
69 2 : OGRFieldType eFType = OFTString;
70 :
71 2 : if( pszLine == NULL )
72 0 : return;
73 :
74 2 : if( strlen(pszLine) < 44 )
75 0 : return;
76 :
77 : // Extract field width.
78 2 : panFieldWidth[nFieldCount] = atoi( RECGetField( pszLine, 37, 4 ) );
79 2 : if( panFieldWidth[nFieldCount] < 0 )
80 0 : return;
81 :
82 : // Is this an real, integer or string field? Default to string.
83 2 : nTypeCode = atoi(RECGetField(pszLine,33,4));
84 2 : if( nTypeCode == 12 )
85 0 : eFType = OFTInteger;
86 2 : else if( nTypeCode > 100 && nTypeCode < 120 )
87 : {
88 0 : eFType = OFTReal;
89 : }
90 4 : else if( nTypeCode == 0 || nTypeCode == 6 || nTypeCode == 102 )
91 : {
92 2 : if( panFieldWidth[nFieldCount] < 3 )
93 2 : eFType = OFTInteger;
94 : else
95 0 : eFType = OFTReal;
96 : }
97 : else
98 0 : eFType = OFTString;
99 :
100 2 : OGRFieldDefn oField( RECGetField( pszLine, 2, 10 ), eFType );
101 :
102 : // Establish field offset.
103 2 : if( nFieldCount > 0 )
104 1 : panFieldOffset[nFieldCount]
105 1 : = panFieldOffset[nFieldCount-1] + panFieldWidth[nFieldCount-1];
106 :
107 2 : if( nTypeCode > 100 && nTypeCode < 120 )
108 : {
109 0 : oField.SetWidth( panFieldWidth[nFieldCount] );
110 0 : oField.SetPrecision( nTypeCode - 100 );
111 : }
112 2 : else if( eFType == OFTReal )
113 : {
114 0 : oField.SetWidth( panFieldWidth[nFieldCount]*2 );
115 0 : oField.SetPrecision( panFieldWidth[nFieldCount]-1 );
116 : }
117 : else
118 2 : oField.SetWidth( panFieldWidth[nFieldCount] );
119 :
120 : // Skip fields that are only screen labels.
121 2 : if( panFieldWidth[nFieldCount] == 0 )
122 0 : continue;
123 :
124 2 : poFeatureDefn->AddFieldDefn( &oField );
125 2 : nFieldCount++;
126 : }
127 :
128 1 : if( nFieldCount == 0 )
129 0 : return;
130 :
131 1 : nRecordLength = panFieldOffset[nFieldCount-1]+panFieldWidth[nFieldCount-1];
132 1 : bIsValid = TRUE;
133 :
134 1 : nStartOfData = VSIFTell( fp );
135 0 : }
136 :
137 : /************************************************************************/
138 : /* ~OGRRECLayer() */
139 : /************************************************************************/
140 :
141 1 : OGRRECLayer::~OGRRECLayer()
142 :
143 : {
144 1 : if( m_nFeaturesRead > 0 && poFeatureDefn != NULL )
145 : {
146 : CPLDebug( "REC", "%d features read on layer '%s'.",
147 : (int) m_nFeaturesRead,
148 1 : poFeatureDefn->GetName() );
149 : }
150 :
151 1 : if( fpREC != NULL )
152 1 : VSIFClose( fpREC );
153 :
154 1 : if( poFeatureDefn )
155 1 : poFeatureDefn->Release();
156 :
157 1 : CPLFree( panFieldOffset );
158 1 : CPLFree( panFieldWidth );
159 1 : }
160 :
161 : /************************************************************************/
162 : /* ResetReading() */
163 : /************************************************************************/
164 :
165 33 : void OGRRECLayer::ResetReading()
166 :
167 : {
168 33 : VSIFSeek( fpREC, nStartOfData, SEEK_SET );
169 33 : nNextFID = 1;
170 33 : }
171 :
172 : /************************************************************************/
173 : /* GetNextUnfilteredFeature() */
174 : /************************************************************************/
175 :
176 48 : OGRFeature * OGRRECLayer::GetNextUnfilteredFeature()
177 :
178 : {
179 : /* -------------------------------------------------------------------- */
180 : /* Read and assemble the source data record. */
181 : /* -------------------------------------------------------------------- */
182 48 : int nDataLen = 0;
183 48 : char *pszRecord = (char *) CPLMalloc(nRecordLength + 2 );
184 :
185 129 : while( nDataLen < nRecordLength )
186 : {
187 48 : const char *pszLine = CPLReadLine( fpREC );
188 : int iSegLen;
189 :
190 48 : if( pszLine == NULL )
191 : {
192 15 : CPLFree( pszRecord );
193 15 : return NULL;
194 : }
195 :
196 33 : if( *pszLine == 0 || *pszLine == 26 /* Cntl-Z - DOS EOF */ )
197 : {
198 0 : CPLFree( pszRecord );
199 0 : return NULL;
200 : }
201 :
202 : // If the end-of-line markers is '?' the record is deleted.
203 33 : iSegLen = strlen(pszLine);
204 33 : if( pszLine[iSegLen-1] == '?' )
205 : {
206 0 : pszRecord[0] = '\0';
207 0 : nDataLen = 0;
208 0 : continue;
209 : }
210 :
211 : // Strip off end-of-line '!' marker.
212 66 : if( pszLine[iSegLen-1] != '!'
213 33 : && pszLine[iSegLen-1] != '^' )
214 : {
215 : CPLError( CE_Failure, CPLE_AppDefined,
216 : "Apparent corrupt data line .. record FID=%d",
217 0 : nNextFID );
218 0 : CPLFree( pszRecord );
219 0 : return NULL;
220 : }
221 :
222 33 : iSegLen--;
223 33 : if( nDataLen + iSegLen > nRecordLength )
224 : {
225 : CPLError( CE_Failure, CPLE_AppDefined,
226 : "Too much data for record %d.",
227 0 : nNextFID );
228 0 : CPLFree( pszRecord );
229 0 : return NULL;
230 : }
231 :
232 33 : strncpy( pszRecord+nDataLen, pszLine, iSegLen );
233 33 : pszRecord[nDataLen+iSegLen] = '\0';
234 33 : nDataLen += iSegLen;
235 : }
236 :
237 : /* -------------------------------------------------------------------- */
238 : /* Create the OGR feature. */
239 : /* -------------------------------------------------------------------- */
240 : OGRFeature *poFeature;
241 :
242 33 : poFeature = new OGRFeature( poFeatureDefn );
243 :
244 : /* -------------------------------------------------------------------- */
245 : /* Set attributes for any indicated attribute records. */
246 : /* -------------------------------------------------------------------- */
247 : int iAttr;
248 :
249 99 : for( iAttr = 0; iAttr < nFieldCount; iAttr++)
250 : {
251 : const char *pszFieldText =
252 : RECGetField( pszRecord,
253 66 : panFieldOffset[iAttr] + 1,
254 132 : panFieldWidth[iAttr] );
255 :
256 66 : if( strlen(pszFieldText) != 0 )
257 66 : poFeature->SetField( iAttr, pszFieldText );
258 : }
259 :
260 : /* -------------------------------------------------------------------- */
261 : /* Translate the record id. */
262 : /* -------------------------------------------------------------------- */
263 33 : poFeature->SetFID( nNextFID++ );
264 33 : m_nFeaturesRead++;
265 :
266 33 : CPLFree( pszRecord );
267 :
268 33 : return poFeature;
269 : }
270 :
271 :
272 : /************************************************************************/
273 : /* GetNextFeature() */
274 : /************************************************************************/
275 :
276 43 : OGRFeature *OGRRECLayer::GetNextFeature()
277 :
278 : {
279 43 : OGRFeature *poFeature = NULL;
280 :
281 : /* -------------------------------------------------------------------- */
282 : /* Read features till we find one that satisfies our current */
283 : /* spatial criteria. */
284 : /* -------------------------------------------------------------------- */
285 5 : while( TRUE )
286 : {
287 48 : poFeature = GetNextUnfilteredFeature();
288 48 : if( poFeature == NULL )
289 15 : break;
290 :
291 33 : if( m_poAttrQuery == NULL || m_poAttrQuery->Evaluate( poFeature ) )
292 28 : break;
293 :
294 5 : delete poFeature;
295 : }
296 :
297 43 : return poFeature;
298 : }
299 :
300 : /************************************************************************/
301 : /* TestCapability() */
302 : /************************************************************************/
303 :
304 8 : int OGRRECLayer::TestCapability( const char * pszCap )
305 :
306 : {
307 8 : return FALSE;
308 : }
309 :
|